Cognitive Complexity

来自 SonarQube

认知复杂度旨在弥补传统的圈复杂度在衡量代码可维护性方面的不足:

  1. 对于不同结构的代码,即使圈复杂度相同,但是理解难度可能差异很大。
  2. 不适合现代的编程语言结构。

计算规则:

  1. 忽略简化写法

    不计算那些使代码更简洁、已读的结构。

  2. 结构增量(Structural Increment)

    • forwhiledo-whileif?:#if#ifdef 会增加 1 分。

    • catch 语句会增加 1 分。

      tryfinally 则不会加入统计。

    • switch 语句会增加 1 分。

      switch 里面的 case 语句则不会加入统计。

    • 同类型的运算符会增加 1 分,但是不同类型的运算符会增加 n 分(n 取决于实际个数)。

      if (a && b && c && d) 会增加 1 分,if (a || b || c || d) 会增加 1 分。

      if (a && b || c) 会增加 2 分,if (a || (b && c) || d) 会增加 3 分。

    • 递归调用会增加 1 分,每个参与递归的方法都会增加 1 分。

    • goto 会增加 1 分。

      带标签的 breakcontinue 会增加 1 分。(不带标签的 breakcontinue 则不加入统计)

      在 Java 中,支持 break xxx、continue xxx 的写法,等同于 C 里面的 goto xxx。

      早期返回 return 则不会加入统计。

  3. 混合增量(Hybrid Increment)

    elseelse-if 都会增加 1 分。它们会增加嵌套层数,但不额外计算嵌套增量。

  4. 嵌套增量(Nesting Increment)

    嵌套增量等于当前的嵌套层级

    嵌套层数则是在每个嵌套结构的基础分上加上当前的嵌套层数。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
if (1) {                            // +1 (结构增量 if)
    for (int i = 0; i < 5; i++) {   // +2 (结构增量 for + 嵌套层数 1)
        if (true && true && true) { // +4 (结构增量 if + 嵌套层数 2 + 基础增量 &&)
        }
    }
} else if (1) {                     // +1 (混合增量 else-if)
    while (1) {                     // +2 (结构增量 while + 嵌套层数 1)
    }
}
// 总分 = 1 + 2 + 3 + 1 + 2 = 10

错误提示

  1. The Cognitive Complexity of this function is 57 which is greater than 32 authorized.
  2. The Cognitive Complexity of this function is 66 which is greater than 32 authorized.

分析

image-20260105175536117

其中:

  1. +1: if statement

    表示识别到 if 语句,复杂度加 1。

  2. +3: if statement (incl 2 for nesting)

    表示识别到 if 语句,而且嵌套层级是 2,复杂度加 3。

  3. +1: else statement

    表示识别的 else 语句,复杂度加 1。

  4. +1: goto statement

    表示识别到 goto 语句,复杂度加 1。

  5. +1: iteration statement

    表示识别到 do-whilewhilefor (;;) 语句,复杂度加 1。

  6. +1: conditional operator

    表示识别到 ? : 语句,复杂度加 1。

  7. +2: conditional operator (incl 1 for nesting)

    表示识别到 ? : 语句,而且嵌套层级是 1,复杂度加 2。

  8. +1: logical operator

    表示识别到 ||&&,复杂度加 1。

  9. +1: switch statement

    表示识别到 switch 语句,复杂度加 1。

  10. +4: switch statement (incl 3 for nesting)

    表示识别到 switch 语句,而且嵌套层级是 3,复杂度加 4。

版权声明

本文为「Zeepunt 日常随笔」的原创文章,遵循 CC BY-NC-ND 4.0 许可协议。允许在署名作者、注明原文链接且不作任何更改的前提下非商业性地分享本文。

原文链接:https://zeepunt.github.io/article/code/sonarqubecognitive-complexity---%E8%AE%A4%E7%9F%A5%E5%A4%8D%E6%9D%82%E5%BA%A6/