Often as a software engineer my team is faced with a choice between two or more options for how to solve a particular problem. What will ultimately end up being the correct choice depends on information we may not have at the time we have to choose an option.
The arguments for and against the various alternatives are usually made along the lines of complexity, flexibility, and time to develop. The simpler solutions take less time to develop, but will be less flexible in the face of potential changes. More flexible solutions are great, except that they take more time to develop. If the expected changes never happen, the extra time to develop the feature is wasted effort.
Since we are not omniscient, we cannot know a priori which design alternative will ultimately be correct. Because we need to make a choice right now, we need some kind of guiding principle to help make a decision.
This idea was recently expressed in a Team Leadership Google Group I read by Charlie Poole on this thread on pair programming:
If I saw a pair debating the best approach for more than three minutes I’d
probably ask them to decide which approach to try first. This leads to useful
considerations, like "Will it be easier to refactor from A to B, or from B to A, if we
change our minds later?" When reminded that the goal is to decide what to do in the
next 5 minutes, not what is "best" in some absolute sense, most pairs move on…
When I talked about this post with my girlfriend Emily, she said “When hanging a picture, it’s better to drill a pilot hole sized to the screw first. If you drill into a stud, no harm done. If you start with a hole sized for an anchor and drill into a stud, you have patching, sanding, and painting to do.” (A stud finder helps in these situations too, but you get the idea.) I’m sure you all have similar examples.
This idea integrates nicely with the principles of YAGNI and Last Responsible Moment. Software, by nature, will change. We are unable to predict how and in what way it will change. Well designed software is not over-engineered software. If we tried to write software that would be malleable in the face of any kind of change, ever, we would never finish. There are simply too many possibilities. It would be an expensive waste of time. The alternative is not to write software that cannot change (otherwise it would no longer be soft-ware), but to make intelligent choices about which axes of change we will support.
In the face of two similar alternatives, we should choose the one that will be easier to change. This will usually be the one that commits the fewest resources, imposes the weakest restrictions, and takes the least time.