I’ve been thinking about this paradigm of navigability and knowability in software for a couple weeks, and thought it might be interesting or helpful to others, so here goes.
Consider 2 towns. The first, Tinyton, is a town of 150 residents, with 5 windy streets that cross back and forth over each other. It has a general store and a diner. The second, Bigville is a town of 15,000. It has a design pattern of gridded streets, with a convention of numbering them, and a few dozen businesses scattered around the town.
Tinyton is knowable. It’s small enough that it is reasonably possible to know every place in the town, and how to get there from anywhere else, at least with a few well known landmarks. However, it is not very navigable. If you’re not already familiar with it, you will get lost a lot.
Bigville on the other hand is navigable, though less knowable. It is unlikely that anyone can learn every place of note in the town, but because the streets are predictable and meaningfully labeled, as long as you know where you are and where you mean to go, you can find your way pretty easily. Within Bigville, neighborhoods will be knowable, but not likely the whole town.
As with urban planning, design patterns and conventions in software should also serve navigability. They should make it easy to find your way around a codebase, and make sense of what your looking at in any particular piece of code you maybe looking at. Architecture should explain why things are where they within a system, but not really what they are or what they do.
Going back to the town analogy, let’s drill down a little farther here and imagine within the Bigville there’s a store called Mike’s Deli. Mike was a plumber, so his deli sells plumbing supplies and work clothes, then has a small deli counter in the back that makes sandwiches. Within the context of his experience, this abstraction provides a useful and meaningful encapsulation, but to others, its highly specialized and poorly scoped, and the name is an obfuscation.
Mike also runs his store out of his garage, so it doesn’t conform to the patterns and conventions of the town. This makes it harder to use as well as being hard to understand, as it requires special knowledge and handling compared to everything else in the town.
Again translating to software, it’s important to remember that while undeniably valuable, encapsulation and abstraction are inherently forms of obfuscation that increase the cognitive load of working with a system. Additionally, they introduce opportunity to violate architecture. Put another way, when things get DRY, they get lighter, but also often harder and more brittle. Try to make sure your encapsulations minimize cost to benefit given this.
Also, when considering abstractions and encapsulations, try to generalize them as much as is reasonable. The less local context a visitor to your neighborhood of the codebase needs to make sense of things, the better.
I hope the navigability/knowability paradigm is a useful framing for others when thinking about software they’re building, and that I’ve done something to help illuminate the cost calculus of encapsulation. In the least, they seem useful for framing code review conversations.