Using the State Pattern to solve the Mars Rover Kata – Part 1

If you have not come across this kata before, this is it:

A Mars Rover has been developed to map out the landscape. It’s a small robot which can move on a grid, controlled by simple commands.

In this example, it will move on a 5×5 grid with a simple co-ordinate system – 0,0 is the bottom left, 4,4 is the top right.

We can control the Rover by sending it a string consisting of commands, such as the following:

RFLFFRF

R means rotate right 90 degrees, L rotate left 90 degrees, and F means move forward one square in the direction the Rover is currently facing. The Rover starts at 0,0 facing North (“up” the grid).

We need a program which will accept strings of commands at the command line, and return the grid position of the Rover after those commands

The objective of this kata is to use two patterns to solve this problem. The State pattern and the Command Pattern

In this post we will only be looking at the state pattern.

Head First Design Patterns

I have read of lot of literature on the the GoF patterns. I am sad to say that in nearly every case I have hated how the GoF patterns have been described. So theoretical. Very dry to read. If you are like me, then go any buy Head First Design Patterns. Its Java but its easy to do the examples in C#. This was the first pattern book that I read that I actually enjoyed reading.

The State Pattern

The state patterns is a behavioral software design pattern. The state pattern allows an object to alter its behaviour when its internal state changes. The object will appear to change its class.

The state pattern is an alternative to putting lots of conditionals in your context by encapsulating the behaviours within state objects, you can simple change the state object in context to change its behaviour.

Landscape

The starting point for the kata is to create the landscape that the rover will move in. First step is to create the interface

public interface ILandscape
{

}

No properties or methods now as I don’t know how I will use it.

Then next to look at is setting the direction of the rover. Create the interface to be used

public interface IDirection
{

}

For each direction we need to test turning left and turning right.

Original Direction Direction after turning left Direction after turning right
North West East
East North South
South East West
West South North

Now that we have the we have the interface, its time to start with the first direction. For no other reason, we will start with North

public class North : IDirection
{

}

The first test we want to right is turn left.

[Test]
public void When_North_And_Turn_Left_Direction_Should_Be_West()
{
    var direction = new North(_landscape);
    var newdirection = direction.TurnLeft();
    Assert.That(newdirection, Is.TypeOf(typeof (West)));
}

The code wont even compile, as we need to make a few changes to the interfaces already in use

public interface IDirection
{
    IDirection TurnLeft();
    IDirection TurnRight();
}

Now need to update the North class

public class North : IDirection
{
    private readonly ILandscape _landscape;

    public North(ILandscape landscape)
    {
        _landscape = landscape;
    }

    public IDirection TurnLeft()
    {
        return new West(_landscape);
    }

    public IDirection TurnRight()
    {
        return new East(_landscape);
    }

    public override string ToString()
    {
        return "North";
    }

}

Run the test again. Passes.

Now to write the next test. When North turn right

[Test]
public void When_North_And_Turn_Right_Direction_Should_Be_East()
{
    var direction = new North(_landscape);
    var newdirection = direction.TurnRight();
    Assert.That(newdirection, Is.TypeOf(typeof(East)));
}

All good. Now we just repeat for all the directions.

Here are all the completed tests

[Test]
public void When_East_And_Turn_Left_Direction_Should_Be_North()
{
    var direction = new East(_landscape);
    var newdirection = direction.TurnLeft();
    Assert.That(newdirection, Is.TypeOf(typeof(North)));
}

[Test]
public void When_East_And_Turn_Right_Direction_Should_Be_South()
{
    var direction = new East(_landscape);
    var newdirection = direction.TurnRight();
    Assert.That(newdirection, Is.TypeOf(typeof(South)));
}

[Test]
public void When_South_And_Turn_Left_Direction_Should_Be_East()
{
    var direction = new South(_landscape);
    var newdirection = direction.TurnLeft();
    Assert.That(newdirection, Is.TypeOf(typeof(East)));
}

[Test]
public void When_South_And_Turn_Right_Direction_Should_Be_West()
{
    var direction = new South(_landscape);
    var newdirection = direction.TurnRight();
    Assert.That(newdirection, Is.TypeOf(typeof(West)));
}

[Test]
public void When_West_And_Turn_Left_Direction_Should_Be_South()
{
    var direction = new West(_landscape);
    var newdirection = direction.TurnLeft();
    Assert.That(newdirection, Is.TypeOf(typeof(South)));
}

[Test]
public void When_West_And_Turn_Right_Direction_Should_Be_North()
{
    var direction = new West(_landscape);
    var newdirection = direction.TurnRight();
    Assert.That(newdirection, Is.TypeOf(typeof(North)));
}

And all the completed classes for each direction

public class East : IDirection
{
    private readonly ILandscape _landscape;

    public East(ILandscape landscape)
    {
        _landscape = landscape;
    }

    public IDirection TurnLeft()
    {
        return new North(_landscape);
    }

    public IDirection TurnRight()
    {
        return new South(_landscape);
    }

    public override string ToString()
    {
        return "East";
    }
}

public class South : IDirection
{
    private readonly ILandscape _landscape;

    public South(ILandscape landscape)
    {
        _landscape = landscape;
    }

    public IDirection TurnLeft()
    {
        return new East(_landscape);
    }

    public IDirection TurnRight()
    {
        return new West(_landscape);
    }

    public override string ToString()
    {
        return "South";
    }
}

public class West : IDirection
{
    private readonly ILandscape _landscape;

    public West(ILandscape landscape)
    {
        _landscape = landscape;
    }

    public IDirection TurnLeft()
    {
        return new South(_landscape);
    }

    public IDirection TurnRight()
    {
        return new North(_landscape);
    }

    public override string ToString()
    {
        return "West";
    }
}

In the next post, we will work on the rover.

Advertisements

My musing about anything and everything

Tagged with: , , , , ,
Posted in Kata, Mars Rover, TDD
2 comments on “Using the State Pattern to solve the Mars Rover Kata – Part 1
  1. […] This is the next part of the Mars Rover Kata. Part 1 can be found here. […]

  2. […] is the third and final part to solve the Mars Rover kata. Part 1 and Part 2 to view what has been done […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Enter your email address to follow this blog and receive notifications of new posts by email.

Join 11 other followers

%d bloggers like this: