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

前端 未结 9 2380
刺人心
刺人心 2020-12-28 21:51

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 v

相关标签:
9条回答
  • 2020-12-28 22:22

    Using exceptions seem a poor fit here. What if one of the getters contained non-trivial logic, and threw a NullPointerException? Your code would swallow that exception without intending to. On a related note, your code samples exhibit different behaviour if parentObject is null.

    Also, there really is no need to "telescope":

    public Z findZ(A a) {
        if (a == null) return null;
        B b = a.getB();
        if (b == null) return null;
        C c = b.getC();
        if (c == null) return null;
        D d = c.getD();
        if (d == null) return null;
        return d.getZ();
    }
    
    0 讨论(0)
  • 2020-12-28 22:25

    I think you could provide static isValid methods on each class, for example for class A that would be:

    public class A {
    ...
      public static boolean isValid (A obj) {
        return obj != null && B.isValid(obj.getB());
      }
    ...
    }
    

    And so on. Then you would have:

    A parentObject;
    
    if (A.isValid(parentObject)) {
      // whatever
    }
    

    However, although I won't get into you business I must say that such a method chaining does not say anything good about the design; maybe it's a sign of need for refactoring.

    0 讨论(0)
  • 2020-12-28 22:27

    It's bad practice to use Exceptions here.

    There's a hint in the name: Exceptions are for exceptional circumstances (i.e. unexpected) . If nulls are expected values, then encountering them is not exceptional.

    Instead, I'd have a look at the class hierarchy and try to understand why such deep access chaining needs to happen. This seems like a big design issue, you shouldn't normally expect the caller to construct calls using deep knowledge of the structure of objects hidden within class A.

    Questions you could ask:

    • Why does the caller need to doSomething() with the Z object anyway? Why not put the doSomething() on class A? This could propagate doSomething() down the chain if needed and if the relevant field was not null....
    • What does a null mean if it exists in this chain? The meaning of a null will suggest what business logic should be employed to handle it.... which could be different at each level.

    Overall, I suspect the right answer is to put doSomething() on each level of the heirarchy and have the implementation something like:

    class A {
      ...
      public void doSomething() {
        B b=getB();
        if (b!=null) {
          b.doSomething();
        } else {
          // do default action in case of null B value
        }
      }
    }
    

    If you do this, then the API user only has to call a.doSomething(), and you have the added bonus that you can specify different default actions for a null value at each level.

    0 讨论(0)
提交回复
热议问题