PMD - NPath complexity very high with ternary operator (?

匿名 (未验证) 提交于 2019-12-03 01:49:02

问题:

I'm using PMD to generate some code quality report on a project.
I don't understand a result for the NPath complexity inspection.
I have created a dull class that is show-casing the result (this is not the real class, but it is using the same pattern):

import java.util.*;  public class SOFExample {      private final Map magicMap = new HashMap();         protected static final long UNKNWOWN = 0L;     private static final class MyCal { long aTime; long bTime; long cTime; long dTime;}      public void usefullMethod(final List 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 result:

The method usefullMethod() has an NPath complexity of 10625

If I add a new variable initialized the same way, I got this:

The method usefullMethod() has an NPath complexity of 103125

And if I replace all? With if-else structure, then I got this:

The method usefullMethod() has an NPath complexity of 1056

Why do I got this very high result with the ternary '?' Operator?

What's wrong with this code? (In this demo code it is easy to extract a method for getting the default values, but in real code it might not be possible)

回答1:

Making the example even simpler, this class has a nPath value of 2. It should be pretty apparent why it is two - there are clearly two execution paths through the code.

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();         }     } } 

And this class has a nPath value of 5. The question is why - there are still two logical paths through the code.

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();     } } 

However, the algorithm used is as follows:

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

It adds the complexity of all children then adds two for ternary. The minimum complexity returned for simple java nodes is 1. The AbstractSyntaxTree shows there are three children. Hence 3 + 2 is 5.

If you have a complex expression in the the ternary operator, the difference it count would be even more prevalent. As far as what's wrong with the code, it already has 9 branches (8 ternary operators and a loop) which is high even without the whole nPath calculation. I would refactor it regardless.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!