Why Encapsulation Simplifies Software
Ever wonder why you should use encapsulation? Sure, we're taught it in school. We love it in really great designs like Apple's measurement API. We may even be surprised just how well such code does its specific task. But are there specific, measurable reasons why encapsulation works? Reasons we can leverage to improve and simplify our own code?
Chunking
Let's start with an example from cognitive psychology (1: Hodent, 2018). Consider the sequence of 13 digits below. Since it is larger than the ~7 items our short term memory can usually handle, this list can be difficult to remember.
1 - 7 - 8 - 9 - 3 - 1 - 4 - 1 - 6 - 1 - 4 - 9 - 2
But if we group those numbers into the meaningful chunks 1789, 3.1416 and 1492 the list is significantly easier to remember. This is chunking, where information is retrieved more easily because it is already stored together in longer term memory. The implication is that problems require less cognitive resources when we use well encapsulated code. More complex problems would become unsolvable until repeated attempts build chunks in our memory. It could also be that poor encapsulation - a model that differs from an existing mental model - could actually make problems more difficult!
Here's a fun test. Find any interview coding question. You know, those small problems that are difficult mostly because of the time constraint. First try to solve the problem with the single method suggested by most coding sites. You know, that static method that includes every relevant property as a parameter to the method. These questions are specifically designed to include enough state to challenge your short term memory.
Now try the question again, but with a nicely encapsulated structure. Something relevant to the problem statement but also already familiar: a matrix, truck route, etc. Make most of the problem state private, and add high level methods to the structure. Suddenly the problem becomes simpler as more cognitive resources are freed up, and edge cases become easier to spot and solve.
Build Time and Complexity
This concept is best demonstrated by a public property in a growing Swift project. Any change to this property - type, name, etc. - could impact every single type in the same module. And so when you make such a change, the build must rebuild every single one of those types. You begin to feel this change in build time pretty quickly as your project grows.
I've seen this both in a new project and an older objective-c conversion. Both started with a single module and kept adding code. But with n-squared growth - where n is the number of public properties in the project - build time quickly became an issue with both projects. Those objective-c import statements suddenly seem less painful, when you are confronted with squeezing legacy code into modules.
领英推荐
So yeah, considering "n-squared where n is properties in the entire project", the answer is a little more serious than "make properties private by default". To achieve even linear let alone constant growth, more aggressive effort is required. Only the absolute minimum required properties should be public in each type. Even then, those types should be organized in modules, and only the bare minimum of types made public.
Change Size, Speed and Risk
Finally let's consider that 10 parameter method chain. You've probably seen one. Those 10 parameters are copied in every layer, from the UI to model to network and back. Consider how many files must be changed to add even just one parameter to that chain. Or worse, if we need to add another, similar method chain. A simple parameter object refactor could greatly reduce the change size in this system.
The requirements always change as our system grows and evolves. It is the responsibility of our design to make new changes as fast and reliable as possible. The fewer dependencies there are in our system - that is, the better the encapsulation - the less files that must be changed. My favourite part of the job is when that unexpected requirement comes out of left field and is actually trivial to implement because my design was so simple and loosely coupled.
It's less satisfying when we must admit that oops, the change will not be trivial. As they say, good decisions come from wisdom, but wisdom, well, that comes from bad decisions. Learn from the mistake and simplify your design. It will pay off when that next change comes down the pipeline - and in your next design.
Conclusion
We've dug a little deeper here into why encapsulation simplifies software design, development and maintenance. Encapsulation simplifies our mental model, improves build time, and reduces the size of maintenance changes. I encourage you to apply similar skepticism to other best practices. We may discover a better practice or at least a better understanding. Thanks for reading!
References
Freelance copywriter | 3X Content Manager | Former embedded developer
9 个月Nice article, Dave! The concept of chunking was cool to learn.