浅析代码圈复杂度及认知复杂度

浅析代码圈复杂度及认知复杂度 

写在开始

圈复杂度用来描述一段代码“可测性”很好(可测性这里指需要构建完善的覆盖全面的单元测试需要付出多少代价),但它的设计模型很难得出一个很好的“可读性&可维护性”的测量结果

新版soanrqube引入了认知复杂度的概念,这个复杂度指标弥补了圈复杂度的一些不足,能更准确的反映一段代码的理解成本,以及维护这段代码的困难程度。

下面就简要的描述下,为何认知复杂度更适合用来评价一段代码的可读性及可维护性。

什么是圈复杂度?

圈复杂度(Cyclomatic complexity)是一种代码复杂度的衡量标准,在1976年由Thomas J. McCabe, Sr. 提出,目标是为了指导程序员写出更具可测性和可维护性的代码。

它可以用来衡量一个模块判定结构的复杂程度,数量上表现为独立路径条数,也可以理解为覆盖所有可能的情况最少需要的测试用例数量。 

代码圈复杂度的计算方法

通常采用的计算方法为点边计算法(当然还有节点判定法),计算公式为:

V(G) = e – n + 2 

e 代表在控制流图中的边的数量(对应代码中顺序结构的部分),n 代表在控制流图中的节点数量,包括起点和终点(注:所有终点只计算一次,即便有多个return或者throw;节点对应代码中的分支语句)

假定有如下这样一段代码:

根据公式 V(G) = e – n + 2 = 12 – 8 + 2 = 6 ,上图的圈复杂段为6。

注:说明一下为什么n = 8,虽然图上的真正节点有12个,但是其中有5个节点为throw、return,这样的节点为end节点,只能记做一个

为什么要引入认知复杂度?

圈复杂度最初的目的是用来识别“难以测试和维护的软件模块”,它能算出最少的全覆盖的测试用例量,但是不能测出一个让人满意的“理解难度”。

这是因为同样圈复杂度的代码,不一定会具有相同的可维护性,我们看看下面的两个例子:

上面这两段代码具有相同的圈复杂度,但显然不具有相同的可读性和可维护性性,这就是圈复杂度的不足之处。

因为圈复杂度理论是在1976年提出的,它不包含一些现代的语言结构,比如try-catch、lambda。

并且,每个方法都默认有一个最小圈复杂度1,这就让我们无从得知,一个给定的类如果圈复杂度很高,它是一个大的易维护的类,还是一个很小很复杂的类。

为了解决上述这些问题,所以引入了“认知复杂度”,它将一段代码被阅读和理解时的复杂程度,估算成一个具体数字

认知复杂度如何评判?

认知复杂度评定基本原则

  • 对线性的代码逻辑中,出现一个打断逻辑的东西,复杂度+1;
  • 当打断逻辑的是一个嵌套时,复杂度+1;
  • 忽略简写:把多句代码缩写为一句可读的代码,复杂度不会额外增加;

上面这种描述可能有点抽象,具体一点说,以下控制流结构会导致认知复杂度增加:

for, while, do while, 三元运算符, if/elif/else, catch语句, 跳转语句(goto/break/continue), 以及嵌套的控制流(每一层嵌套复杂度递增)

我们继续拿上面提到的两个例子举例:

圈复杂度对于getWord方法本身会默认有1的复杂度,每多一个case复杂度+1,所以最终圈复杂度为4

而认知复杂度,对于整个 switch 结构只增加1的复杂度,因为从可理解、可维护程度来说,多几个case并不会导致其增加(当然,大量的case也是我们应当尽力去避免的)

我们接着看另外一个例子:

如你所看到的,认知复杂度考虑到了使这个方法比前面提到的getWords()方法更难理解的因素——嵌套以及跳转语句

因此,虽然这两个方法的圈复杂度是一样的,但是它们的认知复杂度数据很好的反映了它们两者在可理解性/可维护性上的差异。

另外,相对于圈复杂度默认所有方法至少有1的复杂度,认知复杂度并没有这样一个评定规则,这对于entity等简单类的复杂度评判会更加友好和客观:

综上所述,认知复杂度作为代码的“可读性/可维护性”评定指标会更加合适。


附、代码复杂度与软件质量关系

以上复杂度数值可以理解为方法粒度,即如果某一个方法复杂度>30,那这个方法的可读性和可维护性就很低了

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C代码复杂度分析是通过对C代码进行静态分析,评估代码的质量和可维护性的过程。该过程可以帮助开发人员识别潜在的问题,改善代码的可读性和可重用性,并优化代码的性能。 在实际工作中,采用VSCode工具进行代码复杂度分析可以带来以下优势: 首先,VSCode是一个轻量级、开源的集成开发环境,拥有高度灵活的插件系统。通过安装相关的插件,我们可以在VSCode中执行代码复杂度分析。这种集成开发环境的优势在于它可以帮助程序员更方便地进行代码分析和修改。 其次,VSCode提供了许多代码分析工具的插件,比如linters、静态代码分析器等等。这些工具可以自动检测代码中的问题并生成相应的报告。借助这些插件,开发人员可以更快速地定位代码中的潜在问题,比如潜在的性能问题、复杂度较高的代码段等等,并及时进行调整和优化。 此外,VSCode还支持代码高亮、代码折叠、智能代码补全等功能,这些功能都可以提高开发效率和代码的可读性。同时,VSCode还支持多种编程语言,包括C语言,所以非常适合进行C代码复杂度分析。 综上所述,通过使用VSCode工具进行C代码复杂度分析可以帮助开发人员快速定位代码中的问题,并进行相应的改进和优化。这有助于提高代码质量,提升开发效率,减少潜在的Bug,并为项目的后续维护带来便利。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值