software development for the
existentially challenged
Older | Newer Older | Newer
"Replace Type Code with Class": The Evils of Untyped Parameters
comment share
I recently heard about a horrible bug in production code that could have been prevented through a very simple coding practice: Using explictly typed classes instead of type codes. I'm pulling that first part of the title from Martin Fowler's awesome "Refactoring: Improving the Design of Existing Code".

The bug went something like this:

A bunch of client code called a particular method, which took two type codes. For the sake of example, we'll say that they represented, respectively, different meats and different vegetables. The method was intended to construct a balanced Meal object.
public Meal makeBalancedMeal(int vegCode, int meatCode) ...
At some point, the method gained an alternate, improved signature, and the old signature was deprecated and eventually removed. The new signature was this:
public Meal makeBalancedMeal(Vegetable veg, Meat, meat)...
This was an awesome step forward. It has the advantages of:

  • Clarity: you can instantly look at the signature and know what the variables mean
  • Type safety: you don't mix up your meat and vegetables

    During the refactoring, the writers of the client code realized that they had a lot of calls to the original method signature and they became intimidated. To use the new call, they would have to change a lot of lines of code to pass the new types. Because they had already wrapped the call with a "utility" method:
    public static Meal getMealWithoutWashingHands( int vegCode, int meatCode)
    Inside this method, they created Vegetable and Meat objects and passed them to the newly refactored makeBalancedMeal object. The problem is that they screwed it up:
    public static Meal getMealWithoutWashingHands( int vegCode, int meatCode)
    Vegetable veg = new Vegetable(meatCode);
    Meat meat = new Meat(vegetableCode);
    return makeBalancedMeal(veg, meat);
    Reversing the codes wasn't always a problem. Sometimes it created a perfectly valid combination. Other times, though it broke horribly. Not surprisingly, hilarity ensued.

    Had they stuck with passing the typed objects, they could not have had this problem. They might have made the mistake elsewhere (at some point, you do have to deal with the int values), but they wouldn't have made it here, in new and relatively untested code.

    Why did this come about? I blame the system. As usual, there is the institutional fear of refactoring as "introducing too much change and creating bugs". In fact, done sanely, it prevents bugs. The developers who knew that changing from Type Code to Class was a good idea had been beaten down by management to not do anything so bold on a large scale. Instead, they ducked the issue and added yet more code to do exactly the same broken thing.

    As might be expected, the results were horrible. The code produced meals such as "Chicken Neck and Radishes" and "Beef Tongue and Jicama". This caused issues with actual customers in production, costing the company Real Money.


    Post a Comment

    What is this site?!

    t (a professional software developer for a big company) writes about software development and stuff. Unix, Java, Groovy, OS X, and lots of open source libraries and tools.