【发布时间】:2014-09-15 06:37:06
【问题描述】:
我更喜欢这种早期回报的写作风格:
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 语句加起来会在指标上产生显着差异并导致声纳违规。我不想在该方法上粘贴// NOSONAR,因为这可能会通过将来添加到该方法中的新功能/错误来掩盖其他问题。所以我使用第二个版本,即使我不是很喜欢它。有没有更好的方法来处理这种情况?
【问题讨论】:
-
根据en.wikipedia.org/wiki/Cyclomatic_complexity,CC 是通过函数的线性独立路径的数量,在这两种情况下都是 4. Sonar 告诉你一些不同的东西吗?
-
是的。 Sonar 为每个
return语句添加 +1。这是squid:MethodCyclomaticComplexity规则:dev.eclipse.org/sonar/rules/show/… 较早的规则(但现在不赞成使用 squid)没有此约束:dev.eclipse.org/sonar/rules/show/… -
所以这个问题的真正意思是“如何防止声纳计算错误的 CC” - 这不适合这个网站。这样的问题最好放在stackoverflow上。我将此问题标记为迁移。
-
你在这里做了两件事。您有条件逻辑,但也有保护条款。我倾向于尊重单一职责的概念,因为总的来说它使代码更具可读性,除了函数开头的保护子句。
-
之前我问了一个类似的问题 (stackoverflow.com/questions/23381265/…),结果发现 SonarQube 报告的复杂性混合了“循环复杂性”和“基本复杂性”。
标签: cyclomatic-complexity sonarqube