August 15, 2008

Running a marathon in your bare feet

I just read this excellent blog post and it reminded me of something I tried to
describe to some of my team mates.

http://blog.objectmentor.com/articles/2008/08/14/quintessence-the-fif...

My story goes something like this:

A marathon runner realizes that he has a couple of small stones in his
shoes right before the race begins, so he takes off his shoes to get
them out. While he is doing this the race starts.

His coach has always trained him to run the race "10 feet at a time";
just focus on getting through the next 10 feet and the race will take
care of itself.

Since the runner is very literal he considers how he can run the next
10 feet the fastest: 1) Spend 1 minute putting his shoes on 2) Start
running. He decides to start running and is happy with how much
progress he has made in the first 5 seconds of the race.

After a couple of miles, the runner is starting to slow down. His feet
are cracked and torn from running on the rough pavement. He is BEHIND.
He considers stopping and putting his shoes on, but DOES NOT HAVE
ENOUGH TIME. He is behind and just need to keep getting the next 10
feet of the race run.

And so it goes...

This is exactly what focusing on the short term at the expense of the
real time-frame of the project feels like to me. We make decisions
that help no one and that we know are dumb just to get a feature done
this week.

See also, "Important vs Urgent".

August 01, 2008

Link: Taxonomy of Code Smells

One of my personal goals is improving my mental mapping of "code smells" to tools that I can use to make them less smelly. This is a great Taxonomy of Code Smells.

I'll start exploring the mappings of these smells to specific tools to combat them in the near future.

July 18, 2008

Events vs. Messages

The terms event and message seem to be used interchangeably by most programmers. These two concepts are quite different even if their implementations can be identical. In order to illustrate the differences, as I see them, I am going to evolve a simple code block from a procedural implementation, through a message-based implementation, and finally into an OO event-based implementation.

Procedural Approach

Here is a straightforward implementation of the feature “When a gun fires a bullet appropriate effects occur at the barrel of the gun.” This is implemented about how I would expect to see it in most game engines.

if (bulletFired)
{
    ParticleManager::createEmitter(gun.getMuzzlePosition(), “MuzzleFlash.xml”);
    SoundManager::playSound(
gun.getMuzzlePosition(), “ShotFired.snd”);
    TracerManager::createTracer(
gun.getMuzzlePosition(), “BulletTracer.xml”);
}

This implementation is tightly coupled with the three systems that do the work of making appropriate effects when the bullet is fired. It also displays little cohesion since if we follow this pattern there will be code that creates Emitters, Sounds, and Tracers spread all over the place.

Improved Procedural Approach

Even if we data drive which assets are used for the effects and inject the managers we still end up with code that is only slightly less coupled and slightly more cohesive:

if (bulletFired)
{
    mParticleManager.createEmitter(
gun.getMuzzlePosition(), mMuzzleFlashEmitter);
    mSoundManager.playSound(
gun.getMuzzlePosition(), mShotFiredSound);
    mTracerManager.createTracer(
gun.getMuzzlePosition(), mBulletTracer);
}

Procedural Messaging Approach

An approach that is often taken to reduce the coupling found is this type of code is to send messages. This is what I would expect the message-based version to look like:

if (bulletFired)
{
    CreateEmitterMessage emitterMessage(
gun.getMuzzlePosition(), mMuzzleFlashEmitter);
    mMessageManager.sendMessage(emitterMessage);

    PlaySoundMessage soundMessage(gun.getMuzzlePosition(), mShotFiredSound);
    mMessageManager.sendMessage(soundMessage);

    CreateTracerMessage tracerMessage(gun.getMuzzlePosition(), mBulletTracer);
    mMessageManager.sendMessage(tracerMessage);
}

While this removes #include dependency, there is still all of the conceptual coupling that the earlier version had. For instance, if the SoundManager changed to use ints instead of strings to identify sounds this code (as well as all code that played sounds) would have to change. Cohesion is just as low as it was in the previous examples for the same reasons.

I consider using messages this way to be analogous to run-time linking. The message type defines which function gets called and the message parameters correspond to the function parameters. This approach trades frame-rate for compile time without making the code significantly more flexible. Sometimes this is a good trade-off but it is rarely a clear win.

Object Oriented Message Sending

The basic OO/event-based could look like this:

if (bulletFired)
{
    LocationMessage bulletFiredMessage(BulletFiredMessageId,
gun.getMuzzlePosition());
    mMessageManager.sendMessage(
bulletFiredMessage);
}

This is obviously more cohesive because all of the code relates to the concept of a bullet firinf. It is also more loosely coupled because there is no #include or conceptual dependency on any of the systems that react to the event.

Events have characteristics that distinguish them from other types of messages:

1) They are ‘eventful’ in the sense that they only get sent when something special/exceptional happens.

2) They are named and parameterized in the language of the application from the user’s point of view. A user can understand the concept of a bullet firing but would never describe part of the results as “a tracer appears at the end of the gun muzzle”.

3) One message is sent per event.

4) The creator of the event does not require any particular result to happen because of the event being sent. They should also not be aware of how the event is being handled. This means that the payload of the event should not have anything to do with how the event is handled. The position of the gun muzzle is critical to describing the event, while the name of the sound to be played is not intrinsic to the event itself and belongs with the code that handles playing the sound.

Object Oriented Message Handling

Now we just need to handle the event. If you look back to the very first code snippet you will see something like this:

if (bulletFired)
{
   
ParticleManager::createEmitter(gun.getMuzzlePosition(), “MuzzleFlash.xml”);
}

This is a mapping of the detection of a particular condition to the creation of a particular particle emitter. In the OO code snippet we broke the mapping in half. The part that is handled is mapping the condition into a particular message. So all that is left to do is map that message to the creation of a particular particle emitter.

ParticleManager::ParticleManager(void)
{
    // We could easily data drive this is we want to
    mMessageToEffectMap[
BulletFiredMessageId] = “MuzzleFlash.xml”;
}

ParticleManager::handleMessage(const Message& message)
{
    MessageToEffectMap::iterator messageIdEffectPair = mMessageToEffectMap.find(message.Id());
    if (messageIdEffectPair != mMessageToEffectMap.end())
    {
        // I am using an ugly down-casting style messaging system for simplicity
        LocationMessage* locationMessage = static_cast< LocationMessage*> (&message);
        createEmitter(locationMessage->getLocation(), messageIdEffectPair.second());
    }
}

We can repeat this pattern for the Sound and Tracer systems. Each of these classes is cohesive because all of the code that relates to its domain lives within that class and is loosely coupled because each class deals only with concepts within its domain.

This pattern has immediate benefit beyond the vague coupling and cohesion ones:

  • It is easy to data drive because all of the map initialization happens in one place.
  • It removes code and data duplication because multiple objects do not have to remember the mapping from the same condition to the same result.
  • It is easy to refactor, remove, or replace any of these systems because they are the only classes that understand the details of how a {Sound/Particle Emitter/Tracer} is created.

Patterns like this tend to take a little more effort when adding the first (or second) feature that uses them, but my experience has been that they quickly pay off by making all later features easier to implement.

July 17, 2008

Link: Highly cohesive and loosely coupled code

I'm planning to write a group of related posts that describe techniques to write cohesive and loosely coupled code. I strongly believe that these are the two critical measures of flexible code.

Since this topic has already been covered well by people much smarter than me, I'll just point you to this wonderful description of Coupling and Cohesion.

July 15, 2008

Interface parameters vs. Construction parameters

I'm going to start with a simple idea for my first post so I can get the hang of things before I jump into tougher topics. My intent is to address issues I have found in real code.

A programmer is working on a new feature and in order to make that feature work he needs to change a currently existing method Work in class Foo. His change makes that method use a reference to another class Bar. There are lots of ways that Foo can get access to the Bar it needs. The two I am going to focus on are "Passing the Reference into the Method" and "Passing the Reference into the Constructor and Storing as a Member".

Passing the Reference into the Method
This approach is easy to implement and the obvious way to get the reference. Unfortunately, it also changes Foo's interface. This is a 'bad thing' if Foo implements an interface (IFoo) that is also implemented by other classes. It also means that the method might be lying about what it needs to do its work.

By adding the Bar reference to its parameter list, Foo is saying that in order for the Work concept to happen anyone who implements it will need a Bar. If this is the case then, of course, Bar should be passed in to Foo. Otherwise, I believe, it should not.

If you add Bar to IFoo::Work (which you will have to do in order to take advantage of polymorphism), all classes that implement IFoo will have to accept that parameters also. More importantly, any class that calls IFoo::Work will have to provide a Bar reference. If the programmer were to repeat this pattern then IFoo::Work would have a reference to every object used by all implementations of Work. Clearly this is far from ideal and significantly increases the complexity of our program. What is the alternative?

Passing the Reference into the Constructor and Storing as a Member
If the programmer passes the reference to Bar into the constructor of Foo and stores it as a member variable then he can use it freely in Work or any other method that happens to need it. The only real downsides of this approach are that you need to have the reference available when you construct each Foo and it also consumes a little bit of extra memory for each instance of Foo.

An added benefit of moving parameters to the constructor is that the parameters of the Work method are more likely to fit into available registers when it is invoked. Since constructors are generally called less often than other methods this benefit is likely to make your program run faster.

The point I am trying to make is that an interface should only have the methods that are intrinsic to the concept that the class embodies. Likewise, the parameters on a method should only be the ones needed to do the work described by the method name.