The Urge To Jump To Conclusions

tiistaina, tammikuuta 08, 2008

I’m sitting on my couch with a huge headache, the results of a cold or flu or a tumor or something. Its not going away anytime soon so I figured I would type until the pain medication kicks in. Thats about 20 minutes form now, I hope.
I was thinking about a recent conversation where a friend asked me to look at some code. He was pissed because it looked really complex and added nothing. He felt is was just adding a lot of new declarations and complexity that made no sense. So he made a brief rant and then showed me the code.
For a moment I was perplexed by what I was seeing. My eyes went to a clause in the declaration of a Java class and it looked pretty ugly. It had lots of greater-than and less-than symbols and stretched across a few lines of code. At first I thought that there was almost certainly someone over-engineering.
And then I looked again and realized that the original developer was actually being rather smart about his declarations and type safety. The original developer was doing something like the following example:

// Abstract Base Classes
public abstract class Animal<S extends FoodPreferences, T extends ForagingBehavior<S> >
{
S foodPreferences;
T foragingBehavior;
public S getFoodPreferences()
{
return foodPreferences;
}
public void setFoodPreferences(S foodPreferences)
{
this.foodPreferences = foodPreferences;
}
public T getForagingBehavior()
{
return foragingBehavior;
}
public void setForagingBehavior(T foragingBehavior)
{
this.foragingBehavior = foragingBehavior;
}
public abstract void forage();
}

public class FoodPreferences
{

}

public class ForagingBehavior<S extends FoodPreferences>
{
S foodPreferences;

public S getFoodPreferences()
{
return foodPreferences;
}

public void setFoodPreferences(S foodPreferences)
{
this.foodPreferences = foodPreferences;
}
}

// Concrete Implementations
public class WombatFoodPreferences extends FoodPreferences
{
public boolean wantsFruit(){ return true;};
}

public class WombatForagingBehavior<S extends WombatFoodPreferences> extendsForagingBehavior<S>
{

}

public class Wombat extends Animal<WombatFoodPreferences, WombatForagingBehavior<WombatFoodPreferences>>
{
public void forage()
{
// concrete implementation
// Note: no casting to the concrete type
this.getFoodPreferences().wantsFruit();
}
}
There is some pretty heavy use of Java generics here. It works surprisingly well, but you do have to look at it carefully to understand what is happening. This example uses generics to define common classes that can have data types on relevant to the concrete implementation. This is really useful when you have a lot of different children off a common parent class. They all have shared data types and such, but those data types may also be very tightly tied to the child class. The use of generics in this case allow you to generically associate concrete child types without adding a lot of casting and type checking at run time.
This kind of code looks bad at first and then you realize that it actually simplifies the code in a single swipe. First, it eliminates a lot of casting that always makes code harder to read. Second, it ensures type safety. The original developer did a really good job of cleaning up some complex code. I sent the original developer en email telling him that too.
I then spent 5 minutes explaining what was going on and my friend responded with “Oh, that’s really good.” A grand total of ten minutes of conversation and a good developer’s code went from bad to great.

You Might Also Like

0 comments