Monthly Archives: February 2015

Object Oriented, Test Driven Design in C# and Java: A Practical Example Part #4

Download the code in C#
Download the code in Java

Check out my interview on .NET Rocks! – TDD on .NET and Java with Paul Mooney

For a brief overview, please refer to this post.

That’s the hard work done! Our WorkerDrones can now deliver RobotParts to their respective FactoryRoom implementations. Now, we can start building Robots! But wait…

Oh, no. Something's gone wrong!

“Oh, no. Something’s gone horribly wrong!”

It looks like our code is broken. Remember our WorkerDrone logic?

C#

        public void IdentifyRobotPart(RobotPart robotPart) {
            switch (robotPart.RobotPartCategory) {
                case RobotPartCategory.Assembly:
                    _transportMechanism = new AssemblyRoomTransportMechanism();
                    break;
                case RobotPartCategory.Weapon:
                    _transportMechanism = new ArmouryTransportMechanism();
                    break;
            }
        }

Java

    public void identifyRobotPart(robotPart robotPart) {
        switch (robotPart.getRobotPartCategory()) {
            case assembly:
                _transportMechanism = new assemblyRoomTransportMechanism();
                break;
            case weapon:
                _transportMechanism = new armouryTransportMechanism();
                break;
        }
    }

Our Unit Tests only ever considered WorkerDrones that transport a single RobotPart at a time. We haven’t considered the consequences of transporting multiple RobotParts.

As it turns out, our WorkerDrone's TransportMechanism will be overwritten every time a RobotPart is picked up. This will produce incorrect behaviour; essentially, all RobotParts held by a WorkerDrone will be delivered to the same FactoryRoom implementation – the FactoryRoom implementation associated with the last RobotPart to be picked up, which will overwrite the previous RobotPart that was picked up.

“How do we fix this?”

Well, currently our WorkerDrones can only successfully transport a single RobotPart at a time. Our Factory would operate a lot more efficiently if our WorkerDrones could carry multiple RobotParts and successfully deliver them without having to return to the DeliveryBay after each run.

More than 1 RobotPart at a time? Please! Easy work for me!!!

More than 1 RobotPart at a time? Please! Easy work for me!!!

First, let’s change the IdentifyRobotPart method so that it simply returns a TransportMechanism implementation based on the RobotPart parameter:

C#

        public TransportMechanism IdentifyRobotPart(RobotPart robotPart) {
            switch (robotPart.RobotPartCategory) {
                case RobotPartCategory.Assembly:
                    return new AssemblyRoomTransportMechanism((Assembly) robotPart);
                case RobotPartCategory.Weapon:
                    return new ArmouryTransportMechanism((Weapon) robotPart);
            }
            throw new NotImplementedException("I can't identify this component!");
        }

Java

    public transportMechanism identifyRobotPart(robotPart robotPart) throws UnsupportedOperationException {
        switch (robotPart.getRobotPartCategory()) {
            case assembly:
                return new assemblyRoomTransportMechanism((assembly) robotPart);
            case weapon:
                return new armouryTransportMechanism((weapon) robotPart);
        }
        throw new UnsupportedOperationException("I can't identify this component!");
    }

We’ll call this method every time our WorkerDrone picks up a RobotPart. Next, let’s replace our TransportMechanism member-variable with a collection:

C#

    private readonly List<TransportMechanism> _transportMechanisms;

Java

    private List<transportMechanism> _transportMechanisms;

Now we need to modify the OffLoadRobotPart to simply transfer the RobotPart that we just picked up to its associated FactoryRoom instance.

C#

        public FactoryRoom OffLoadRobotPart() {
            if (_factoryRoom == null) {
                EnterRoom();
            }
            _factoryRoom.AddRobotPart(_robotPart);
            return _factoryRoom;
        }

Java

    public E offLoadRobotPart() {
        if (_factoryRoom == null) {
            enterRoom();
        }

        _factoryRoom.addRobotPart(_robotPart);
        return _factoryRoom;
    }

Note that we’ve also changed our TransportMechanism abstraction to accept a RobotPart by default. This is where we’ll load the RobotPart that is picked up by the WorkerDrone.

C#

        protected TransportMechanism(RobotPart robotPart) {
            _robotPart = robotPart;
        }

Java

    protected transportMechanism(U robotPart) {
        _robotPart = robotPart;
    }

Now, the most important part. We need to change the TransportRobotParts method to loop through each TransportMechanism (we’ll have 1 for each RobotPart that we picked up) and execute the OffLoadRobotPart method:

C#

       public void TransportRobotParts() {
            foreach (var transportMechanism in _transportMechanisms) {
                transportMechanism.OffLoadRobotPart();
            }

            _transportMechanisms.Clear();
        }

Java

   public void transportRobotParts() {
        for (Iterator<transportMechanism> i = _transportMechanisms.iterator(); i.hasNext(); ) {
            transportMechanism transportMechanism = i.next();
            transportMechanism.offLoadRobotPart();
        }

        _transportMechanisms.clear();
    }

OK. Now our WorkerDrone can successfully deliver multiple RobotParts to multiple FactoryRooms. Now we need to ensure that it will return to the DeliveryBay once it has delivered its payload.

I'm ready to transport more RobotParts! Back to the DeliveryBay I go...

“I’m ready to transport more RobotParts! Back to the DeliveryBay I go…”

AS usual with TDD, let’s start with the tests, and introduce a new test to assert that multiple RobotParts can be delivered successfully. Our test will cover a scenario where a WorkerDrone delivers multiple RobotParts and then returns to the DeliveryBay.

C#

        public void WorkerDroneReturnsToDeliveryBayAfterDeliveringRobotParts() {
            WorkerDrone workerDrone = new MockedWorkerDrone();

            var randomAssembly = new MockedAssembly();
            var randomWeapon = new MockedWeapon();

            workerDrone.PickUpRobotPart(randomAssembly);
            workerDrone.PickUpRobotPart(randomWeapon);

            workerDrone.TransportRobotParts();
            Assert.True(workerDrone.GetTransportationMechanisms().Any());

            var transportMechanism = workerDrone.GetTransportationMechanisms().First();
            Assert.IsInstanceOf<DeliveryBayTransportMechanism>(transportMechanism);
        }

Java

    public void workerDroneReturnsToDeliveryBayAfterDeliveringRobotParts() {
        workerDrone workerDrone = new mockedWorkerDrone();

        robotPart randomAssembly = new mockedAssembly();
        robotPart randomWeapon = new mockedWeapon();

        workerDrone.pickUpRobotPart(randomAssembly);
        workerDrone.pickUpRobotPart(randomWeapon);

        workerDrone.transportRobotParts();

        Iterator<transportMechanism> iterator = workerDrone.getTransportMechanisms().iterator();
        assertTrue(iterator.hasNext());

        transportMechanism transportMechanism = iterator.next();
        assertThat(transportMechanism, instanceOf(deliveryBayTransportMechanism.class));
    }

Notice here that we assert that our WorkerDrone contains a single DeliveryBayTransportMechanism. This implementation, when executed, simply returns the WorkerDrone to the DeliveryBay. Let’s look at how this works:

C#

        public void TransportRobotParts() {
            foreach (var transportMechanism in _transportMechanisms) {
                transportMechanism.OffLoadRobotPart();
            }

            _transportMechanisms.Clear();

            var deliveryBayTransportMechanism = new DeliveryBayTransportMechanism();
            _transportMechanisms.Add(deliveryBayTransportMechanism);

            deliveryBayTransportMechanism.EnterRoom();
        }

Java

    public void transportRobotParts() {
        for (Iterator<transportMechanism> i = _transportMechanisms.iterator(); i.hasNext(); ) {
            transportMechanism transportMechanism = i.next();
            transportMechanism.offLoadRobotPart();
        }

        _transportMechanisms.clear();

        deliveryBayTransportMechanism deliveryBayTransportMechanism = new deliveryBayTransportMechanism();
        _transportMechanisms.add(deliveryBayTransportMechanism);

        deliveryBayTransportMechanism.enterRoom();
    }

Note that we explicitly create a DeliveryBayTransportMechanism instance and execute the enterRoom method. Now our WorkerDrone has returned to DeliveryBay after successful delivery of its payload. We’ve demonstrated how TDD and OOD can facilitate change during the software development life-cycle.

The next tutorial in the series will focus on building Robots.

Connect with me:

RSSGitHubTwitter
LinkedInYouTubeGoogle+

Object Oriented, Test Driven Design in C# and Java: A Practical Example Part #3

Download the code in C#
Download the code in Java

Check out my interview on .NET Rocks! – TDD on .NET and Java with Paul Mooney

For a brief overview, please refer to this post.

We’ve provided our WorkerDrones with a means to determine an appropriate method of transportation by inspecting any given RobotPart implementation. Now WorkerDrones may select a TransportationMechanism implementation that suits each RobotPart. But we have yet to implement the actual logic involved. This is what we’ll cover in this tutorial. Look at how eager the little guy is! Let’s not delay; he’s got plenty of work to do.

WorkerDrone

Once again, here is our narrative:

“Mechs with Big Guns” is a factory that produces large, robotic vehicles designed to shoot other large, robotic vehicles. Robots are composed of several robotic parts, delivered by suppliers. Parts are loaded into a delivery bay, and are transported by worker drones to various rooms; functional parts such as arms, legs, etc., are dispatched to an assembly room. Guns and explosives are dispatched to an armoury.
The factory hosts many worker drones to assemble the robots. These drones will specialise in the construction of 1 specific robot, and will require all parts that make up that robot in order to build it. Once the drone has acquired all parts, it will enter the assembly room and build the robot. Newly built robots are transported to the armoury where waiting drones outfit them with guns. From time to time, two robots will randomly be selected from the armoury, and will engage one another in the arena, an advanced testing-ground in the factory. The winning robot will be repaired in the arena by repair drones. Its design will be promoted on a leader board, tracking each design and their associated victories.

Let’s look at what exactly happens when we transport a RobotPart.
First, the WorkerDrone needs to identify the RobotPart that it just picked up, so that it can transport the part to the correct FactoryRoom. Let’s dive right in.

In the previous tutorial, we defined a means to do this by examining a RobotPart's RobotPartCategory and returning an appropriate TransportMechanism. Now, let’s add logic to our TransportMechanism.

First, we need to keep track of the FactoryRoom where we’ll offload the RobotParts:

C#

 private FactoryRoom _factoryRoom;

Java

    private E _factoryRoom;

First of all, what can we tell about the difference between both implementations? Both contain private properties, but our C# implementation is explicitly bound to a FactoryRoom object. Our Java implementation, on the other hand, seems to be bound to the letter “E”.

“What’s that all about?”

The difference in implementations can be explained by discussing Generics. Essentially, Generics allow us to define an action, like a method, without defining a concrete return-type or input parameter – instead, we define these in concrete implementations of our abstraction. At this point, rather than go off-topic, I’ll provide a link to a thorough tutorial on this subject in C#.

In a nutshell, the difference in implementations comes down to a personal preference – I prefer Java’s implementation of Generics over C#’s, specifically Java’s support for covariance and contravariance. Again, I’m happy to follow up with this offline, or to host a separate post on the subject, but for now, let’s keep going.

Let’s look at our Java implementation of transportMechanism:

public abstract class transportMechanism&lt;E extends factoryRoom, U extends robotPart&gt; {

Here, we’re telling the compiler that our transportMechanism class will require 2 concrete implementations, both of which should be derived from factoryRoom and robotPart respectively. To illustrate this, let’s look at armouryTransportMechanism, a class derived from transportMechanism in Java:

public class armouryTransportMechanism extends transportMechanism&lt;armoury, weapon&gt; {

    @Override
    public armoury getFactoryRoom() {
        return new armoury();
    }
}

Notice our Generic implementation of factoryRoom and robotPart map to armoury and weapon, respectfully.

I’ll cover more about Generics on request. For now, let’s co back to our design.

Our TransportMechanism needs to return an appropriate FactoryRoom:

C#

public abstract FactoryRoom GetFactoryRoom();

Java

public abstract E getFactoryRoom();

So, what actually happens when a WorkerDrone moves RobotParts to a FactoryRoom? The WorkerDrone needs to enter the FactoryRoom, and then offload its components into the FactoryRoom:

C#

        public void EnterRoom() {
            _factoryRoom = GetFactoryRoom();
            _factoryRoom.AddTransportationMechanism(this);
        }

        public FactoryRoom OffLoadRobotParts(List&lt;RobotPart&gt; robotParts) {
            if (_factoryRoom == null) {
                EnterRoom();
            }
            _factoryRoom.SetRobotParts(new List&lt;RobotPart&gt;(robotParts));
            robotParts.Clear();

            return _factoryRoom;
        }

Java

    public void enterRoom() {
        _factoryRoom = getFactoryRoom();
        _factoryRoom.addTransportationMechanism(this);
    }

    public E offLoadRobotParts(List&lt;U&gt;robotParts) {
        if (_factoryRoom == null) {
            enterRoom();
        }
        _factoryRoom.setRobotParts(new ArrayList&lt;U&gt;(robotParts));
        robotParts.clear();

        return _factoryRoom;
    }

Here is a breakdown of what’s happening:

Our TransportMechanism returns a FactoryRoom implementation, based on the RobotPart carried by the WorkerDrone, and then the FactoryRoom adds the TransportationMechanism to its list of occupants:

C#

        public void AddTransportationMechanism(TransportMechanism transportMechanism) {
            _transportMechanisms.Add(transportMechanism);
        }

Java

    public void addTransportationMechanism(transportMechanism transportMechanism) {
        _transportMechanisms.add(transportMechanism);
    }

OK. Now our WorkerDrone has entered the FactoryRoom. It should now offload its RobotParts via the OffLoadRobotParts method above. Here’s what’s happening:

  • A safeguard is in place to ensure that the WorkerDrone enters the room before offloading components
  • The WorkerDrones RobotPart payload is copied to the FactoryRoom
  • The WorkerDrones RobotPart payload is emptied

“Why the safeguard? Can’t we just explicitly call the EnterRoom method before calling OffLoadRobotParts?”

Yes, but let’s offer another layer of protection for consuming applications. After all, if a developer forgot to ensure that a WorkerDrone enters a room before offloading RobotParts, the system would crash. Even if we implemented counter-measures to prevent this, our WorkerDrone would effectively dump its payload somewhere in the Factory.

What do you expect me to do now?!?

What do you expect me to do now?!?

Our WorkerDrone is now housed within an appropriate FactoryRoom, and has offloaded its RobotParts to that FactoryRoom.

“So how did we get here?”

Let’s examine the associated Unit Test:

C#

        [Test]
        public void WorkerDroneOffLoadsRobotParts() {
            WorkerDrone workerDrone = new MockedWorkerDrone();
            RobotPart robotPart = new MockedRobotPart(RobotPartCategory.Assembly);

            workerDrone.PickUpRobotPart(robotPart);
            var factoryRoom = workerDrone.TransportRobotParts();

            Assert.AreEqual(0, workerDrone.GetRobotPartCount());
            Assert.AreEqual(1, factoryRoom.GetRobotPartCount());
            Assert.IsInstanceOf&lt;AssemblyRoom&gt;(factoryRoom);

            robotPart = new MockedRobotPart(RobotPartCategory.Weapon);

            workerDrone.PickUpRobotPart(robotPart);
            factoryRoom = workerDrone.TransportRobotParts();

            Assert.AreEqual(0, workerDrone.GetRobotPartCount());
            Assert.AreEqual(1, factoryRoom.GetRobotPartCount());
            Assert.IsInstanceOf&lt;Armoury&gt;(factoryRoom);
        }

Java

    @Test
    public void workerDroneOffLoadsRobotParts() {
        workerDrone workerDrone = new mockedWorkerDrone();
        robotPart robotPart = new mockedRobotPart(robotPartCategory.assembly);

        workerDrone.pickUpRobotPart(robotPart);
        factoryRoom factoryRoom = workerDrone.transportRobotParts();

        assertEquals(0, workerDrone.getRobotPartCount());
        assertEquals(1, factoryRoom.getRobotPartCount());
        assertThat(factoryRoom, instanceOf(assemblyRoom.class));

        robotPart = new mockedRobotPart(robotPartCategory.weapon);

        workerDrone.pickUpRobotPart(robotPart);
        factoryRoom = workerDrone.transportRobotParts();

        assertEquals(0, workerDrone.getRobotPartCount());
        assertEquals(1, factoryRoom.getRobotPartCount());
        assertThat(factoryRoom, instanceOf(armoury.class));
    }

Notice out first pair of Asserts. We’ve transported the RobotParts from WorkerDrone to FactoryRoom, and simply assert that both components contain the correct number of RobotParts. Next, we assert that our TransportMechanism has selected the correct FactoryRoom instance; Weapons go to the Armoury, Assemblies to the AssemblyRoom.

“Great. I just looked at those FactoryRoom and RobotPart implementations. They’re all implementations of abstractions. Why didn’t you use interfaces, instead of abstract classes?”

There are 2 reasons for this:

  1. Our abstractions contain methods that need to be accessed by the implementations
  2. Our implementations are instances of our abstractions from a real-world perspective – they don’t just exhibit a set of behaviours.

It’s worth noting that a class can derive from a single class only in both C# and Java, whereas a class can derive from many interfaces as you like.

The next tutorial in the series will focus on returning our WorkerDrones to the DeliveryBay, and outlining the structure of RobotBuilders.

Connect with me:

RSSGitHubTwitter
LinkedInYouTubeGoogle+

Object Oriented, Test Driven Design in C# and Java: A Practical Example Part #2

Download the code in C#
Download the code in Java

Check out my interview on .NET Rocks! – TDD on .NET and Java with Paul Mooney

For a brief overview, please refer to this post.

Following on from the previous tutorial, where we looked at Supplier and DeliveryBay objects, let’s move on to WorkerDrones.

Once again, here is our narrative:

“Mechs with Big Guns” is a factory that produces large, robotic vehicles designed to shoot other large, robotic vehicles. Robots are composed of several robotic parts, delivered by suppliers. Parts are loaded into a delivery bay, and are transported by worker drones to various rooms; functional parts such as arms, legs, etc., are dispatched to an assembly room. Guns and explosives are dispatched to an armoury.
The factory hosts many worker drones to assemble the robots. These drones will specialise in the construction of 1 specific robot, and will require all parts that make up that robot in order to build it. Once the drone has acquired all parts, it will enter the assembly room and build the robot. Newly built robots are transported to the armoury where waiting drones outfit them with guns. From time to time, two robots will randomly be selected from the armoury, and will engage one another in the arena, an advanced testing-ground in the factory. The winning robot will be repaired in the arena by repair drones. Its design will be promoted on a leader board, tracking each design and their associated victories.

Worker Drones

Worker Drones have several functions, as per the narrative, so we’re going to tackle the implementation one step at a time. It seems that at a fundamental level, the drones need to be able to differentiate between different RobotParts. For example, consider a situation in which the following set of robotic legs arrive in the DeliveryBay:

Walker Robot, Vertical

In that case, our WorkerDrone needs to transport these to the AssemblyRoom. However, check out the guns on this guy!!!

White Mech weapon on a white background

Those weapons, should they arrive in the DeliveryBay, need to be transported to the Armoury.

Essentially, WorkerDrone behaviour depends on the category that each RobotPart is associated with, and can change at runtime. Consider the following scenario:

  1. WorkerDrone enters DeliveryBay and collects a RobotPart
  2. The RobotPart is identified as an item that belongs in the AssemblyRoom
  3. WorkerDrone transports the RobotPart to the AssemblyRoom
  4. WorkerDrone picks up the next RobotPart, which happens to be a Weapon
  5. WorkerDrone delivers this to the Armoury

WorkerDrones have 2 separate types of behaviour that govern RobotPart transportation. This is commonly known as the Strategy Design Pattern.

“Wait, that actually sounds like a Bridge pattern to me!”

Structurally, they are both the same. The difference is in their implementation. A Bridge is a behaviour that is set at design-time, and remains constant. A Strategy on the other hand, can change at runtime.

What we’re essentially doing is abstracting WorkerDrone transportation behaviour to separate classes that share the same abstraction. Our WorkerDrone simply chooses the correct implementation to suit a given scenario, and the implementation does the work.

Let’s keep thiings simple for the moment; we won’t actually implement the act of transporting RobotParts, we’ll simply implement the fundamental components involved.

To start, we need to identify RobotParts. So let’s tag them with a specific category – either Assembly, or Weapon. First, we need to define these categories:

C#

    public enum RobotPartCategory {
        Assembly,
        Weapon
    }

Java

public enum robotPartCategory {
    assembly,
    weapon
}

Now, we modify our RobotPart astraction to accept either of these categories:

C#

    public abstract class RobotPart {
        private readonly RobotPartCategory _robotPartCategory;

        public RobotPartCategory RobotPartCategory { get { return _robotPartCategory; } }

        protected RobotPart(RobotPartCategory robotPartCategory) {
            _robotPartCategory = robotPartCategory;
        }
    }

Java

public abstract class robotPart {
    protected robotPartCategory robotPartCategory;

    public robotPartCategory getRobotPartCategory() {
        return robotPartCategory;
    }

    protected robotPart(robotPartCategory robotPartCategory) {
        this.robotPartCategory = robotPartCategory;
    }
}

So far, so good. We spoke about different transportation behaviours. So let’s first create the abstraction:

C#

    public abstract class TransportMechanism {}

Java

public abstract class transportMechanism {}

And both implementations; Assembly and Weapon. Remember: we’re not implementing any logic in these classes yet – we first need to ensure that our WorkerDrone can apply the correct behaviour based on each RobotPart:

C#

    public class AssemblyRoomTransportMechanism : TransportMechanism {}
    public class ArmouryTransportMechanism : TransportMechanism {}

Java

public class assemblyRoomTransportMechanism extends transportMechanism {}
public class armouryTransportMechanism extends transportMechanism {}

Now let’s implement a simple method that allows our WorkerDrone to choose the manner in which it will transport a given RobotPart, by first examining that RobotPart

C#

    public abstract class WorkerDrone {
        public TransportMechanism TransportMechanism { get; private set; }

        public void IdentifyRobotPart(RobotPart robotPart) {
            switch (robotPart.RobotPartCategory) {
                case RobotPartCategory.Assembly:
                    TransportMechanism = new AssemblyRoomTransportMechanism();
                    break;
                case RobotPartCategory.Weapon:
                    TransportMechanism = new ArmouryTransportMechanism();
                    break;
            }
        }
    }

Java

public class workerDrone {
    private transportMechanism _transportMechanism;

    public transportMechanism getTransportMechanism() {
        return _transportMechanism;
    }

    public void identifyRobotPart(robotPart robotPart) {
        switch (robotPart.getRobotPartCategory()) {
            case assembly:
                _transportMechanism = new assemblyRoomTransportMechanism();
                break;
            case weapon:
                _transportMechanism = new armouryTransportMechanism();
                break;
        }
    }
}

As usual, our WorkerDrone is an abstraction and we apply a mocked implementation in our associated unit test:

C#

    public void WorkerDroneIdentifiesRobotPart() {
            var robotPart = new MockedRobotPart(RobotPartCategory.Assembly);
            var workerDrone = new MockedWorkerDrone();

            workerDrone.IdentifyRobotPart(robotPart);
            Assert.IsInstanceOf<AssemblyRoomTransportMechanism>(workerDrone.TransportMechanism);

            robotPart = new MockedRobotPart(RobotPartCategory.Weapon);

            workerDrone.IdentifyRobotPart(robotPart);
            Assert.IsInstanceOf<ArmouryTransportMechanism>(workerDrone.TransportMechanism);
        }

Java

    public void workerDroneIdentifiesRobotPart() {
        robotPart robotPart = new mockedRobotPart(robotPartCategory.assembly);
        workerDrone workerDrone = new mockedWorkerDrone();

        workerDrone.identifyRobotPart(robotPart);
        assertThat(workerDrone.getTransportMechanism(), instanceOf(assemblyRoomTransportMechanism.class));

        robotPart = new mockedRobotPart(robotPartCategory.weapon);

        workerDrone.identifyRobotPart(robotPart);
        assertThat(workerDrone.getTransportMechanism(), instanceOf(armouryTransportMechanism.class));
    }

Let’s walk through this test:

  1. We instnantiate a new RobotPart as an Assembly
  2. We instatiate our WorkerDrone
  3. The WorkerDrone examines the RobotPart and instantiates its TransportationMechanism appropriately
  4. We assert that the correct TransportationMechanism behavioural implementation has been applied for the Assembly RobotPart
  5. We repeat the process for a Weapon RobotPart

In the next tutorial, we’ll implement the logic involved in transporting RobotParts from the DeliveryRoom to both AssemblyRoom and Armoury.

Connect with me:

RSSGitHubTwitter
LinkedInYouTubeGoogle+