Abstraction - Finding The Balance
Coding towards abstractions rather than concrete implementation allows us to achieve loose coupling and generalization. However, abstractions do come at a cost and are often the subject of over-use.
“All problems in computer science can be solved by another level of indirection, except for the problem of too many layers of indirection.” – David J. Wheeler
Lack of abstractness is harmful as it indicates tightly coupled implementations, such implementations are brittle and costly to modify as often required changes are not isolated rather they ripple across the entire code base, this makes it very time-consuming to make changes and bugs are likely to emerge as a result. The more areas that are required to change the more it is likely for stability to be compromised.
Too many abstractions on the other hand are also harmful as abstractions introduce complexity by blurring out relationships between components making it more difficult for developers to utilize existing abstractions. This not only places cognitive load on humans reading code but can also impact performance by resolving indirection at runtime.
Therefore either extremes are harmful and it is best to find the balance, however, this is easier said than done, how would one know how many abstractions are too little or too many?
Thankfully, Robert Martin (Uncle Bob) devised a metric that can guide us to achieve balance.
The Distance from the Main Sequence equation allows us to visualize the relationship between abstractness and instability on a graph and it provides us with an idealized line, the closer our calculated figure plots to the idealized line the more balanced our implementation is.
If the calculated distance from the main sequence is plotted below the idealized line then this indicates a lack of abstractions, which makes it painful to make a change. While a point plotted above the line indicates that too many abstractions exist to make code useful.
You can read further about this in the book “Agile software development: principles, patterns, and practices.” by Robert C. Martin.
There can be other non-mathematical approaches to determine if an abstraction is called for such as the YAGNI principle.
The YAGNI Principle – An acronym based on the mantra “You Aint Gonna Need It” from the teachings of extreme programming, adhering to this principle allows developers to concentrate on what is required now rather than future perceptions which may.
Our future perceptions may wildly differ from the realities of the future, and building upon such perceptions prematurely may result in redundant/useless code that we have incurred the costs of the building.
Utilise domain knowledge - combining domain and technical knowledge will allow for distinguishing between genuine and perceived change, this distinction aids in determining whether abstraction is beneficial or not.
TDD Practices, can also help prevent unnecessary layers of indirection, as the bare minimum of code is written to pass a test, where the tests themselves are based on genuine requirements.
Remember, simply applying concepts to implementations does not make one a good software engineer, it is rather applying them when suitable; always be in a position where you can technically justify your implementation.
“Knowing concepts like abstraction, inheritance, and polymorphism do not make you a good object-oriented designer. A design guru thinks about how to create flexible designs that are maintainable and that can cope with change.” – Head First Design Patterns
Follow me for more software engineering related content.