到处都是空指针,因为数据突然稀疏

时间:2009-11-05 21:20:19

标签: java refactoring nullpointerexception

有人设计了依赖于完整数据的代码; XML始终具有每个元素。数据源现在发送稀疏XML;如果之前它已经空了,那么它现在已经丢失了。因此,是时候在修复错误的同时进行重构了。

这样有100多行代码:

functionDoSomething(foo, bar, getRoot().getChild("1").getChild("A").
    getChild("oo").getContent());

除此之外,getChild(“A”)可能会返回null。或者任何getChild(xxx)方法都可以。

作为一个额外的转折,实际上有四种不同的方法,而不是getChild(),它们只能在某些订单中出现。有人提出了一个varargs调用,这不是一个坏主意,但不会像我想的那样干净利落。

清洁这个最快的方法是什么?最好的?建议在每条线附近“尝试/捕捉”,但男人,那是丑陋的。将上述方法的第三个参数分解为它自己的函数可以起作用......但这需要100多个新方法,这些方法感觉很难看,尽管不那么简单。

getChild(xxx)调用的数量介于每行6到10之间,没有固定的深度。也没有办法为此获得正确的DTD;事情将在以后没有事先抬头的情况下添加,并且当发生这种情况时我更喜欢日志中的警告,需要优雅地处理XML中的额外行。

想法?

getChild()实际上是一种方便的方法。我想到的最简洁的方法是让方便方法返回一个有效的Child对象,但让那个“空”Child的getContent()总是返回“”。

6 个答案:

答案 0 :(得分:9)

请考虑使用XPATH而不是这个混乱。

答案 1 :(得分:8)

你所描述的(返回一个特殊的子对象)是NullObject模式的一种形式,这可能是最好的解决方案。

答案 2 :(得分:2)

解决方案是使用XML的DTD文件。它验证您的XML文件,因此当A是必需的时,getChild("A")不会返回null。

答案 3 :(得分:2)

怎么样:

private Content getChildContent(Node root, String... path) {
    Node target = root;
    for ( String pathElement : path ) {
         Node child = target.getChild(pathElement);
         if ( child == null ) 
            return null; // or whatever you should do

         target = child;
    }

    return target.getContent();

}

用作

functionDoSomething(foo, bar, getChildContent(root, "1", "A", "oo"));

答案 4 :(得分:2)

您的问题可能是设计问题:Law of Demeter

如果没有,您可以使用Option type之类的内容将getChild的返回类型更改为Option< Node>:

for(Node r : getRoot())
  for(Node c1 : r.getChild("1"))
    for(Node c2: c1.getChild("A"))
      return c2.getChild("oo")

这是有效的,因为Option实现了Iterable,它将在未定义返回值时中止。这与Scala类似,它可以在单个表达式中表达。

另一个优点是您可以定义永不返回空值的接口。使用Option类型,您可以在接口定义中声明返回值可能未定义,客户端可以决定如何处理它。


答案 5 :(得分:0)

如果它总是向下钻到大致相同的级别,你可以使用Eclipse重构代码,并且它会自动更改看起来相同的每一行。

通过这种方式,您可以将方法修改为更智能,而不是单独修改每一行