首页/开发/代码质量与评审速查/认知复杂度(Cognitive Complexity)
技术债与度量63 条

认知复杂度(Cognitive Complexity)

SonarSource 提出的可读性导向复杂度:嵌套越深增分越多,线性顺序分支少加分,switch 整块计一次,直接回应「圈复杂度对可读性建模不足」的问题。

认知复杂度是什么

认知复杂度是 SonarSource 提出的可读性导向度量:嵌套越深增分越多,顺序排列的分支只加基础分,分支结构整块计一次。它直接回应了圈复杂度对可读性建模不足的问题——同样数量的分支,嵌在一起的写法比平铺的更难读,分差就体现在嵌套增量上。

基本信息

提出方SonarSource
与圈复杂度的差别带嵌套增量与结构惩罚,更贴近阅读难度
工具支持SonarQube 与 SonarLint 内置规则
默认阈值工具通常给出默认上限,可按团队调整
主要用途定位难读函数,指导拆分

典型使用场景

  • 评审前找出最难读的函数作为拆分候选
  • 为函数复杂度设定团队阈值并加入门禁
  • 重构前后对比分数,验证可读性改善
  • 培训时解释为什么深层嵌套代价更高
  • 与技术债清单结合,量化待偿还位置

计分示意

计分示意
if (a) {              // +1
    if (b) {          // +2(嵌套增量)
        if (c) { }    // +3
    }
}
// 三个平铺的 if:+3(每个 +1)
// 同样三次判断,嵌套写法更贵,也更难读
// 提前返回或卫语句通常能直接消掉大部分增分

增分与不加分的情形

情形计分说明
顺序分支每个加基础分平铺结构代价较低
嵌套分支随嵌套深度递增越深越贵,鼓励提前返回
相关逻辑运算整块计一次连续的条件组合不重复加分
简单方法调用不加分抽取命名函数不增加分数
分数用于排序而不是评价个人:同一个函数在不同团队感受不同,重点是把最贵的几个函数挑出来拆分,而不是压到某个数字以下。
不要和圈复杂度混在一起比较:两套口径不同,阈值不可互换,否则会得出互相矛盾的结论,团队也就不再相信指标。
降低分数最有效的动作是减少嵌套:提前返回、提取方法、把条件里的计算提成命名变量,通常能同时改善可读性与可测试性。

易错点

  • 与圈复杂度混用比较:口径不同却互换阈值,结论矛盾
  • 只看分数不看写法:提前返回与卫语句已能消除大部分增分
  • 为降分把逻辑拆成碎片:函数数量暴涨,调用链变长,可读性反而下降
  • 把复杂度当个人考核:开发者会把判断藏进更隐蔽的写法

数据来源与参考

  • SonarSource 认知复杂度白皮书(Cognitive Complexity)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌