圈复杂度和McCabe

  • 【书名】:软件架构——Python语言实现
  • 【主题】:圈复杂度
  • 【摘要】:圈复杂度(Cyclomatic Complexity)是衡量计算机程序复杂程度的一种措施。它根据程序从开始到结束的线性独立路径的数量计算得来的。在 Python 中可以使用 mccabe 包测量程序的圈复杂度。

1 圈复杂度

对于没有任何分支的代码,它的圈复杂度为 1 ,意味着代码只有一条路径。例如下面的函数:

1

2

3

def (a, b):

return a + b

对于有一条分支的代码,它的圈复杂度为 2 ,比如下面递归计算阶乘的代码:

1

2

3

4

5
def factorial(n):

if n == 0:

return 1

else:

return n * factorial(n-1)

在 1976 年, Thomas J. McCabe 开发了使用有向图计算复杂的算法。为了得到这个指标,程序控制流程图可以画成一个有向图,其中:

  • 节点表示一个程序块
  • 边表示从一个程序块到另一个程序块的控制流

根据程序的控制图,McCabe 复杂度可以表示为

1
M = E - N + 2P

其中:

  • E:边的数量
  • N:节点的数量
  • P:连接组件的数量

2 McCabe的使用

在 Python 中可以使用 McCabe 包测量程序的圈复杂度。它可以当作一个独立的模块,也可以当作程序的一个插件。可以使用 pip 安装模块

1
pip install mccabe

2.1 作为命令行使用

unittestflake8 等工具一样。

1

2

3

4

5

6

7
$ python -m mccabe --min 5 mccabe.py

("185:1: 'PathGraphingAstVisitor.visitIf'", 5)

("71:1: 'PathGraph.to_dot'", 5)

("245:1: 'McCabeChecker.run'", 5)

("283:1: 'main'", 7)

("203:1: 'PathGraphingAstVisitor.visitTryExcept'", 5)

("257:1: 'get_code_complexity'", 5)

2.2 作为 flake8 插件

当 flake8 版本在 2.0 以上和 McCabe 已经安装的情况下,该插件可用。

1

2
$ flake8 --version

2.0 (pep8: 1.4.2, pyflakes: 0.6.1, mccabe: 0.2)

在命令中使用 --max-complexity 选项即可。

1

2

3
$ flake8 --max-complexity 10 coolproject

...

coolproject/mod.py:1204:1: C901 'CoolFactory.prepare' is too complex (14)

根据 McCabe 圈复杂度大于 10 ,就认为是 too complex ,需要进行重构以降低复杂度。

3 程序控制图

3.1 生成程序控制图

以上述 factorial 函数代码为例子,将其保存为一个 factorial.py 文件中,如下:

1

2

3

4

5

6

7

def factorial(n):

if n == 0:

return 1

else:

return n * factorial(n-1)

第一步 使用 python -m mccabe factorial.py -d

输出 dot 文本图形描述语言的有向图。

1

2

3

4

5

6

7

8

9

10

11

12

13

14
graph {

subgraph {

node [shape=circle,label="If 4"] 2187726207240;

node [shape=circle,label="3:0: 'factorial'"] 2187726207016;

node [shape=circle,label="Stmt 5"] 2187726207408;

node [shape=point,label=""] 2187726207296;

node [shape=circle,label="Stmt 7"] 2187726207520;

2187726207240 -- 2187726207408;

2187726207240 -- 2187726207520;

2187726207016 -- 2187726207240;

2187726207408 -- 2187726207296;

2187726207520 -- 2187726207296;

}

}

第二步,Graphviz渲染图片

Graphviz 是 AT&T Labs Research开发的图形绘制工具软件.它使用一个特定的DSL(领域特定语言): dot作为脚本语言,然后使用布局引擎来解析此脚本,并完成自动布局。graphviz提供丰富的导出格式,如常用的图片格式,SVG,PDF格式等。

打开 Graphviz 编辑器,将上述文档保存为 factorial.gv 文档,生成程序控制图。

第三步,计算 McCabe 复杂度

根据公式,复杂度: M = 5 - 4 + 2 x 1 = 2

4 降低复杂度

使用字典替代复杂的 if-else 分支代码是 Python 中降低复杂度一个有效的方法。

比如可以将下面的分支代码:

1

2

3

4

5

6

7

8

def f(x):

if x == 'a':

return 1

elif x == 'b':

return 2

else:

return 9

改为下面的字典映射代码

1

2

3

4

5

6

def f(x):

return {

'a': 1,

'b': 2

}.get(x, 9)

复杂度也从 3 降低到 1 。

5 参考资料

原文:大专栏  圈复杂度和McCabe

原文地址:https://www.cnblogs.com/chinatrump/p/11612031.html

时间: 2024-11-08 20:44:24

圈复杂度和McCabe的相关文章

前端代码质量-圈复杂度原理和实践

写程序时时刻记着,这个将来要维护你写的程序的人是一个有严重倾向,并且知道你住在哪里的精神变态者. 导读你们是否也有过下面的想法? 重构一个项目还不如新开发一个项目...这代码是谁写的,我真想...你们的项目中是否也存在下面的问题? 单个项目也越来越庞大,团队成员代码风格不一致,无法对整体的代码质量做全面的掌控没有一个准确的标准去衡量代码结构复杂的程度,无法量化一个项目的代码质量重构代码后无法立即量化重构后代码质量是否提升针对上面的问题,本文的主角 圈复杂度 重磅登场,本文将从圈复杂度原理出发,介

基于Table方法降低代码圈复杂度

描述: 在项目开发过程中,经常要求圈复杂度不能超过10,有时候写着写着圈复杂度就很大,我在项目代码中见过函数圈复杂度大于100的函数,由于历史的原因,代码越积越多,没人出去重构,导致后面很难懂和维护,所以在编码初期就应该在心中有个要求,就是圈复杂度不能超过10,如果超过10,肯定是代码逻辑写的过于复杂,要回过头来 想想怎么去分解功能,让流程简单易懂. 本文主要通过一些例子来介绍基于Table方式降低圈复杂度的过程. 例子1:一个简单的游戏控制函数 你可能会遇到如下类似的代码: if(strcmp

圈复杂度

一.现象 1. 代码设计不规范. 当项目规模达到一定的程度,比如达到十万行的代码量.那么项目肯定存在有些类特别大,方法特别多.特别长. 以上因素会导致什么后果呢? 一个类没有做到单一指责,后期对这个类改动会导致其他功能出现Bug. 代码阅读性较差,维护困难. 2. 没有一个准确的标准去衡量代码结构复杂的程度. 各个公司都会有自己的规范,但是开发中很少人能够去完全遵循规范.而且没有一个明确的标准去衡量代码的复杂程度,而且人工去检测代码的复杂程度是很繁琐的.因此我们急需一个标准去检测代码结构复杂的程

C语言switch/case圈复杂度优化重构

软件重构是改善代码可读性.可扩展性.可维护性等目的的常见技术手段.圈复杂度作为一项软件质量度量指标,能从一定程度上反映这些内部质量需求(当然并不是全部),所以圈复杂度往往被很多项目采用作为软件质量的度量指标之一. C语言开发的项目中,switch/case代码块是一个很容易造成圈复杂度超标的语言特性,所以本文主要介绍下降低switch代码段的重构手段(如下图).switch圈复杂度优化重构可分为两部分:程序块的重构和case的重构.程序块重构是对代码的局部优化,而case重构是对代码的整体设计,

圈复杂度(Cyclomatic Complexity)

圈复杂度(Cyclomatic Complexity)是很常用的一种度量软件代码复杂程度的标准.这里所指的"代码复杂程度"并非软件内在业务逻辑的复杂程度,而是指代码的实现方式的 复杂程度.说起来有点绕是么?打个比方就是嘴笨的人可以把简单的事情说得很复杂.虽然"内在业务逻辑"与"实现方式"有紧密的联系,有很多研究统计指出, 圈复杂度高的代码中错误的可能性更大,维护的成本更高. 它的计算方法很简单,计算公式为:V(G)=e-n+2.其中,e表示控制流

圈复杂度(Cyclomatic Complexity)-转

圈复杂度(Cyclomatic Complexity)是一种代码复杂度的衡量标准.它可以用来衡量一个模块判定结构的复杂程度,数量上表现为独立现行路径条数,也可理解为覆盖所有的可能情况最少使用的测试用例数.圈复杂度大说明程序代码的判断逻辑复杂,可能质量低且难于测试和维护.程序的可能错误和高的圈复杂度有着很大关系. 下面这个实例中,单元测试的覆盖率可以达到100%,但是很容易发现这其中已经漏掉了一个NPE的测试用例.case1方法的圈复杂度为2,因此至少需要2个用例才能完全覆盖到其所有的可能情况.

【软件测试】圈复杂度

圈复杂度:在软件测试的概念里,它用来衡量一个模块判定结构的复杂程度,数量上表现为线性无关的路径条数,即 合理的预防错误所需测试的最少路径条数. 圈复杂度大说明程序代码可能质量低且难于测试和维护,根据经验,程序的可能错误和高的圈复杂度有着很大关系. 圈复杂度的原理:(其实就是分支的个数) 圈复杂度为1,意味着代码只有一条路径. 对于有一条分支的代码,它的圈复杂度为2. 从1开始,一直往下经过程序. 一旦遇到以下关键字,或者其它同类的词,就 +1. 如 if.while.repeat.for.and

什么是Cyclomatic Complexity(圈复杂度)? .

Campwood Software SourceMonitor Version 3.5 The freeware program SourceMonitor lets you see inside your software source code to find out how much code you have and to identify the relative complexity of your modules. For example, you can use SourceMo

白盒测试浅谈

白盒测试[1] 又称结构测试.透明盒测试.逻辑驱动测试或基于代码的测试.白盒测试是一种测试用例设计方法,盒子指的是被测试的软件,白盒指的是盒子是可视的,你清楚盒子内部的东西以及里面是如何运作的."白盒"法全面了解程序内部逻辑结构.对所有逻辑路径进行测试."白盒"法是穷举路径测试.在使用这一方案时,测试者必须检查程序的内部结构,从检查程序的逻辑着手,得出测试数据.贯穿程序的独立路径数是天文数字. 采用什么方法对软件进行测试呢?常用的软件测试方法有两大类:静态测试方法和