On Minimum-Change Programming
Think about how easy it is to make a change to a shiny new, clean, well-designed system. Now think about how hard it is to make changes to a fifteen-year old system that has been under constant maintenance. Why the difference?
Once upon a time, your fifteen-year-old monster was a shiny new system with a clean design. (At least, the people who built it probably thought it was a clean design.) So the question can be rephrased as: How did such a cute baby grow up to become such an obnoxious teenager? The answer: one change at a time.
When faced with a maintenance task, most people look for the easiest way to make the change. This is frequently dominated by internal process considerations like changing the smallest number of source files. Need to get an additional piece of data from here to there? You can either:
- Add add an additional parameter to all of the interfaces between here and there, updating .idl files, .h files and .cpp files. Change all of the routines between here and there to propagate the additional parameter. Or,
- Over here, stuff it into a global variable, and over there pull it out of the global, thus changing here and there, but nothing in between.
Most of the time, people choose the second. It's easy, and it gets the job done. Unfortunately, it's short-sighted. Every time you do this, the code base gets more complex. After several of these, you can't find the original clean design any more. Because of this, each subsequent change gets harder and harder, until you can't change anything without breaking something else.
Nevertheless, people persist in doing this. I've even seen check-in checklist forms that ask "Is this the smallest possible change?" as if that were a good thing. It's not.
So, what should we do? My maxim is:
When you're done, the code should look like you knew what you were doing when you started, whether you did or not.
In other words, when making a change, change as much as necessary to make it look like the system was designed from the start with the new requirement. If you do this, the first few changes take more time than they would otherwise. But unlike the other approach, the difficulty of changes does not increase with time.
The other problem, unfortunately, is that this is nearly impossible to do if your starting point is already a mess. This means that it becomes extremely important to resist the urge for a quick fix when the code is new, because code cleanliness is like virginity: once you've lost it, you don't get it back. To paraphrase Nancy Reagan:
Minimum-Change Programming? Just say NO.