【问题标题】:Sonar cyclomatic complexity rule issue - discourages multiple return statements声纳圈复杂度规则问题 - 不鼓励使用多个返回语句
【发布时间】:2014-05-22 09:33:24
【问题描述】:

对于下面这段代码,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 语句来计算圈复杂度?是否可以更改计算逻辑,使其不提升单个退出点。

【问题讨论】:

  • 我必须同意你的看法。多重回报确实没有任何本质上的错误。正如您所看到的here,这个想法背后有历史原因,但在更现代的语言中使用它们应该没有任何问题。但是,我不知道如何更改计算方法,因此将保留评论。

标签: java sonarqube cyclomatic-complexity


【解决方案1】:

我同意你应该使用一些常识并使用你认为最简单的代码。

顺便说一句,如果你使用? :,你可以简化你的代码并且只有一个回报

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

【讨论】:

  • 这并没有解决复杂性的问题,这只是代码美学。
【解决方案2】:

“那么是否有充分的理由考虑使用 return 语句 圈复杂度的计算?计算的逻辑可以是 已更改,因此它不会促进单个退出点。”

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

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

【讨论】:

  • 100 行代码中的 4 个返回语句肯定是个问题。但是我首先要排序 100 行代码,而不是 4 个返回语句。
  • @Hari 你是 100% 正确的。 6 年前,我在一个遗留代码库中工作,其中 100 行方法并不少见。现在我要重构地狱了
【解决方案3】:

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

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

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

【讨论】:

    【解决方案4】:

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

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

    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 等的值有副作用,即在这种情况下它们是有状态的方法而不是字段,那么与不能提前返回相比,提前返回的代码概念复杂度要高得多。

    【讨论】:

    • 如果我错了,请纠正我,但这并不等同。如果 cond1 == true,两个原始示例都将停止比较。您的示例将比较 cond2、cond3 和 cond4,即使 cond1 == true
    • @HenrikKjusAlstad - 很好,我忘记了“其他”。固定。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-01
    • 1970-01-01
    相关资源
    最近更新 更多