This is the log of a sample project from a small band of software engineers eager to learn better ways of working and new technologies. We've decided to use .NET 3.0 to create a Battleships game.

The Quest For The Perfect Project

Friday 23 February 2007

Evolutionary Design - keep it simple

Multiplayer Battleships is giving us an avenue to play around with some Agile techniques that have interested us. One of those is surrounding how we design the modules we're implementing. The idea is to only do as much design as necessary to get a task completed. You shouldn't design for the future, we do need to be aware of the direction that we're heading in, but we shouldn't start churning out all this code to cover the "what if" scenario.

I'm starting to see the benefits of this way of thinking already. At the beginning of a project, you can't really expect to fully understand all the implications that lie ahead so having a mammoth design task to plan the whole system is often flawed. I'm using the technique to have evolutionary design and already I've started to see why this is better than spending weeks planning and designing early on. I'm new to writing games, especially games that have the added complexity of being multiplayer. The last game I wrote was some little console C++ horse racing game 10 years ago when I was learning to program (whoa, I feel old!).

I'm starting to realise that you need to think in a different mindset when trying to develop a multiplayer game and I'm very fortunate that my other half loves developing games, so I've got someone to bounce my ideas off of. Last night we had a chat because I keep finding that I'm having to refactor continually because something I initially thought was a great implementation, suddenly started to fall over when I considered how it would work in a multiplayer environment. I've identified that my design has been subtly flawed for a while, so it's great that I had designed the whole game from day 1 because at the end of the day, I've got several learning curves going on here. I'm starting to think my lack of knowledge around multiplayer games is the biggest.

For example:

I came up with this basic idea about a ship having health and whenever it received an attack, the health would decrease. I was happily testing the process attack code when I started to dream up more complex tests that verified several players attacking the same ship. I needed a way to model this in code and as it currently stood, my design was flawed. It wasn't a terrible design, but it was just wrong for the multiplayer aspect.

A similar issue arose when I started thinking about the board representation. I couldn't stop players from placing ships on certain coordinates because it would alert them to the probability of there being another ship there. As a result, ships can occupy the same coordinates in Multiplayer Battleships. I'd initially not really thought about this and found myself once again revisiting the design board to make this possible in a multiplayer environment.

The list goes on, but I'm finally turning the corner and realising that I need to approach my evolving design from a multiplayer perspective early on, otherwise I'll spend a lot more of my limited time rewriting and rewriting.

A great article that has helped me along the way is: "Is Design Dead by Martin Fowler"

Labels: ,

Thursday 8 February 2007

Getting into the swing of it

I'm finally coding and it feels great to get back into C# and .NET land. The first few weeks of this project were spent discussing and creating a rough product backlog with details of tasks we'd like to do. I was concerned that with us trying to do "the perfect project" that we might end up in analysis paralysis and never actually get started, but that doesn't seem to be the case.

I've just started fleshing out the domain classes, it's very early stages - but it's coding at last! I was determined to do things properly though. I've not really experienced much TDD in .NET it wasn't until I started writing Java that I became an Agile adopter. TestDriven.NET has various nuances to the TDD framework that I was used to using in Java but I'm slowly picking it all up.

When you're up against deadlines at work, you sometimes take the easy option and start coding straight away not really doing the whole TDD properly, just tacking on the unit tests afterwards. I did however make more of an effort to write a test first when we came across bugs because it was a great way to verify that you'd actually fixed it.

One simple TDD example from Battleships:

I've identified one of the domain classes to be a ship and before I even created the Ship class, I created the test class initialising x and y coordinates for the ship.
[TestFixture]
public class ShipTest
{
   [Test]
   public void ConstructShip()
   {
       Ship ship = new Ship(6, 8);
       Assert.AreEqual(6, ship.X);
       Assert.AreEqual(8, ship.Y);
   }
}
The test doesn't compile until I expand this further and create the Ship class. In true TDD style, you'd literally do a compile after each stage.
  1. Construct the ship.
  2. Fix compile errors by creating a ship class and basic constructor.
  3. Test for some values (x and y coordinates).
  4. Modify the ship to give you the coordinates.
public class Ship
{
   /// <summary>
   /// The X coordinate on the board for this ship
   /// </summary>
   int x;
   public int X { get { return x; } }

   /// <summary>
   /// The Y coordinate on the board for this ship
   /// </summary>
   int y;
   public int Y { get { return y; } }

   public Ship(int x, int y)
   {
       this.x = x;
       this.y = y;
   }
}
Now that we have created the class, the unit test to construct a ship works. It's progressed from there, in that we now have a length for the ship and an orientation value, but this just demonstrates how basic the unit tests were at the very beginning.
I am really starting to see the benefits of doing it properly though. I've been quite strict on myself, even with these straightforward domain classes that I'm creating at the moment. I'm writing a test even before I've created the class and although at first I felt a bit silly, I stuck at it and it's now really good fun. I'm seeing the benefits already and I'm confident that the code I'm producing is of a higher standard than if I'd not had unit tests at all. You spot the errors quickly because it's staring you right in the eyes when you get failed unit tests.

The last time I looked at C#, it was in .NET 1.1. I'm actually finding it a lot easier to works with C# 2 and the .NET 2.0 framework after my brief experiences with Java. I'd completely forgotten about the old way of using the .NET collections and I slipped right into the groove with C# generics - they're just fabulous.

I'm so glad Microsoft have taken a few hints from Eclipse, the IDE is much better than 2003, very slick - though I do miss the organise imports. So if you know any of the Microsoft IDE developers, give them a little nudge from me ;).

All in all, it's lovely to be back in .NET land and I can't wait until this project really gets going.

Emma

Labels: