My first personal code retreat

To tie in with the Global Day of Code Retreat, I’m doing some personal retreating so that I can practice and hopefully learn some new things. There is a great intro video referred by the code retreat site that gives an introduction to what it is all about – in essence “perfect practice makes perfect”.
Rather than trying to solve a whole problem, just code as perfect as you can for a short period of time.

So I’ll be coding for 45 minutes recording what I’ve learnt and then in the spirit of the code retreat, deleting the code (although it will be on my blog). Repeat again same day, or another day. Each time I’ll try and learn something new.

The Conway game of life is used for a code retreat and the rules are summarised from the code retreat page as:

The universe of the Game of Life is an infinite two-dimensional orthogonal grid of square cells, each of which is in one of two possible states, live or dead.
Every cell interacts with its eight neighbours, which are the cells that are directly horizontally, vertically, or diagonally adjacent. At each step in time, the following transitions occur:

Any live cell with fewer than two live neighbours dies, as if caused by under-population.
Any live cell with more than three live neighbours dies, as if by overcrowding.
Any live cell with two or three live neighbours lives on to the next generation.
Any dead cell with exactly three live neighbours becomes a live cell.

So here goes with pure test driven development in context specification style as my first code retreat.

(an hour later)…

Because I’m using my usual context specification test driven style, I found it very easy to define my tests in the language of the rules themselves. This ensures there are no ambiguities and I’m writing my tests with the domain in mind.
This is, for me, why context specification is such a useful development tool.

I started with one test:

    [Subject(typeof(Cell))]
    public class when_an_alive_cell_has_two_alive_neighbours
    {
        Establish context = () =>
        {
            _liveNeighbour = new Cell(State.Alive, null);
            _secondLiveNeighbour = new Cell(State.Alive, null);
            _neighbours = new List<Cell> {_liveNeighbour, _secondLiveNeighbour};

            _cell = new Cell(State.Alive, _neighbours);
        };

        Because of = () => _stateForNextGeneration = _cell.IdentifyStateForTheNextGeneration();

        It should_live_on_to_the_next_generation = () =>
            _stateForNextGeneration.ShouldEqual(State.Alive);

        static Cell _cell;
        static IEnumerable<Cell> _neighbours;
        static Cell _liveNeighbour;
        static Cell _secondLiveNeighbour;
        static State _stateForNextGeneration;
    }

This produced the simplest implementation possible to make this test pass:

    public enum State
    {
        Alive,
        Dead
    }

    public class Cell
    {
        public Cell(State state, IEnumerable<Cell> neighbours)
        {
        }

        public State IdentifyStateForTheNextGeneration()
        {
            return State.Alive;
        }
    }

Then I moved on to some more tests that would shape the development:

    [Subject(typeof(Cell))]
    public class when_an_alive_cell_has_one_alive_neighbour
    {
        Establish context = () =>
        {
            _liveNeighbour = new Cell(State.Alive, null);
            _neighbours = new List<Cell> { _liveNeighbour };

            _cell = new Cell(State.Alive, _neighbours);
        };

        Because of = () => _stateForNextGeneration = _cell.IdentifyStateForTheNextGeneration();

        It should_not_live_on_to_the_next_generation_due_to_under_population = () =>
            _stateForNextGeneration.ShouldEqual(State.Dead);

        static Cell _cell;
        static IEnumerable<Cell> _neighbours;
        static Cell _liveNeighbour;        
        static State _stateForNextGeneration;
    }

This results in a specific guard clause to help me meet the original test and I have to expose the current state on the Cell:

    public class Cell
    {
        public State CurrentState { get; private set; }
        readonly IEnumerable<Cell> _neighbours;

        public Cell(State state, IEnumerable<Cell> neighbours)
        {
            CurrentState = state;
            _neighbours = neighbours;
        }

        public State IdentifyStateForTheNextGeneration()
        {
            if(_neighbours.Count(n => n.CurrentState == State.Alive) == 2)
                return State.Alive;

            return State.Dead;
        }
    }

I know added another test that would fail:

    [Subject(typeof(Cell))]
    public class when_an_alive_cell_has_four_alive_neighbours
    {
        Establish context = () =>
        {
            _neighbours = new List<Cell> { new Cell(State.Alive, null), 
                            new Cell(State.Alive, null), 
                            new Cell(State.Alive, null), 
                            new Cell(State.Alive, null) };

            _cell = new Cell(State.Alive, _neighbours);
        };

        Because of = () => _stateForNextGeneration = _cell.IdentifyStateForTheNextGeneration();

        It should_not_live_on_to_the_next_generation_due_to_over_population = () =>
            _stateForNextGeneration.ShouldEqual(State.Dead);

        static Cell _cell;
        static IEnumerable<Cell> _neighbours;
        static State _stateForNextGeneration;
    }

To make this test pass I know have to be more specific in my guard clause:

        if(_neighbours.Count(n => n.CurrentState == State.Alive) == 2)

I can now refine it more for three alive neighbours:

    [Subject(typeof(Cell))]
    public class when_an_alive_cell_has_three_alive_neighbours
    {
        Establish context = () =>
        {
            _neighbours = new List<Cell> { new Cell(State.Alive, null), 
                            new Cell(State.Alive, null), 
                            new Cell(State.Alive, null) };

            _cell = new Cell(State.Alive, _neighbours);
        };

        Because of = () => _stateForNextGeneration = _cell.IdentifyStateForTheNextGeneration();

        It should_live_on_to_the_next_generation = () =>
            _stateForNextGeneration.ShouldEqual(State.Alive);

        static Cell _cell;
        static IEnumerable<Cell> _neighbours;
        static State _stateForNextGeneration;
    }

And this once again refines my implementation:

    public class Cell
    {
        public State CurrentState { get; private set; }
        readonly IEnumerable<Cell> _neighbours;

        public Cell(State state, IEnumerable<Cell> neighbours)
        {
            CurrentState = state;
            _neighbours = neighbours;
        }

        public State IdentifyStateForTheNextGeneration()
        {
            var aliveNeighbours = _neighbours.Count(n => n.CurrentState == State.Alive);
            
            if( aliveNeighbours == 2 || aliveNeighbours == 3)
                return State.Alive;

            return State.Dead;
        }
    }

Now I thought it was time to introduce rules for a dead cell:

    [Subject(typeof(Cell))]
    public class when_a_dead_cell_has_two_alive_neighbours
    {
        Establish context = () =>
        {
            _neighbours = new List<Cell> { new Cell(State.Alive, null), 
                            new Cell(State.Alive, null) };

            _deadCell = new Cell(State.Dead, _neighbours);
        };

        Because of = () => _stateForNextGeneration = _deadCell.IdentifyStateForTheNextGeneration();

        It should_still_be_dead_on_the_next_generation = () =>
            _stateForNextGeneration.ShouldEqual(State.Dead);

        static Cell _deadCell;
        static IEnumerable<Cell> _neighbours;
        static State _stateForNextGeneration;
    }

This test fails, so once again, the simplest thing possible:

    public class Cell
    {
        public State CurrentState { get; private set; }
        readonly IEnumerable<Cell> _neighbours;

        public Cell(State state, IEnumerable<Cell> neighbours)
        {
            CurrentState = state;
            _neighbours = neighbours;
        }

        public State IdentifyStateForTheNextGeneration()
        {
            if (CurrentState == State.Dead)
                return State.Dead;

            var aliveNeighbours = _neighbours.Count(n => n.CurrentState == State.Alive);
            
            if( aliveNeighbours == 2 || aliveNeighbours == 3)
                return State.Alive;

            return State.Dead;
        }
    }

Another test for dead, this time for resurrection:

    [Subject(typeof(Cell))]
    public class when_a_dead_cell_has_three_alive_neighbours
    {
        Establish context = () =>
        {
            _neighbours = new List<Cell> { new Cell(State.Alive, null), 
                            new Cell(State.Alive, null), 
                            new Cell(State.Alive, null) };

            _deadCell = new Cell(State.Dead, _neighbours);
        };

        Because of = () => _stateForNextGeneration = _deadCell.IdentifyStateForTheNextGeneration();

        It should_become_alive_on_the_next_generation = () =>
            _stateForNextGeneration.ShouldEqual(State.Alive);

        static Cell _deadCell;
        static IEnumerable<Cell> _neighbours;
        static State _stateForNextGeneration;
    }

Now making the implementation neat for this was interesting. What I don't want is mess with an if statement at the start of the existing method:

            if (CurrentState == State.Dead)
            {
                if (xxxxxx)
                    return State.Alive;

                return State.Dead;
            }

So instead the rules were split to make them expressive:

    public class Cell
    {
        public State CurrentState { get; private set; }
        readonly IEnumerable<Cell> _neighbours;

        public Cell(State state, IEnumerable<Cell> neighbours)
        {
            CurrentState = state;
            _neighbours = neighbours;
        }

        public State IdentifyStateForTheNextGeneration()
        {
            var aliveNeighbours = _neighbours.Count(n => n.CurrentState == State.Alive);

            return CurrentState == State.Alive ? IdentifyStateBecauseIAmAlive(aliveNeighbours) :
                            IdentifyStateBecauseIAmDead(aliveNeighbours);
        }

        State IdentifyStateBecauseIAmAlive(int aliveNeighbours)
        {
            if (aliveNeighbours == 2 || aliveNeighbours == 3)
                return State.Alive;

            return State.Dead;
        }

        State IdentifyStateBecauseIAmDead(int aliveNeighbours)
        {
            if(aliveNeighbours ==3)
                return State.Alive;

            return State.Dead;
        }
    }

So what did I learn from this?

It was interesting that I was able to define the rules without actually declaring any dead neighbours at all. Because I’m working with IEnumerable<Cell> and not restricting the Cell implementation to have exactly eight neighbours or know about top, left, right, diagonal etc, my rules implementation seems to be easier and my tests certainly were easier to set up.

Because I started at the cell level I haven’t even explored the grid itself yet – would I have an external grid class that managed the creation of cells and ensured the neighbour arrangement for example?
I also haven’t explored what happens to current state on the “tick” of the generation, something I might want to concentrate on a later retreat.

My tests seem very expressive, and I could write more for edge cases over and above the rules themselves, such as eight specific dead neighbours, etc.
Its a shame such rich information is only available to developers, so one of my next retreats will be to look at other ways of defining these specifications.

So I’m happy after this retreat – although I haven’t pushed myself that much on this one, I am confident that because I’ve started with the rules from the problem domain (and not layout) I have had a relatively easy implementation of the rules and have shaped the code in a particular way that fits nicely.



0 comments: