圈复杂度初入门

639 阅读2分钟

概念

圈复杂度(Cyclomatic complexity),也称条件复杂度,是一种代码复杂度的衡量标准。由Thomas J. McCabe于1976年提出,用于表示程序的复杂度。

圈复杂度计算方法

点、边、连通分量计算法

公式:

V(G) = e - n + 2p

e表示控制流图中边(edge)的数量,n(node)表示控制流图中节点的数量,p代表的是连通分量(连通分量的概念可以自行百度,但是在我们常见的程序里,连通分量的值为1)

连通分量:简单来说是加p条边,可以让这个图变成一个强连通图,所谓强连通图是指从任意节点可以到达任意节点的图

节点判定法

简单来说就是程序运行过程中的分岔口,一个分岔口会对应一个节点。当然对于switch 这类一个分岔口,多个节点路径来说,对应的分岔即为判定节点。

常见的判定节点有:

if ... else if ...

while

switch ... case ...

三目运算

&& || 操作

几种常见的控制程序复杂度计算方法

image.png

对于程序中的代码而言,如果

ControlStructureCyclomatic Complexity
Sequence暂时无法在飞书文档外展示此内容v = 1 - 2 + 2 = 1
If Then Else暂时无法在飞书文档外展示此内容v = 4 - 4 + 2 = 2
While暂时无法在飞书文档外展示此内容v = 3 - 3 + 2 = 2
Until暂时无法在飞书文档外展示此内容v = 3 - 3 + 2 = 2

常见的代码场景及其复杂度

If else场景

function testA () {
  const a = 1
  if (a > 0) {
    console.log('大于0')
  } else if (a === 0) {
    console.log('小于0')
  } else {
    console.log('等于0')
  }
}

对应的图

image.png

While场景

function testB () {
  let a = 1
  while (a < 10) {
    a++
  }

  if (a > 11) {
    console.log(a)
  }
}

对应的图 image.png

圈复杂度及缺陷

圈复杂度不是一个能够让你不会写出BUG的银弹,它只是一个警钟,而这个警钟在你不好好设计代码时会响起。

圈复杂度和软件质量

圈复杂度代码状况可测性维护成本
1-10清晰、结构化
10-20复杂
20-30非常复杂
>30不可读不可测非常高

圈复杂度与测试的关系

如果是TDD开发模式,开发者们会更倾向于编写简单的函数以便测试,这样也能够从另一方面驱动开发者编写出圈复杂度低的函数

常见工具

Code Metrics vscode插件(安装该插件并启用后,在每个函数的上面,会提示出对应的圈复杂度值)

引文

McCabe1976

更多实践

降低代码的圈复杂度# 概念