声纳给我以下圈复杂度数:22。
对于以下程序:
private static SomeDto checkSomething(AnotherDto anotherDto, String reference)
{
SomeDto someDto = new SomeDto();
// condition 1
if (!someDto.getA())
return new SomeDto("bla1", "blabla");
// condition 2
if (someDto.getName2() == null || checkSurName(anotherDto.getName()))
return new SomeDto("bla2", "blabla");
// condition 3
if (someDto.getName3() == null || checkSurName(anotherDto.getName()))
return new SomeDto("bla3", "blabla");
// condition 4
if (someDto.getName4() == null && checkSurName(anotherDto.getName()))
return new SomeDto("bla4", "blabla");
// condition 5
if (someDto.getName5() == null || checkSurName(anotherDto.getName()))
return new SomeDto("bla5", "blabla");
// condition 6
if (someDto.getName6() == null && checkSurName(anotherDto.getName()))
return new SomeDto("bla6", "blabla");
// condition 7
if (someDto.getName7() == null && checkSurName(anotherDto.getName()))
return new SomeDto("bla7", "blabla");
// condition 8
if (someDto.getName8() == null && checkSurName(anotherDto.getName()))
return new SomeDto("bla8", "blabla");
// condition 9
if (someDto.getName9() == null && checkSurName(anotherDto.getName()))
return new SomeDto("bla9", "blabla");
// condition 10
if (someDto.getName10() == null && checkSurName(anotherDto.getName()))
return new SomeDto("bla10", "blabla");
// condition 11
if (someDto.getName11() == null && checkSurName(anotherDto.getName()))
return new SomeDto("bla11", "blabla");
return someDto;
}
我遇到的问题如下:
“此方法“checkSomething”的循环复杂度为 22,大于授权的 12。”
我的问题是: 考虑到 McCabe 公式 V(G) = E - N + 2,Sonar 的数量是如何达到 22 的?
哪里:
E = 边数
N = 节点数
该方法有多少条边和节点? 该方法的控制流程是什么?
我们使用 SonarQube 版本 6.3(内部版本 19869)。
SonarQube 最新版本的文档清楚地说明了它如何计算圈复杂度:
Complexity(复杂度)是计算出的Cyclomatic Complexity 基于代码的路径数。每当控制 函数流分裂,复杂度计数器增加 一。每个函数的最小复杂度为1。这个计算 由于关键字和功能不同,因此语言略有不同。
如果您打开该段落下方的“特定于语言的详细信息”,Java 行将显示如下。
增加复杂性的关键字:if、for、while、case、catch、 抛出,&&,||,?
由于OP在提出问题时使用的是6.3版本,我还检查了我能找到的最旧版本的文档(不再可用),即6.7。到那时,计算略有不同。
增加复杂性的关键字:if、for、while、case、catch、 throw、return(这不是方法的最后一条语句)、&&、||、?
备注:
else、default 和finally 关键字不会增加复杂性。
一个带有 switch 语句和大量 case 的简单方法 语句可能具有令人惊讶的高复杂度值(仍然有 将开关块转换为等效块时的相同值 if 语句的序列)。
示例:以下方法的复杂度为 5
public void process(Car myCar){ // +1
if(myCar.isNotMine()){ // +1
return; // +1
}
car.paint("red");
car.changeWheel();
while(car.hasGazol() && car.getDriver().isNotStressed()){ // +2
car.drive();
}
return; }
好吧,经过进一步调查并根据这个link(checkstyle工具),我得出的结论是McCabe公式并没有真正应用于计算Java程序中的圈复杂度。
复杂度等于决策点的数量 + 1 决策点: if、 while 、 do、 for、 ?:、 catch 、 switch、 case 语句以及运算符 && 和 ||在目标体内。
因此,如果我将此规则应用于之前的示例代码:
private static SomeDto checkSomething(AnotherDto anotherDto, String reference) // 1
{
SomeDto someDto = new SomeDto();
// condition 1
if (!someDto.getA()) // 2
return new SomeDto("bla1", "blabla");
// condition 2
if (someDto.getName2() == null || checkSurName(anotherDto.getName())) // 4
return new SomeDto("bla2", "blabla");
// condition 3
if (someDto.getName3() == null || checkSurName(anotherDto.getName())) // 6
return new SomeDto("bla3", "blabla");
// condition 4
if (someDto.getName4() == null && checkSurName(anotherDto.getName())) // 8
return new SomeDto("bla4", "blabla");
// condition 5
if (someDto.getName5() == null || checkSurName(anotherDto.getName())) // 10
return new SomeDto("bla5", "blabla");
// condition 6
if (someDto.getName6() == null && checkSurName(anotherDto.getName())) // 12
return new SomeDto("bla6", "blabla");
// condition 7
if (someDto.getName7() == null && checkSurName(anotherDto.getName())) // 14
return new SomeDto("bla7", "blabla");
// condition 8
if (someDto.getName8() == null && checkSurName(anotherDto.getName())) // 16
return new SomeDto("bla8", "blabla");
// condition 9
if (someDto.getName9() == null && checkSurName(anotherDto.getName())) // 18
return new SomeDto("bla9", "blabla");
// condition 10
if (someDto.getName10() == null && checkSurName(anotherDto.getName())) // 20
return new SomeDto("bla10", "blabla");
// condition 11
if (someDto.getName11() == null && checkSurName(anotherDto.getName())) // 22
return new SomeDto("bla11", "blabla");
return someDto;
}
如果我错了,请纠正我。 难道不应该至少考虑 return 语句(除了该方法的最后一个语句)吗?
无论如何,结果数字 22 是有道理的。该方法有大量连续的“if”条件,应该对此采取措施以提高其可维护性。