Friday, June 11, 2010

Casting in Java Leads to DRY Violations

The Don't Repeat Yourself principle states that you should not have any duplication in your code. Code duplication makes the code harder to maintain. In Java, one finds often code like this:

  String extractValue(IType parameter) {
    if (parameter instanceof ILiteralType) {
      ILiteralType literalType = (ILiteralType)parameter;
      return literlType.getValue();    
    }
    return null;
  }

Of course, it is best to avoid casting completely. However, in some cases this is not possible. When casting, the code must first check if an object is an instance of the desired type using the instanceof operator. If the test succeeds, the object can be casted to the type. The problem is that you have to specify the type twice which is a repetition and therefore violates DRY. Whenever you change the type in the instanceof expression you need to change the cast in sync. Failing to do so will result in an error that occurs only at run time.

One can circumvent this problem by using a little static helper function (we have put it in a class named ObjectUtil):


  public static T castOrNull(Object o, Class clazz) {
    if (!clazz.isInstance(o)) return null;
    return clazz.cast(o);
  }

With the help of this function the code above becomes:

  String extractValue(IType parameter) {
    ILiteralType literalType =
          ObjectUtil.castOrNull(parameter, ILiteralType.class);
    if (literaType == null) {
      return null;
    }
    return literalType.getValue();
  }

Now, the type is specified only once as argument to the castOrNull method.

(The attentive reader will object that ILiteralType is still specified twice, once as argument to castOrNull and once when defining the variable literalType. So effectively, we have only two occurrences instead of three in the original code. However, an inconsistency of the two remaining occurrences will be detected by the compiler and is therefore far fewer problematic!)

No comments:

Post a Comment