Thought-provoking TDD exercise at the Software Craftsmanship conference

Yesterday I attended Keith Braithwaite‘s workshop titled ”TDD as if you meant it” at the Software Craftsmanship 2009 conference, and I found it truly thought provoking. At the start of the workshop I thought that the exercise is plain silly but I publicly take it back: Keith – you really taught me something yesterday and I thank you for that.

Attendees were split into pairs who were working on the task together, using TDD practices with very strict rules:

  1. write exactly ONE failing test
  2. make the test from (1) pass by first writing implementation code IN THE TEST
  3. create a new implementation method/function by:
    1. doing extract method on implementation code created as per (2), or
    2. moving implementation code as per (2) into an existing implementation method
  4. only ever create new methods IN THE TEST CLASS
  5. only ever create implementation classes to provide a destination for extracting a method created as per (4).
  6. populate implementation classes by doing move method from a test class into them
  7. refactor as required
  8. go to (1)

The exercise involved writing a piece of code to evaluate whether a stone in the Go game can be taken or not. The definition of whether a stone can be taken was given as it having only one ‘liberty’, with liberties defined as free horizontal or vertical places adjacent to the stone. For example, the white stone in the picture below has two liberties (diagonals don’t count) and it cannot be taken.

The picture above was the first example we had to implement. The rules were designed to strictly let the domain code evolve from the test code in baby steps, which I though was the way I’m doing unit testing anyway, so it did not feel challenging at all. My first attempt started like this:

public void StoneHasTwoLibertiesIfTwoCornersAreCovered()
	GoGrid grid=new GoGrid(3,3);

Keith came over and said “Wow! Where did that GoGrid come from?” The rules of the workshop were that we had to let domain code evolve from the test code, and I tried to explain that the class doesn’t yet exist and I’m using the test to drive it’s design, so in my mind I was following the rules of the game but Keith was having none of it, so we had to delete that and start over. As we weren’t allowed to use domain classes, even presumed domain classes, my next attempt was to store it in a char array and then possibly later move that out:

public void StoneHasTwoLibertiesIfTwoCornersAreCovered()
	char grid[][]=new char[][]{ 
                     new char[]{' ', ' ', ' '},
                     new char[]{'B', 'W', ' '},
                     new char[]{' ', 'B', ' '},
 	int liberties=0;
    	for (int x=0; x<3; x++)

Keith came over again and complained against that. At this point, I was a bit lost. I guess that my pair partner was lost as well. Keith kept asking why we were writing this code, I was explaining that I was describing the example that he gave but again he was not accepting it. Then we came to the point of what exactly we were testing and I said “well the test name says it – if the stone has two corners covered, its liberty is 2”, and Keith asked why haven’t we specified that in the test rather than starting with a grid. So we changed the test to this:

public void StoneHasTwoLibertiesIfTwoCornersAreCovered()
	int cornersCovered=2;
 	int liberties=4- cornersCovered;

Finally he seemed happy with this, but to me it looked plain silly. It was not any closer to the end goal and I was just testing subtraction. Encouraging us to stick with it for a while, Keith left to help others and we continued writing other examples. After a couple more similar cases implemented as tests, we were allowed to refactor and move the code to calculate liberties to a new method in the test class. Then we started implementing cases with groups of stones, and things sort of fell into place.

Operations on groups of stones would be a lot more complicated to handle with the grid directly. The exercise was pushing us towards a design that treated groups as a whole rather than individual pieces and not having the grid as a matrix of stones defined at all. Of course the same functionality can be implemented directly on a grid but it would mean much more code and it would be much more complex.

The exercise was very interesting, although I initially thought that it is silly and too simplistic. It showed me how much hidden assumptions can affect my work if I don’t really try to express them and of course I fell into the classic trap of restating the problem and solving the restated problem first. I was thinking about something that I’ll probably need in the future and jumping too much ahead instead of just focusing on the task that I really was supposed to solve.

My counter-argument is that in real projects, not in workshop labs, I would typically have a bigger chunk of requirements and domain explored and we would try out a few designs to see which one fits the problem space best before we started coding, so unit tests will be used to flesh out the APIs but the design ideas would probably be there in some form. Nevertheless, I think that it would be really interesting to try this technique out on a real project as well. According to Keith after the exercise, classes developed like this tend to have very little or no state, very little code and end up with methods with long parameter lists, coming much closer to the functional programming paradigm. The code ends up with lots of small classes.

Read about the follow-up on this exercise as well: TDD as if you meant it: revisited

I'm Gojko Adzic, author of Impact Mapping and Specification by Example. My latest book is Fifty Quick Ideas to Improve Your Tests. 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

How to get more value out of user stories

Impact Mapping

30 thoughts on “Thought-provoking TDD exercise at the Software Craftsmanship conference

  1. Gojko, nice write-up . I’m glad you found the workshop stimulating.

    As far as using this technique on a real project goes, I wouldn’t do it all the time but I have learned that when I get into a tricky spot of coding it’s good practice go slower, and slower again; use smaller steps, and smaller again, be more explicit, more concrete and more simple-minded.

    It can seem with this technique that you just aren’t getting anywhere. I learned that the peak feeling of frustration that I’m not “getting anything done” comes just before the sudden snap! where all these little bits of code that don’t seem to do any work suddenly turn themselves inside out and beautifully simple design emerges. One has to push past that feeling, put in that last example, and wait for the magic.

    Lastly, let me say here what I said at the top of the session yesterday: to quote Allan Watts (badly), I came not as a salesman but as an entertainer. I want you to enjoy these ideas because I enjoy them.

  2. Pingback: Frank Carver’s Punch Barrel / Fun with very strict TDD

  3. I guess I’m missing something, but it seems to me the lesson has more to do with the benefits of functional programming than it does with TDD.

    “I get into a tricky spot of coding it’s good practice go slower, and slower again; use smaller steps, and smaller again, be more explicit, more concrete and more simple-minded.”

    This is how most functional programs are written and how most functional programmers work.

    “According to Keith after the exercise, classes developed like this tend to have very little or no state, very little code and end up with methods with long parameter lists, coming much closer to the functional programming paradigm. The code ends up with lots of small classes.”

    One thing you’ve made me realize though is that TDD is a lot like programming in a functional language with a repl…just not as good :)

  4. Bertrand, you have uncovered the hidden agenda!

    I’m firmly convinced that sincere TDD leads one towards a functional style. In corporate settings where one can’t sensibly talk about functional programming but can talk about TDD that’s a useful property :)

  5. Well, I at least don’t see the benefit. You /say/ that code ends up nice & stateless etc but, this post sure doesn’t get you there.

    TDD, vapor benefit 4-ever.

  6. Pingback: rob bowley - adventures in software craftsmanship » Blog Archive » Software Craftsmanship 2009 Round Up

  7. “According to Keith after the exercise, classes developed like this tend to have very little or no state, very little code and end up with methods with long parameter lists, coming much closer to the functional programming paradigm. The code ends up with lots of small classes.”

    I can see the benefit of having very little state and small classes but would we not want to avoid having methods with long parameter lists?

    Sounds like a cool idea though – we’ve tried something similar in coding dojos here and it’s really hard to keep to those rules and sometimes seems too simplistic.

  8. @mark: I’m not claiming that every consequence of this technique is beneficial in every case.

    As it happens long method argument lists can be a way to discover new objects–if we see the same long parameter list in several places. If the contents of those argument lists are hidden way in object fields then this might not be so obvious. Expand to contract.

  9. Pingback: Coding Dojo #11: Javascript Isola at Mark Needham

  10. Pingback: Coding Dojo #13: TDD as if you meant it at Mark Needham

  11. I’d be really interested in seeing the evolution of a piece of code like this. Know of any examples I might look at?

  12. For me, the writeup stops be concrete exactly where things get interesting – we see a couple of failed attempts, then an example of where Keith apparently thought they should start, then very high-level, uninstructive description of the subsequent process.

    As Andrew noted – it would be interesting to see the rest of the steps, because what’s there doesn’t really give me a feeling of what happened.

    [Also, I thought the TDD mantra was to start with a test that fails. The example of the test that Keith liked is a test that doesn’t fail. Huh?]

  13. I’m giving this a try, using the bowling game problem, and I’ve run up against an issue I’m not sure how to solve. I created my first three tests (the score after a single roll is the value of that roll, after the second roll when there’s no strike the score is the two added together, after the third roll when there’s no strike or spare the score is the three added together), which provided me with enough duplication to extract a method (getScore()) and a domain object (RollHistory) that I then moved getScore() to… but now I’m not sure how to continue. My next test would naturally be to calculate the score after the third roll when there’s a spare in the first frame, but all the implementation changes would go in the existing method. Is this how this technique is supposed to work?

  14. I find the idea to be interesting. The procedure is not all that unfamiliar with the way I usually work apart from 2 points (which I think are the main points of this exercise).

    That is points no 1 and 4. I can understand the need for point 1 to make the solution evolve from something really simple to a working but still simple solution. I cannot however see the great benefits of point 4. To write the code in the test and then move it. I have not yet tried it myself, so I would not rule out it, but I would like to hear some comments on why it is good/not good.

  15. Pingback: Practice, Code Exercises, and Code Katas : Steve Smith's Blog

  16. Pingback: Kent Beck’s Test Driven Development Screencasts at Mark Needham

  17. Pingback: Mini-Review of Kent Beck’s TDD Screencast Episode 1: Starter Test | Agile Shrugged

  18. Pingback: Koans and Katas, Oh My! Slides and Links From My Øredev 2010 Session | Cory Foy

  19. Pingback: My first code retreat | Valtech UK

  20. Pingback: Upcoming Events « Sergey Shishkin

  21. Pingback: Adastral Park code retreat at Kerry Buckley

  22. Pingback: CodeRetreat | Blog Xebia France

  23. Pingback: ALE 2011 « Code Craft

  24. What is interesting is the discussion on functional here. I’ve recently been in one of these sessions with Keith, and found it tough, really tough – and yet I have used functional languages, and regularly write python stuff using a functional style. I’ve also written unit tests (and trying to find unit test frameworks) for Scheme (the lisp dialect), and I’ve even tried the TDD methods in it, which does tease out a design. I have practiced the “build as if stuff exists” way of functional. Perhaps I can re-approach the exercise thinking functionally and see how much more it works.

  25. Pingback: My first Coderetreat abroad |

  26. Pingback: Claysnow Limited – Teaching TDD (TTDD)

Leave a Reply

Your email address will not be published. Required fields are marked *