Mark Needham

Thoughts on Software Development

Coding Dojo #13: TDD as if you meant it

with 9 comments

We decided to follow Keith Braithwaite’s ‘TDD as if you meant it‘ exercise which he led at the Software Craftsmanship Conference and which I originally read about on Gojko Adzic’s blog.

We worked on implementing a Flash Message interceptor, to hook into the Spring framework, that one of my colleague’s has been working on – the idea is to show a flash method to the user, that message being stored in the session on a Post and then removed on a Get in the ‘Post-Redirect-Get‘ cycle. It’s similar to the ‘:flash’ messages that get passed around in Rails.

The Format

We used the Randori approach with five people participating for the whole session.

What We Learnt

  • We were following these rules for coding :
    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)

    Despite having read about Gojko’s experiences of this exercise I still found it amazingly frustrating early on taking such small steps and the others pointed out a couple of times that the steps we were taking were too big. The most difficult thing for me was the idea of writing the implementation in the test and working out what counts as implementation code and what counts as test setup. The line seemed to be a little bit blurred at times.

  • We worked out after writing 5 or 6 tests that we had overcomplicated things – we originally started out using a map to represent the session and then called the get and put methods on that to represent putting the flash message into and taking it out from the session. We decided to redo these tests so that the flash message was just represented as a string which we manipulated. This second approach guided us towards the idea of having a FlashMessageStore object with a much simpler API than a Map.
  • We started off only extracting methods when there was duplication in our tests which forced us to do so. As a result of doing this I think we ended up having the implementation details in the test for longer than the exercise intended. We didn’t introduce a class to hold our methods for quite a while either – the idea we were following was that we wouldn’t create a class unless we had three methods to put on it. Once we got the hang of the exercise we started creating those methods and classes much earlier.
  • Dave pointed out an interesting way of writing guard blocks which I hadn’t seen before – the idea is that if you want to exit from a method it’s fine not to have the {} on the if statement as long as you keep the whole statement on one line. Roughly something like this:
    public void clearFlashMessageIfRequestTypeIsGet(Request request) {
    	if(!"get".equalsIgnoreCase(request.GetType()) return;
    	// do other stuff
    }
  • It seemed like following these rules guided us towards tiny/micro types in our code and the methods we extracted were really small compared to the ones we would have written if we’d started off writing the test and implementation separately.
  • We had an interesting discussion towards the end of the dojo about the merits of wrapping framework libraries with our own types. For example we might choose to wrap the HttpServletRequest in our own Request object so that we can control the API in our code. Although I think this might initially be a bit confusing to people who expect to see a certain set of methods available when they see they are using a Request object, this approach seems to be following Steve McConnell’s advice in Code Complete of ‘coding into a language’ rather than in a language – we are moulding the framework to our system’s needs.

For next time

  • I really enjoy the dojos where we experiment with an approach which is slightly different than what you do on projects. Although the language (Java) was familiar to everyone it was still challenging to code a very different way than what we’re used to. We’ll probably try this exercise again the next time with another problem.
Be Sociable, Share!

Written by Mark Needham

April 30th, 2009 at 6:12 am

Posted in Coding Dojo

Tagged with

  • http://peripateticaxiom.blogspot.com Keith Braithwaite

    Mark,
    Interesting experience, thanks for writing it up. Now that you’ve been through the exercise on a realistic problem, how do you feel about the resulting code? (Note: “how do you feel?” not “what do you think?)

  • http://billcomer.blogspot.com/ Bill Comer

    Mark,

    I thought I would give this a go in Java and failed, but I am unsure quite why. Perhaps you can enlighten me.

    I have a class Foo with some existing methods on it.
    I wish to add a new method bar() to do some work.
    Without alterring Foo I go to my test class and add a new test:

    public void testBar() throws Exception {
    Foo foo = new Foo() {
    public void bar(){
    // do some Baaing..
    }
    }
    foo.bar();
    }

    The compiler happily accepts the method bar() but fails to compile with a method undefined for the line:
    foo.bar();

    If I create an interface with bar() in or a stub in Foo then all is happy but this appears to miss the point.

  • http://www.markhneedham.com Mark Needham

    @Keith – I felt pretty good about the code, it felt much more like it evolved doing it this way.

    I discussed this with a few guys in the Dojo and we thought that the FlashMessageStore in this case became more obvious and that if we’d have coded the normal way we might not have seen that abstraction. Certainly an exercise to try again

  • http://peripateticaxiom.blogspot.com Keith Braithwaite

    @Bill,
    The compiler rejects the call to foo.bar() because bar is a method on an un-named sub-class of Foo, but foo is declared as a pointer to Foo so the method is not visible via that pointer.

    If you are following the intent of the exercise, you will not create a method bar like this, you will write some code in the test method that does the work and then (if it turns out to be desirable) factor that code out into a method–and perhaps not on Foo.

    Hope that helps.

  • http://peripateticaxiom.blogspot.com Keith Braithwaite

    @Mark,
    Good, that’s the feeling I look for in the exercise.

  • Pingback: Coding Dojo #14: Rock, Scissors, Paper - TDD as if you meant it at Mark Needham

  • Pingback: Most interesting links of November « The Holy Java

  • Pingback: TDD as if you Meant It « cumulativehypotheses

  • Cordoval

    where is the code for the message interceptor?