Sonar给出了以下圈复杂度数: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授权。"
我的问题是: 考虑到Mac Cabe公式 v(g)= e - n + 2 ,Sonar如何达到22?
其中:
e =边数
n =节点数
此方法中有多少条边和节点? 这种方法的控制流程是什么?
我们在SonarQube版本6.3(build 19869)上。
答案 0 :(得分:1)
嗯,经过进一步的调查并根据这个link(checkstyle工具),我得出结论,McCabe公式并没有真正用于计算Java程序中的圈复杂度。
复杂性等于决策点的数量+ 1个决策点:if,while,do,for,?:,catch,switch,case statement,and operator&&和||在目标体内。
因此,如果我将此规则应用于上一个示例代码:
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;
}
如果我错了,请纠正我。 不应该至少考虑返回语句(除了方法的最后一个语句之外)吗?
无论如何,22的结果数是有道理的。该方法具有大量连续的“if”条件,应该对其进行某些操作以提高其可维护性。
答案 1 :(得分:0)
我不确定我是否会告诉您,但是复杂度法则的循环法不能通过方法来工作。
这是对您所有班级的计算。您需要了解代码中用于稳定指标中适当的ciclomativ值的方法数量。
此致
答案 2 :(得分:0)
SonarQube documentation for the latest version清楚地说明了它如何计算圈复杂度:
复杂度(复杂度)是计算出的环复杂度 基于代码中路径的数量。每当控制 函数流分裂,复杂度计数器递增 一。每个函数的最小复杂度为1。 语言因关键字和功能的不同而略有不同。
如果您打开该段落下面的“特定于语言的详细信息”,则Java行如下所示。
增加复杂性的关键字:如果是,持续,大小写,抓住, 抛出&&,||,?
由于在提出问题时OP正在使用6.3版本,所以我还检查了可以找到的documentation for the oldest version,即6.7。那时,计算略有不同。
增加复杂性的关键字:如果是,持续,大小写,抓住, 抛出,返回(不是方法的最后一个语句),&&,||,?
注意:
其他,默认和finally关键字不会增加复杂性。
具有switch语句和大量情况的简单方法 语句可能具有令人惊讶的高复杂度值(仍然具有 将开关模块转换为等效模块时具有相同的值 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; }