Building systems like a tailor made suit
There seems to be an increasing trend for people building systems to ensure they meet current needs but then take that even further with customising them to fit just so. Or sometimes it is expressed as a refusal to consider future needs unless those are clearly expressed and the need for them is well established. Maybe this is an old trend from mainframe days that is going through a resurgence.
Here are some examples of what I mean:
- In software just writing code that does what is needed now without the hooks for what might come later.
- In hardware just configuring the capacity that is needed now without planning for future growth. (As an aside, the thing I find most irritating here is cutting cables to exactly the right length).
To me, almost everything I design must have an virtually obsessive degree of future-proofing built into it. Over the years I’ve built up a whole set of techniques to minimise the impact of this need, so that I get the future proofing I want, but without hassle.
Maybe some people just don’t know how to do that and so they avoid building in the future proofing as they can only see it adding complexity and cost?
I’m fairly convinced that my approach has two significant benefits:
- The first and most obvious is that it enables later change to happen much quicker and with much less difficulty than otherwise. Of course that relies on the nature of the future proofing work that was done originally, but then that is the skill that needs to be learnt.
- The second and potentially more contestable is that designing with future in mind actually produces better design now. It forces me down the road of making things generic, designing distinct interfaces or protocols and, most importantly, building the whole design around a conceptual framework.
This last point about the conceptual framework is critical to the understanding of any system. So long as you understand that everything fits in a conceptual framework and know what that is then you can far easier extrapolate your understanding to areas of detail that you don’t know, than otherwise. In other words, it is so much easier to take a sensible guess. It is also so much easier to understand how you would extend it.
The counter-argument to my whole proposition here is that modern technology and modern methodology make changing systems so much easier than before. For example, with virtualisation tools a server or disk volume can be moved and resized with a single click. Or, with modern IDEs, software can be re-factored with a single command.
However, both of those would be even faster, or perhaps even unnecessary if the design was done right in the first place.
I have to reply to this, since you are insulting my religion! ;-)
This presupposes that adding hook code early on is cheaper than adding hook code when you actually need it. Suppose that was not the case and that the cost was the same. In that scenario you’d be better off waiting because:
1) If it turned out you never needed the hooks you would have saved the wasted effort and added complexity of putting them in.
2) If you put them in when you needed them you’d have more information about the problem in hand and be more likely to put the _right_ hooks in place.
I would go so far as to suggest that it is worth waiting even if it is slightly more expensive to add the hooks later. That’s because adding the hooks in early adds hidden costs. The code is more complex which slows down all development. The other argument is an economic one. Consider work being done as an investment and the functionality delivered as the return on that investment. If you think of it like that then obviously you want to invest in areas that will quickly start giving returns. Adding hooks will take a long time to yield any return, investment that could have been made in areas that would yield returns quicker.
I haven’t even mentioned what happens if the hook code is not quite what is needed when you actually come to use it. In my experience this sort of code almost always needs changing to some degree at the point it comes to be used…
So the question is, what are the relative costs? Well the traditional thinking is that the ‘cost of change’ curve is exponential. So that making changes up front is much cheaper than making them later. That would blow everything I’ve said out of the water. However, there is growing evidence that using agile techniques can make that curve much flatter.
Scott Ambler talks about the cost of change curve here:
http://www.ambysoft.com/essays/whyAgileWorksFeedback.html
Martin Fowler talks about evolutionary vs up front design here:
http://www.martinfowler.com/articles/designDead.html
It is simply Waterfall against agile methodologies, surely. Waterfall says design everything you think you will ever need first then build, agile says design what you know you need now, build it, then see if you need anything else.
First, it’s not waterfall since I’m not talking about designing everything in advance. Only about preparing for future change.
Second, ‘hooks’ was a poor choice of word. Good design is about things like a coherent conceptual framework (aka domain driven design), clear interfaces and reusable code. My contention is that these can be done much better with forethought.
This forethought is basically just an extension of the pattern matching that all programmers do. This is an iterative cycle, where each iteration sees specific code sucked up and rewritten as generic code. My contention is that this practice should not stop when the current work is done but continue to a natural end point.
Another way of putting this is basically OO design. It is obviously far simpler to write basic code than to think in terms of advanced design patterns. But those patterns can allow changes far more easily than the simpler code.
Arrogant though it might sound, I think that experience is what makes these decisions likely to provide future benefit. But if you don’t try then that experience will be very slow in coming.
Finally, I think the cost of unplanned (or at least unprepared) later change is far more than most people imagine. It is not just the cost of the code, but also the data restructuring, the deployment etc. All of these can be mitigated to some extent by decision made before the change is known about.
Surely Y2K is a prime example of this.
And, how about the USofA penchant for allowing only one middle initial in most of the forms?