Good design comes at a price, and it is important to understand these costs if we seek to build and maintain well designed code.
What are the Costs?
Up-Front Design Costs
Elegant code usually takes longer to create than spaghetti code.
As time goes by, good designs tend to rot. It can take considerable effort to maintain good design.
The counter to this is that poorly designed code becomes increasingly difficult to maintain, reducing its value and the value that can be added to it.
Increased Cost of Grokking a Code Base
The smaller your modules, the more there are and the higher your levels of abstraction. But more layers in your code mean that new developers will have a harder time understanding your code base.
In addition, a good design often maps onto a business domain. As a result, a developer may need deep domain knowledge in order to understand the reasoning behind many of the design decisions t
hat have been taken. It takes time and effort (ie. investment) for developers to gain this knowledge.Of course, developers are generally happier working on clean, well designed code, and happy are less likely to change jobs. Nevertheless, this can be a considerable cost to some organisations.
Higher Levels of Abstraction Lead to Slower Code
In general, the more modules you have, the higher the cost of those modules communicating with each other, the slower your code will run. Big balls of mud are often fast.
Of course, not all code needs to be especially fast. Moreover, well designed code is easier to optimize. Furthermore, it can be cheaper to add better hardware than reduce developer productivity: developer time is usually more expensive than CPU cycles.
Finally, good design often does involve more abstraction… but not always.
Better Design Results in More Lines of Code
Many languages require significant amounts of “boiler plate” (standard code) in the header and footer of each module, typically indicating such things as the module’s scope, namespace and name.
Better design often calls for more descriptive names, which are often longer than poorly thought through names.
It is arguable that “lines of code” is a poor measure of developer productivity, but even so, each additional character is a codebase has a cost associated with it.
Is Good Design Worth the Cost?
In my view, not always. I believe that the purpose of design is to maximise value delivered by a solution over the lifetime of a problem. So, if a solution is only intended to be used once, never changed, used by a single user and very short and simple then there is little to be gained by putting too much time into making its code base perfect. On the other hand, if a solution is intended to be with an organisation for any length of time, then overall costs can be reduced if the principles of good design are applied.
A common principle of good design is to avoid repetition, and this often involves increasing abstraction. I have often witnessed a pattern amongst developers, according to their experience:
- Novice developers apply little abstraction
- More experienced tend towards over-abstraction (using, for example, all the design patterns they can think of on every project)
- The true expert will apply appropriate, pragmatic levels of abstraction.