我更喜欢早期回报的写作风格:
public static Type classify(int a, int b, int c) {
if (!isTriangle(a, b, c)) {
return Type.INVALID;
}
if (a == b && b == c) {
return Type.EQUILATERAL;
}
if (b == c || a == b || c == a) {
return Type.ISOSCELES;
}
return Type.SCALENE;
}
不幸的是,每个return
语句都会增加Sonar计算的圈复杂度指标。考虑这个替代方案:
public static Type classify(int a, int b, int c) {
final Type result;
if (!isTriangle(a, b, c)) {
result = Type.INVALID;
} else if (a == b && b == c) {
result = Type.EQUILATERAL;
} else if (b == c || a == b || c == a) {
result = Type.ISOSCELES;
} else {
result = Type.SCALENE;
}
return result;
}
Sonar报告的后一种方法的圈复杂度低于第一种,为3.我被告知这可能是CC指标错误实施的结果。或者声纳是否正确,这真的更好吗?这些相关问题似乎不同意:
如果我添加对更多三角形类型的支持,return
语句将相加以使指标发生显着差异并导致Sonar违规。我不想在方法上粘贴// NOSONAR
,因为这可能会掩盖将来添加到方法中的新功能/错误导致的其他问题。所以我使用第二个版本,即使我不喜欢它。有没有更好的方法来处理这种情况?
答案 0 :(得分:2)
不是一个真正的答案,但是评论的时间太长了。
这条SONAR规则似乎彻底打破了。你可以重写
b == c || a == b || c == a
作为
b == c | a == b | c == a
并且在这个奇怪的游戏中获得两分(甚至可能有一些速度,因为分支是昂贵的;但这仍然取决于JITc,无论如何)。
old rule声称,圈复杂度与测试次数有关。 new one没有,这是一件好事,因为很明显,两个片段的有意义测试数量完全相同。
有没有更好的方法来处理这种情况?
实际上,我确实得到了答案:对于每次提前退货,请使用|
代替||
一次。 :d
现在认真对待:有一个错误要求annotations允许禁用单个规则,该规则被标记为已修复。我再也不看了。
答案 1 :(得分:2)
您的问题与https://jira.codehaus.org/browse/SONAR-4857有关。目前,所有SonarQube分析仪都在混合环成复杂性和基本复杂性。从理论的角度来看,return语句不应该增加cc,这种变化将在SQ生态系统中发生。
答案 2 :(得分:0)
由于问题也是关于早期返回语句作为编码风格,因此考虑大小对返回方式的影响会很有帮助。如果方法或函数很小,少于30行,则早期返回没有问题,因为读取代码的任何人都可以一目了然地看到整个方法,包括所有返回。在较大的方法或功能中,早期返回可能是无意中为读者设置的陷阱。如果早期返回发生在读者正在查看的代码之上,并且读者不知道返回高于或忘记它在上面,则读者将误解代码。生产代码可能太大而无法放在一个屏幕上。
因此,无论谁管理复杂性的代码库,都应该在复杂性出现问题的情况下考虑方法大小。如果代码占用多个屏幕,则可以证明更为迂腐的返回方式。如果方法或功能很小,请不要担心。
(我使用Sonar并遇到过同样的问题。)