认知复杂度是什么
认知复杂度是 SonarSource 提出的可读性导向度量:嵌套越深增分越多,顺序排列的分支只加基础分,分支结构整块计一次。它直接回应了圈复杂度对可读性建模不足的问题——同样数量的分支,嵌在一起的写法比平铺的更难读,分差就体现在嵌套增量上。
基本信息
| 提出方 | SonarSource |
|---|---|
| 与圈复杂度的差别 | 带嵌套增量与结构惩罚,更贴近阅读难度 |
| 工具支持 | SonarQube 与 SonarLint 内置规则 |
| 默认阈值 | 工具通常给出默认上限,可按团队调整 |
| 主要用途 | 定位难读函数,指导拆分 |
典型使用场景
- 评审前找出最难读的函数作为拆分候选
- 为函数复杂度设定团队阈值并加入门禁
- 重构前后对比分数,验证可读性改善
- 培训时解释为什么深层嵌套代价更高
- 与技术债清单结合,量化待偿还位置
计分示意
计分示意
if (a) { // +1
if (b) { // +2(嵌套增量)
if (c) { } // +3
}
}
// 三个平铺的 if:+3(每个 +1)
// 同样三次判断,嵌套写法更贵,也更难读
// 提前返回或卫语句通常能直接消掉大部分增分增分与不加分的情形
| 情形 | 计分 | 说明 |
|---|---|---|
| 顺序分支 | 每个加基础分 | 平铺结构代价较低 |
| 嵌套分支 | 随嵌套深度递增 | 越深越贵,鼓励提前返回 |
| 相关逻辑运算 | 整块计一次 | 连续的条件组合不重复加分 |
| 简单方法调用 | 不加分 | 抽取命名函数不增加分数 |
分数用于排序而不是评价个人:同一个函数在不同团队感受不同,重点是把最贵的几个函数挑出来拆分,而不是压到某个数字以下。
不要和圈复杂度混在一起比较:两套口径不同,阈值不可互换,否则会得出互相矛盾的结论,团队也就不再相信指标。
降低分数最有效的动作是减少嵌套:提前返回、提取方法、把条件里的计算提成命名变量,通常能同时改善可读性与可测试性。