“… it is simplicity that is difficult to make.” – Bertholdt Brecht
Developers are creative people; we love to build stuff. We all spend our days, and sometimes our nights too, building stuff. Building stuff is what we do best, often we just can’t help ourselves.
And therein lies the problem. Let me say it again:
“often we just can’t help ourselves.”
How often have you seen code-bases where developers have been let loose to just build “stuff”? This can manifest itself in any number of ways; huge amounts of abstraction, nightmarish levels of inheritance or code which has been made ridiculously generic in the name of re-use, to name but a few.
Blindly following “good software engineering principles”1 can lead to some horribly unreadable and unmaintainable code. Take the “Don’t Repeat Yourself” principle for example. We all know that good code is DRY, right? But the key to this principle is the avoidance of repetition. The clue is in the name; if there is no repetition, it doesn’t apply. Trust me, you will know when a piece of code needs to be DRY – it will happen just at the point you are going to repeat yourself.
Remember, it is called “refactor”, not “pre-factor”.
Let’s spend a moment thinking about another prime cause of unreadable and unmaintainable code – unnecessary implementation of design patterns. Now don’t get me wrong, design patterns can be very useful aids to software development. But they are just that, an aid. Patterns should be implemented when a need for them has been positively identified, not because someone once told you, “that’s the way it should be done”.
In fact, take one of the most common design patterns – Inversion of Control. Overuse of IoC/Dependency Injection can lead to code which is horrendously difficult to maintain and debug. .NET developers who have encountered this pattern will no doubt have come across this, infamously hard to debug, little beauty:
No parameterless constructor defined for this object.
Many of you will have used, or at least be aware of StructureMap. It is a well-regarded “Dependency Injection / Inversion of Control tool for .Net that can be used to improve the architectural qualities of an object oriented system by reducing the mechanical costs of good design techniques”. However, a brief scan of the StructureMap home page itself reveals some useful guidance:
Do not use StructureMap if an application or process requires little flexibility. The abstraction and indirection afforded by StructureMap is unnecessary and even harmful in simpler systems or processes.
DI should stand for Dependency Injection, not Developer Indirection.
I am sure we are not alone. Imagine giving a building architect the following brief: “I just got a great new lawnmower. I would like you to design me a great building to go with it”. That is it; no budget, no use cases, no specification of building materials, no sort of high-level design, no other requirements. If the architect constructed the building in the same way that much software is built you could easily end up with something like this:
There can be no doubting the skill of the architect. After all, it is a beautiful, classic design, built from the finest materials by master craftsmen. However, it is slightly over-the-top if the “great building” you wanted was one in which you simply intended to store your lawnmower and nothing more. The optimal design would probably look more like this:
The architect’s design, while it would amply fulfil the function, would be immeasurably more complex, take much longer to construct, be harder to maintain, take up way more room and be vastly more expensive.
So who’s fault would this be? Is it your fault, or the fault of the architect? Well, the simple answer is both – you for not stipulating sufficient constraints and the architect for building way too much stuff. But, in the same way as software developers, architects just love to build stuff.
So how does this apply to software projects? It is imperative that the people responsible for the solution design provide a clear definition of requirements and constraints, and the people responsible for the implementation of the design (i.e. the software developers) need to learn to build sheds where a shed is all that is required.
Simply put: YAGNAC – You Ain’t Gonna Need A Cathedral.
Reuse Myth – can you afford reusable code? – Allan Kelly
Cargo cult programming – Wikipedia
Why I Hate Frameworks – Joel Spolsky
1 to be read in a high-pitched nasally whine