8

对于以下代码,sonarqube 计算方法的圈复杂度为 9

String foo() {
    if (cond1) return a;
    if (cond2) return b;
    if (cond3) return c;
    if (cond4) return d;
    return e;
}

我理解根据计算规则http://docs.sonarqube.org/display/SONAR/Metrics+-+Complexity 9 的复杂性是正确的。所以方法的复杂度是 = 4 (if) + 4 (return) + 1 (method) = 9

如果我有一个退出点,则可以降低这种复杂性。

String foo() {
    String temp;
    if (cond1) { 
        temp = a;
    } else if (cond2) {
        temp = b;
    } else if (cond3) { 
        temp = c;
    } else if (cond4) {
        temp = d;
    } else {
        temp = e;
    }
    return temp;
}

我相信这段代码比以前的版本更杂乱和不可读,我觉得拥有返回保护条件的方法是一种更好的编程实践。那么,是否有充分的理由考虑使用 return 语句来计算圈复杂度?是否可以更改计算逻辑,使其不促进单个退出点。

4

4 回答 4

9

I agree you should use some common sense and go with the code which you believe is simplest.

BTW You can simplify you code and have just one return if you use ? :

String foo() {
    return cond1 ? a :
           cond2 ? b :
           cond3 ? c :
           cond4 ? d : e;
}
于 2014-05-22T09:43:28.237 回答
2

其他答案对所涉及的计算提出了很好的观点。

我想指出,您关于代码可读性较差的断言是错误的,因为在一种情况下您有大括号,而在另一种情况下您没有。

String foo() {
  String output = e;
  if (cond1) output = a;
  else if (cond2) output = b;
  else if (cond3) output = c;
  else if (cond4) output = d;

  return output;
}

这与您使用 return 语句给出的示例一样可读。是否允许无括号 if 语句是一个样式问题,您可能应该在所有代码中保持一致。

圈复杂度确实解决的更重要的问题是,如果计算 cond1、cond2 等的值有副作用,即在这种情况下它们是有状态的方法而不是字段,那么代码的概念复杂度要高得多,如果与不能返回相比,您可能会提前返回。

于 2014-05-26T07:30:56.157 回答
2

这是圈复杂度的一个已知问题。

也有充分的理由认为圈复杂度是无用的。它与 SLOC 密切相关,仅与实际错误相关。事实上,SLOC 与圈复杂度一样可以很好地预测缺陷。大多数其他复杂性指标也是如此。

请参阅http://www.leshatton.org/Documents/TAIC2008-29-08-2008.pdf,从幻灯片 16 开始。

于 2014-05-22T09:53:30.710 回答
2

“那么,考虑返回语句来计算圈复杂度是否有充分的理由?是否可以更改计算逻辑,使其不促进单个退出点。”

在您的示例中,具有多个回报不会增加复杂性,正如@Peter Lawrey 所说,您应该运用常识。

这是否意味着多个返回语句的所有示例都不复杂并且应该被删除?我不这么认为。如果很容易想出一个由于多个返​​回语句而难以阅读的方法示例。想象一下一个 100 行的方法,其中散布着 4 个不同的返回语句。这就是该规则试图解决的问题。

于 2014-05-22T09:47:30.293 回答