Don’t Abstractions Complicate Things?
During a code review of a highly modular system, I was asked the question of whether the necessary abstractions to realise such a system weren’t harmful since they make the system harder to understand than a highly concrete system. At the time, I gave an answer that left me dissatisfied. I also realised later on that the question is worth pondering in more detail. Hence today’s blog post.
It’s a good question—abstract systems can be more difficult to understand than concrete systems. I’ve written on the Cost of Abstraction before.
Highly concrete systems, where object references are programmed only in concrete terms, have their advantages—in principle, it’s easier for us programmers to follow the exact behaviour. For example, when variables are called
sqlServerDataAccess, we concretely know what we are dealing with.
sqlServerDataAccess, highlight the problem that accompanies such a high degree of concreteness: What if we wanted to work with another bank or a different database? It seems like we’ve painted ourselves into a corner. More abstract yet extensible variables
dataAccess will leave us with more wriggle room to extend the program without, hopefully, having to change the code—see the Open-Closed Principle.
However, there is another sticking point with highly concrete systems: Their very concreteness makes them difficult to partition. Concrete programs often end up being a monolithic mess. To understand a highly concrete system in part means understanding it in its entirety.
In this picture of a highly concrete system, the parts, represented by the little black boxes, can only be understood as a working whole. The system is difficult to break up into logical modules and components.
In contrast, a more abstract system is easier to decompose into coherent, loosely coupled parts. We can learn the behaviour of a component with fewer references to other components.
In the illustration below of a pluggable, modular, and more abstract system, only the behaviour of the boxes immediately inside a container box needs to be understood to make local sense. Boxes far removed from one another are independent—changes in one’s behaviour does not affect the other one.
In conclusion, abstraction has a cost, making it more difficult for programmers to understand a system. However, this cost pales in comparison to highly concrete systems, which, ultimately, are more difficult to understand and change.