PMD - 使用三元运算符的NPath复杂度非常高(?

时间:2011-02-22 15:11:59

标签: pmd

我正在使用PMD为项目生成一些代码质量报告 我不理解NPath复杂性检查的结果 我已经创建了一个dull类,它显示了结果(这不是真正的类,但它使用相同的模式):

import java.util.*;

public class SOFExample {

    private final Map<String, Date> magicMap = new HashMap<String, Date>();    
    protected static final long UNKNWOWN = 0L;
    private static final class MyCal { long aTime; long bTime; long cTime; long dTime;}

    public void usefullMethod(final List<MyCal> myCals) {

        final Date a = magicMap.get("a");
        final Date b = magicMap.get("b");
        final Date c = magicMap.get("c");
        final Date d = magicMap.get("d");

        final long aTime = a == null ? UNKNWOWN : a.getTime();
        final long bTime = b == null ? UNKNWOWN : b.getTime();
        final long cTime = c == null ? UNKNWOWN : c.getTime();
        final long dTime = d == null ? UNKNWOWN : d.getTime();

        for (MyCal myCal : myCals) {
            if(myCal.aTime == UNKNWOWN) myCal.aTime = aTime;
            if(myCal.bTime == UNKNWOWN) myCal.bTime = bTime;
            if(myCal.cTime == UNKNWOWN) myCal.cTime = cTime;
            if(myCal.dTime == UNKNWOWN) myCal.dTime = dTime;
        }
    }
}

PMD结果:

  

方法usefullMethod()的NPath复杂度为10625

如果我添加一个以相同方式初始化的新变量,我得到了这个:

  

方法usefullMethod()的NPath复杂度为103125

如果我全部更换?使用if-else结构,我得到了这个:

  

方法usefullMethod()的NPath复杂度为1056

为什么我用三元'得到这个非常高的结果'?'操作?

这段代码有什么问题? (在此演示代码中,很容易提取获取默认值的方法,但在实际代码中可能无法实现)

1 个答案:

答案 0 :(得分:20)

使示例更简单,此类的nPath值为2.应该很明显为什么它是两个 - 代码中有两条执行路径。

package test;

import java.util.*;

public class Test {

    private static final long UNKNWOWN = -1;

    public void method(Date a) {
        long aTime;

        if (a == null) {
            aTime = UNKNWOWN;
        } else {
            aTime = a.getTime();
        }
    }
}

此类的nPath值为5.问题是为什么 - 代码中仍有两条逻辑路径。

package test;

import java.util.*;

public class Test {

    private static final long UNKNWOWN = -1;

    public void method(Date a) {
        final long aTime = a == null ? UNKNWOWN : a.getTime();
    }
}

但是,使用的algorithm如下:

int npath = complexitySumOf(node, 0, data);     
npath += 2;

它增加了所有孩子的复杂性,然后为三元增加了两个。简单java节点返回的最小复杂度为1. AbstractSyntaxTree显示有三个子节点。因此3 + 2是5.

<ConditionalExpression beginColumn="36" beginLine="11" endColumn="69" endLine="11" ternary="true">
  <EqualityExpression beginColumn="36" beginLine="11" endColumn="44" endLine="11" image="==">
    <PrimaryExpression beginColumn="36" beginLine="11" endColumn="36" endLine="11">
       <PrimaryPrefix beginColumn="36" beginLine="11" endColumn="36" endLine="11">
         <Name beginColumn="36" beginLine="11" endColumn="36" endLine="11" image="a"/>
       </PrimaryPrefix>
    </PrimaryExpression>
    <PrimaryExpression beginColumn="41" beginLine="11" endColumn="44" endLine="11">
      <PrimaryPrefix beginColumn="41" beginLine="11" endColumn="44" endLine="11">
        <Literal beginColumn="41" beginLine="11" charLiteral="false" endColumn="44" endLine="11" floatLiteral="false" intLiteral="false" singleCharacterStringLiteral="false" stringLiteral="false">
          <NullLiteral beginColumn="41" beginLine="11" endColumn="44" endLine="11"/>
       </Literal>
      </PrimaryPrefix>
    </PrimaryExpression>
  </EqualityExpression>
  <Expression beginColumn="48" beginLine="11" endColumn="55" endLine="11">
    <PrimaryExpression beginColumn="48" beginLine="11" endColumn="55" endLine="11">
      <PrimaryPrefix beginColumn="48" beginLine="11" endColumn="55" endLine="11">
        <Name beginColumn="48" beginLine="11" endColumn="55" endLine="11" image="UNKNWOWN"/>
      </PrimaryPrefix>
     </PrimaryExpression>
  </Expression>
  <PrimaryExpression beginColumn="59" beginLine="11" endColumn="69" endLine="11">
    <PrimaryPrefix beginColumn="59" beginLine="11" endColumn="67" endLine="11">
      <Name beginColumn="59" beginLine="11" endColumn="67" endLine="11" image="a.getTime"/>
    </PrimaryPrefix>
    <PrimarySuffix argumentCount="0" arguments="true" arrayDereference="false" beginColumn="68" beginLine="11" endColumn="69" endLine="11">
      <Arguments argumentCount="0" beginColumn="68" beginLine="11" endColumn="69" endLine="11"/>
    </PrimarySuffix>
  </PrimaryExpression>
</ConditionalExpression>

如果你在三元运算符中有一个复杂的表达式,它的数量差异会更加普遍。至于代码有什么问题,它已经有9个分支(8个三元运算符和一个循环),即使没有整个nPath计算也很高。无论如何我都会重构它。