The Simplest Thing That Could Possibly Work

In April 2011 I attended the Agile Games 2011 Un-conference in Cambridge, MA.  Given it's proximity to MIT, I'd like to believe I came away smarter simply through osmosis, but time will tell. :)

On the first day after Luke Hohmann's keynote, I hummed and hawed about which Deep Dive session to attend.  While many of the games sessions sounded interesting, I kept coming back to Adam Sroka's Coding Dojo.  So, I decided to attend and write me some code!

The goal was to show how to use the dojo concept as a practice or teaching technique, and in our case the goal was to build a poker game using true TDD.  To get the groups up and running quickly, Adam suggested that we spend a little time simply creating the basics for the card game War, which would provide the foundation for the rest of the work we would do.

When we started, I witnessed for the umpteenth time something that seems to be really, really hard for software people to abandon... doing the Simplest Thing That Could Possibly Work.

This principle is something that I learned early in my XP days.  It goes hand in hand with TDD and says,
"Don't do any more than is required to make the currently failing test pass."
With the card game dojo, the group with whom I was working immediately started whiteboarding out the entire system with classes and methods, including some way to display the cards.  While that isn't necessarily bad, they were going way too far for what was needed at that particular time.

After about 15 minutes of trying to wrangle these designers, I asked them, "So, what's the first test?"  Crickets.  I asked, "What's the most fundamental thing we need to be able to do in order to implement this game?  What's the first test to start doing that?"  More crickets, followed by a return to the whiteboard.

Moss Collum, however, did get what I was asking and he & I simply sat down at his laptop.  We figured that the most fundamental part of any card game is to be able to compare the value of two hands against each other, which means being able to compare two cards against each other.

So, using ping-pong pairing, Moss wrote the first test which was something like:
I wrote the code to make that test pass, but to do so I only needed to implement the value of the card.  The test had no concept of the card's suit being valuable!  So, once the test pass we refactored just the test name to something like:
Moss and I gave out a cheer when our first test was passing, which caught the attention of the folks at the whiteboard.  I wrote another test, and Moss wrote the bare minimum code to make the test pass, then refactored.  He wrote another test, and we invited another group member to sit down and make it pass.  Rinse and repeat.  Over time we built out the game to the point of detecting specific poker hand patterns.

It was a constant struggle, though, to keep people from implementing more functionality than the current test required.  Several times I heard, "But we're going to need this anyway!"  Maybe.  Maybe not.  It's in that speculation that the danger in over-thinking and over-engineering a solution lies.  If you're speculating, some of that speculation is bound to be incorrect.

This struggle isn't limited to coding dojos at a Games conference - I hear it constantly when coaching teams.  After all, they're different - they have all sorts of reasons to write complex code!  Well, their problem domain may be complex, but that doesn't mean that their code has to be as well.

Don't confuse Simple with Doesn't Work in the Real World, either.  If you're writing a quick utility application to crunch some data for yourself, you may not need to worry about scalability.  If you're writing code for telecom switching equipment, you certainly do need to deal with a different list of "-ilities" that need to be considered.  However, at the core the code should be as simple as is required to solve the problem at hand.  Test-Driven Development is an excellent way to do this, since the tests focus the developers on writing just enough code to solve that problem.

By sticking to the mantra of Do the Simplest Thing That Could Possibly Work, you will avoid or at least certainly delay the type of code bloat that results in Big Balls of Mud.  You will also avoid a ton of time spent on code that wasn't needed, not to mention time saved maintaining the code in the future.

Of course, that isn't a problem for you... you have plenty of spare time on your hands, right?