Yesterday at AltNetUK Openspace Coding Days we repeated the TDD as if you meant it exercise, originally organised by Keith Braithwaite at the Software Craftsmanship 2009 conference. This gave me a chance to once again go back to the problem, but from a completely different perspective.
The exercise involves developing a very simple piece of code strictly adhering to the TDD rules, so much so that participants aren’t allowed to create domain methods or classes other than extracting them from test code. The goal of the exercise is to demonstrate factoring out just what you really need from the test code into domain design rather than starting with a pre-set design structure. Although this is in general taken as a goal of TDD, many programmers (me included) don’t realise how much their assumptions make them jump ahead too quickly. By making it very painful to add new domain code, this exercise slows participants down to a point where people have to spend a considerable amount of time actually focusing code on exactly what is required and no more.
Even on a very simple problem such as tic-tac-toe, differences from a pre-conceived design and the one that emerges from code are considerable, the latter being a lot more elegant and better suited to describe a problem.
The original exercise involved stones and the Go game. As I’ve never played that before and we had a lot less time than in the original one, I suggested tic-tac-toe. This turned out to be a very good idea as we spent less time explaining what the domain but it still proved the point of the exercise.
The requirements on the flip-chart were the following:
- a game is over when all fields are taken
- a game is over when all fields in a column are taken by a player
- a game is over when all fields in a row are taken by a player
- a game is over when all fields in a diagonal are taken by a player
- a player can take a field if not already taken
- players take turns taking fields until the game is over
All the participants worked in pairs. Most of the teams started by building a 3×3 board and describing requirements that were not given at all (eg first player won, tics or noughts being placed) and took three or four attempts at describing the problem to really go down to basics. As predicted, people were annoyed by this but I did make an effort to explain that the start of the exercise feels silly and annoying so this went much better than I expected. After the first requirement was done correctly, the next three followed easily as they are fairly related. The fifth one though posed a problem again and this is where things got really interesting, some teams falling back on the grid idea (and getting their code deleted) and some teams starting to flesh out the concepts of players and the actual dynamics of fields being taken.
By the end of the exercise, almost half the teams were coding towards something that was not a 3×3 char/int grid. We did not have the time to finish the whole thing, but some interesting solutions in making were:
- a bag of fields that are literally taken by players – field objects start in the collection belonging to the game and move to collections belonging to players, which simply avoids edge cases such as taking an already taken field and makes checking for game end criteria very easy.
- fields that have logic whether they are taken or not and by whom
- game with a current state field that was recalculated as the actions were performed on it and methods that could set this externally to make it easy to test
Most of the game classes had very nice explicit methods for checking different game end criteria. During a short retrospective at the end, some participants said that their code was very nicely isolated and encapsulated, with “less leakage than normal”, and that very explicit specifications ended up in the code making it easy to understand.
This exercise reminded me again about Eric Evans’ introductory presentation to domain modeling. One of the basic ideas there is that the best models are not the most realistic ones but the ones that allow us to describe a particular problem efficiently. The best models are good because they serve a particular purpose in a particular context, so a bag of fields might be a better model of the tic-tac-toe game than a 3×3 board even if the latter feels much more realistic and natural.
In my view, this exercise worked really well. It was interesting to observe it from a different perspective (this time I got the role of the annoying git who went around the room and deleted code that people wrote and did not need). Tic-tac-toe was a good choice as it did not require spending time on explaining and comes with an almost guaranteed 3×3 pre-conceived model. Some participants suggested that we should have done requirements 5 and 6 first and then moved to 1-4. Although this would take away the big refactoring moment, it might actually work better to allow people to factor out a very different model straight from the start. Introducing that the exercise is a bit annoying at the start was also a good idea, as I think that it went smoother than the original one with less opposition to dropping unnecessary code.
You can see some of the code examples on the openspacecode repository. For more information on the original exercise and the rules, see my earlier post about it. Mark Needham repeated the exercise earlier as well, building a message interceptor – something much more technical and practical than a tic-tac-toe or Go game. You can read his conclusions at markhneedham.com.
I'm Gojko Adzic, author of Impact Mapping and Specification by Example. I'm currently working on 50 Quick Ideas to Improve Your User Stories. To learn about discounts on my books, conferences and workshops, sign up for Impact or follow me on Twitter. Join me at these conferences and workshops:
Specification by Example Workshops
- Dublin, IE, 20-21 November
Product Owner Survival Camp
- Vienna, AT, 6-7 October
- Frankfurt, DE, 14-15 October
- London, UK, 24-25 November
- Stockholm, SE (with Jeff Patton and Mattias Skarin), 3-4 November
- Zurich, CH, Spring 2015 (TBA)
Conference talks and workshops