Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it acceptable to use exceptions instead of verbose null-checks?

I recenly encountered this problem in a project: There's a chain of nested objects, e.g.: class A contains an instance variable of class B, which in turns has an instance variable of class C, ..., until we have a node in the tree of class Z.

     -----      -----      -----      -----               ----- 
     | A | ---> | B | ---> | C | ---> | D | ---> ... ---> | Z |
     -----      -----      -----      -----               -----  

Each class provides getters and setters for its members. The parent A instance is created by an XML parser, and it is legal for any object in the chain to be null.

Now imagine that at a certain point in the application, we have a reference to an A instance, and only if it contains a Z object, we must invoke a method on it. Using regular checks, we get this code:

    A parentObject;

    if(parentObject.getB() != null &&
        parentObject.getB().getC() != null &&
        parentObject.getB().getC().getD() != null &&
        parentObject.getB().getC().getD().getE() != null &&
        ...
        parentObject.getB().getC().getD().getE().get...getZ() != null){
            parentObject.getB().getC().getD().getE().get...getZ().doSomething();
    }

I know that exceptions should not be used for ordinary control flow, but instead of the previous code, I have seen some programmers doing this:

    try {
        parentObject.getB().getC().getD().getE().get...getZ().doSomething();
    } catch (NullPointerException e){}

The problem with this code is that it may be confuse when maintaining it, since it doesn't show clearly which objects are allowed to be null. But on the other hand is much more concise and less "telescopic".

Is it an acceptable to do this to save development time? How could the API be redesigned to avoid this problem?

The only thing I can think of to avoid the long null checking is to provide void instances of the nested objects and providing isValid methods for each one of them, but wouldn't this create a lot of innecesary objects in memory?

(I've used Java code, but the same question can apply to C# properties)

Thanks.

like image 714
Mister Smith Avatar asked Jan 30 '12 16:01

Mister Smith


1 Answers

It is bad design if parentObject needs to know that A contains a B which contains a C wich contains.... That way, everything is coupled to everything. You should have a look at the law of demeter: http://en.wikipedia.org/wiki/Law_Of_Demeter

parentObject should only call methods on its instance variable B. So, B should provide a method that allows for the decision, e.g.

public class A {
  private B myB;
  //...
  public boolean isItValidToDoSomething(){
    if(myB!=null){
      return myB.isItValidToDoSomething();
    }else{
      return false;
    }
  }
}

Eventually, at the level of Z, the method has to return true.

Imho, saving development time is never a reason for tolerating problems in the design. Sooner or later these problems will steal you more time than it would have taken to fix the problems in the first place

like image 91
joergl Avatar answered Sep 19 '22 05:09

joergl