Mark Needham

Thoughts on Software Development

Rock Scissors Paper: TDD as if you meant it

with 4 comments

I decided to spend a bit of time on Saturday having another go at writing Rock Scissors Paper while following Keith Braithwaite’s TDD as if you meant it exercise.

We previously did this exercise at a coding dojo but I wanted to see what happens when you code for a longer period of time with this exercise since we typically only code for maybe a couple of hours at a dojo.

I decided to also checkin the code I was writing into Git after every single change I made – an idea I originally learnt from Dan North, and the code is all on github.

What did I learn?

  • I was coding for maybe 4 or 5 hours and checked in about 120 times which is far more frequently than I would do normally although perhaps it shouldn’t be.

    I thought it would be quite distracting to have to check in that often but the checkin messages ended up becoming a stream of consciousness of what I was thinking which proved quite useful on a few occasions when I got side tracked a bit and retraced my steps in the history to find out what I was supposed to be doing – Git was pretty much acting as my sounding board since I didn’t have a pair to work with on this exercise.

    I’d definitely try this out again and as I’ve mentioned a few times I want to try it out in a coding dojo some time.

  • While trying to remove some duplication that had worked its way into the code I realised that the template method would be the easiest way to remove that duplication and as I mentioned in an earlier post, having functions/actions in C# makes the implementation of this pattern a bit simpler:
        public abstract class ThrowBase : IThrow
        {
            private readonly Func<IThrow, bool> beatenBy;
     
            protected ThrowBase(Func<IThrow, bool> beatenBy)
            {
                this.beatenBy = beatenBy;
            }
     
    	 ....		
     
            public bool Beats(IThrow aThrow)
            {
                return IsDifferentThrowTo(aThrow) && !beatenBy(aThrow);
            }
     
        }
    }
        public class Scissors : ThrowBase
        {
            public Scissors() : base(weapon => weapon.BeatsScissors()) { }
     
    	...
        }

    If we didn’t have functions then we’d need a method on ‘ThrowBase’ which we would need to implement in each of its sub classes.

    As it is we can just pass a function into the constructor which does the same job.

  • Another thing I found quite interesting about this exercise was that I was seeing more easily where methods didn’t seem to belong on an existing object and I ended up creating a new object which described the interaction – chatting about the code with Liz she pointed out that I was probably creating domain events which we had discussed a few days earlier in book club.

    Once I started thinking about this interactions as ‘domain events’ the naming of them seemed to be much more obvious – for example after this conversation with Liz I realised that the interaction between two ‘Throws’ would be a ‘ThrowDown’ and that there would probably be a ‘ThrowDownAdjudicator’ to decide the outcome of a ‘ThrowDown’.

  • I found it quite difficult to follow the rules of the exercise when I realised that I wanted to return a ‘ThrowDownResult’ which would indicate whether there was a winner for a ‘ThrowDown’ and if so who it was. I couldn’t see a way to write all of this code in the test since I had already created the class previously so I ended up writing this code straight onto the class.

    I think I probably extracted to a class too early on some occasions instead of waiting for a more complete version of a method to be written before moving it.

    Next time I think I’d wait until I’d completed all the examples /tests I want to write around a particular method before moving it onto a class.

Be Sociable, Share!

Written by Mark Needham

August 24th, 2009 at 10:11 pm

Posted in Testing

Tagged with