Using the command pattern to solve the Mars Rover Kata – Part 3

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

The Command Pattern

The Command Pattern encapsulates a request as an object, thereby letting you parametrise other objects with different requests, queue or log requests, and support undoable operations.

Or in English, use the command pattern when want to decouple the client that executes the command from the command logic and its dependencies.

That is what is we need to execute the three commands that must be sent to the rover.

We need commands for the following:

  • Move Forward
  • Turn Left
  • Turn Right

First will create a command interface with an execute methods and then blank classes for each of the three commands required

public interface ICommand
{
    void Execute();
}

public class ForwardCommand : ICommand
{
    public void Execute()
    {
        throw new NotImplementedException();
    }
}

public class TurnLeftCommand : ICommand
{
    public void Execute()
    {
        throw new NotImplementedException();
    }
}
public class TurnRightCommand : ICommand
{
    public void Execute()
    {
        throw new NotImplementedException();
    }
}
public class NotFoundCommand : ICommand
{
    public void Execute()
    {

    }
}

Now starts the real work required. We need a parser that will allow us to select the correct command to execute the rover

[TestFixture]
public class CommandParserTests
{
    private Dictionary<string, ICommand> _availableCommands;

    [SetUp]
    public void Setup()
    {
        _availableCommands = AvailableCommands.List;
    }

    [Test]
    public void Get_Correct_Command_To_Move_Forward()
    {
        var commandParser = new CommandParser(_availableCommands);
        var command = commandParser.ParseCommand("F");
        Assert.That(command, Is.TypeOf());
    }
}

I have created a static class AvailableCommands that will contain all the commands that are available. With the way that the list has been created, it will be easier to add other commands in the future.

I know that static classes are evil, but in this situation, a static is acceptable if my opinion.

public static class AvailableCommands
{
    public static Dictionary<string, ICommand> List
    {
        get
        {
            var commands = new Dictionary<string, ICommand">
                {
                    {"F", new ForwardCommand()},
                    {"L", new TurnLeftCommand()},
                    {"R", new TurnRightCommand()}
                };
            return commands;
        }
    }
}

Now that we have everything else in place, we need to work on the parser, which will be doing the actual work of getting the command to be executed

public class CommandParser
{
    private Dictionary<string, ICommand> _commands;

    public CommandParser(Dictionary<string, ICommand> commands)
    {
        _commands = commands;
    }

    public ICommand ParseCommand(string command)
    {
        if (_commands.ContainsKey(command))
            return _commands[command];
        return new NotFoundCommand();
    }
}

Just in case somebody ever sends an invalid command, we are using the Null Reference Pattern to create the NotFoundCommand. This class will do no work. Its to prevent a NullReferenceException.

The initial test will pass, now create two more tests to make sure that if we pass in the command string L and R, we get the correct command back to execute

[Test]
public void Get_Correct_Command_To_Turn_Left()
{
    var commandParser = new CommandParser(_availableCommands);
    var command = commandParser.ParseCommand("L");
    Assert.That(command, Is.TypeOf());
}

[Test]
public void Get_Correct_Command_To_Turn_Right()
{
    var commandParser = new CommandParser(_availableCommands);
    var command = commandParser.ParseCommand("R");
    Assert.That(command, Is.TypeOf());
}

[Test]
public void Get_NullCommand_With_Invalid_Command()
{
    var commandParser = new CommandParser(_availableCommands);
    var command = commandParser.ParseCommand("G");
    Assert.That(command, Is.TypeOf());
}

Now all that is required is to wire up the commands to be executed. The final test that we want to pass is

[Test]
[TestCase("RFLFFRF", 2, 2, "East")]
[TestCase("RMLLM", 0, 0, "West")]
public void TestMovement(string commandString, int xCoordinateExpected, int yCoordinateExpected, string directionExpected)
{
    var rover = new Rover(_landscape);
    rover.ExecuteCommands(commandString);
    Assert.That(rover.CoordinateX, Is.EqualTo(xCoordinateExpected));
    Assert.That(rover.CoordinateY, Is.EqualTo(yCoordinateExpected));
    Assert.That(rover.Direction.ToString(), Is.EqualTo(directionExpected));
}

All that is required is one small change to the rover class

public void ExecuteCommands(string commandString)
{
    var commands = AvailableCommands.List;
    var commandParser = new CommandParser(commands);

    for (int index = 0; index < commandString.Length; index++)
    {
        var command = commandString[index].ToString();
        var commandToExecute = commandParser.ParseCommand(command);
        commandToExecute.Execute(this);
    }
}

And now everything is completed. Just the final command line application to showcase the rover, and everything is completed

class Program
{
    static void Main(string[] args)
    {
        WriteHelp();
        var landscape = new Landscape(5);
        var rover = new Rover(landscape);
        Console.WriteLine(rover.ToString());
        string commandsToExecute = string.Empty;
        while (commandsToExecute != "E")
        {
            Console.Write("Enter Commands: ");
            commandsToExecute = Console.ReadLine().ToUpper();
            rover.ExecuteCommands(commandsToExecute);
            Console.WriteLine();
            Console.WriteLine(string.Format("Current Rover Position Heading: {0}",rover.ToString()));
        }
    }

    private static void WriteHelp()
    {
        Console.WriteLine("Valid Commands are:");
        Console.WriteLine("L - Turn Rover Left");
        Console.WriteLine("R - Turn Rover Right");
        Console.WriteLine("F - Move Rover Forward");
        Console.WriteLine("E - End");
        Console.WriteLine("Enter to execute commands");
    }
}

The code is available on Github.


Advertisement
About

My musing about anything and everything

Tagged with: , , ,
Posted in Kata, Mars Rover, TDD

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 )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

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

Join 13 other subscribers
%d bloggers like this: