Simplest versus first thing that could possibly work

One of the core XP practices that resonated with me quite early on was the concept of simple design.  When I learned TDD, this practice was further refined with the concept of doing the “simplest thing that could possibly work”.  To make a test pass, I would code the simplest thing that could possibly work.  It takes quite a bit of discipline to adhere to this mantra of simplicity, fighting a constant urge to design something more complex than the problem at hand requires.

Browsing the XP wiki, you can find a lot of discussion of what exactly this means.  TDD calls for “Red, Green, Refactor”, which might lead you to wonder why you would need to refactor after doing the simplest thing that could possibly work.  It seems that the consensus formed around first performing the fewest steps, then refactoring to the fewest pieces or components.  But in our quest for simplicity, I notice a second, more subtle mistake: confusing the first thing that happens to work with the simplest thing that could possibly work.  If I choose the first thing that happens to work, my refactoring step often leads me merely to the simplest solution, but not the most elegant.

The difference between the two is easy to fix – it just requires thinking!  Thinking about possible solutions, different designs, vetting alternate paths to the goal.  This can be accomplished through pair programming, whiteboarding, and just about any exercise that requires us to think of at least two possible solutions before picking the winner.  I don’t necessarily see this happening with every possible solution, however.  But some of the most awkward designs I’ve created seem to stem from just picking the first thing that works, and not doing a little thinking.

Which is quite sad, as a little effort and investment in investigating multiple designs pays off many-fold in the long run.  Evolutionary design works best when we’re not stumbling in the dark, but making informed decisions with the most options as possible on the table.  If this sounds something like the idea of concurrent or set-based engineering, it should!  Except in this case, we perform it in the micro, at the point of every non-trivial design decision.  Simplicity is not automatic, and often comes from choosing the best design from a few options.  But we can’t be lazy about it, as taking just five minutes to think of a different approach can save man-hours (or days even) further down the road.

Defining and refining conventions