程序复杂度之圈复杂度

圈复杂度(Cyclomatic complexity)也称为条件复杂度或循环复杂度,是一种软件度量,是由Thomas J. McCabe, Sr. 在 1976 年提出,用来表示程序的复杂度,其符号为 VG 或是 M。圈复杂度是对源代码中线性独立路径数的定量测量。

圈复杂度使用的程序的控制流图来计算:在图中的节点对应于程序中一组不可分割的命令[代码行],有向边连接两个可连续执行的节点;[可连续执行的两个节点:第二个节点的命令组可能在第一个节点执行后立刻开始执行]。圈复杂度可以应用到独立的功能,模块,方法或类。

基础路径测试:通过测试用例测试程序中的每个线性无关的独立路径;在这种测试策略下,测试用例的数目将等于该程序的圈复杂度;

圈复杂度定义

圈复杂度度量的是程序中线性独立路径的数量;例如:如果程序中不包含控制、判断、条件语句(例如 if,swith 等),那么复杂度就是 1 ;因为整个程序只有一条执行路径;如果程序包含一条IF语句,那么就会有两条路径来执行完整个程序(IF为 TRUE,IF 为 FALSE),所以这时候的复杂度就是 2;两个嵌套的 IF 语句,或者包含两个判断条件的一个 IF 语句,复杂度就是 4;

在数学上,一个结构化程序的圈复杂度通过该程序的控制流图来定义;控制流图包含程序的基本块(图的节点),和两个基本块之间可执行性(图的边)。

原理:

上图:单程序的控制流图。此程序由红色的节点开始运行,然后进入循环(红色节点下由三个节点组成),离开循环后有条件分支,最后运行蓝色节点后结束,此控制流图中,E = 9, N = 8, P = 1,因此其圈复杂度为 9 - 8 + (2*1) = 3

数学表达式:

                    M = E - N + 2P

其中
E 为图中边的个数
N 为图中节点的个数
P 为连接组件的个数

强连通图的圈复杂度定义:要求做完线上功能的先要求线上的功能

上图:对应同一个程序的控制流图,但多加一个从结束点到启始点的边,因此为强连通的控制流图,若利用此图计算圈复杂度,其公式为 M=E-N+P,而 E = 10、N = 8、P = 1,因此圈复杂度为 3
另一个计算圈复杂度的公式用与计算每一个结束节点总是连接到启动节点的流程控制图;这种图称为强连通的;此时的圈复杂度就是图中回路的个数,也称为第一贝蒂数[first Betti number]),其公式如下:

                      M = E - N + P

上式可以视为计算图中线性独立回路(回路内不包括其他回路)的个数,由于控制流图增加结束点到启始点的边,因此对应一个结束点至少会有一个回路。
对于单一的程序(或副程序或方法),P 恒为 1。对于单一子程序,该公式可以简单的表达为:

                      M = E - N + 2

圈复杂度可以适用于同时分析许多程序或副程序的情形(例如针对一个类中的所有方法),此时 P 等于程序的个数,因为每一个程序的图都是一个独立的连接组件。若每一个程序都只一个结束点,P 也可以视为是结束点的个数。

McCache 证明了任何只有一个进入点和一个技术点的结构化程序,其圈复杂度等于程序中决策点(IF,FOR loops)的个数加 1;

圈复杂度也可以延伸到多个结束点的程序,此时的圈复杂度如下:

                       π - s + 2

其中
π 是程序中决策点的个数

s 为结束点的个数

圈复杂度应用

限制软件复杂度
麦凯布提出圈复杂度时,其原始目的之一就是希望在软件开发过程中就限制其复杂度。他建议程序设计者需计算其开发模块的复杂度,若一模块的圈复杂度超过 10,需再分区为更小的模块。NIST(国家标准技术研究所)的结构化测试方法论已此作法略作调整,在一些特定情形下,模块圈复杂度上限放宽到 15 会比较合适。此方法论也承认有些特殊情形下,模块的复杂度需要超过上述的上限,其建议为“模块的圈复杂度需在上限范围以内,否则需提供书面数据,说明为何此模块圈复杂度有必要超过上限。”

评估软件的结构化程度 「structuredness」
Essential complexity (numerical measure of "structuredness")

启示软件测试工作

圈复杂度决定了需要多少个测试用来达到特定模块测试覆盖率要求;

模块内聚性的评估
可以预期一个复杂度较高模块的内聚性会比较低,至少不会到功能内聚性的程度。一个有高复杂度及低内聚性的模块中会有许多的决策点,这类的模块多半运行超过一个明确定义的任务,因此内聚性较低。一个 2005 年的研究发现复杂度的度量和由专家评估的模块内聚性有高度负相关,反而针对内聚性设计的度量和专家评估结果之间的相关性还比较不明显[6]。

推测软件缺陷个数

许多研究指出一模块及方法的圈复杂度和其中的缺陷个数有相关性,许多这类研究发现圈复杂度和缺陷个数有高度的正相关:圈复杂度最高的模块及方法,其中的缺陷个数也最多。

不过,有些研究是在控制模块大小相近的情形下进行分析(例如比较二个源代码行数相近,但圈复杂度不同模块的缺陷个数),许多这类的研究发现圈复杂度和缺陷个数没有明显相关,不过仍有一些研究认为在此情形下二者仍有相关性。有些此领域的研究者认为那些研究结果圈复杂度和缺陷个数没有明显相关的研究,其研究方法的有效性可能有问题。

莱斯·哈顿认为利用圈复杂度来预测缺陷个数,和利用源代码行数来预测缺陷个数的结果大致相近。

OneAPM Mobile Insight以真实用户体验为度量标准进行 Crash 分析,监控网络请求及网络错误,提升用户留存。访问 OneAPM 官方网站感受更多应用性能优化体验,想阅读更多技术文章,请访问 OneAPM 官方技术博客
本文转自 OneAPM 官方博客

时间: 2024-09-16 17:01:22

程序复杂度之圈复杂度的相关文章

关于圈复杂度CCN NCSS

关于软件度量中的圈复杂度   首先看两个概念:   NCSS(Non Commenting Source Statements)有效代码行,扣除注释. CCN(Cyclomatic Complexity Number),圈复杂度.1个方法的CCN值通常意味着我们需要多少个测试案例来覆盖其不同的路径.当CCN发生很大波动或者CCN很高的代码片段被变更时,意味改动引入缺陷风险高.根据资料,圈复杂度(或CC)大于10的方法存在很大的出错风险. 以下内容摘自:http://blog.csdn.net/y

圈复杂度评价及工具

转载请注明出处:http://blog.csdn.net/horkychen 圈复杂度用来评价代码复杂度,以函数为单位,数值越大表示代码的逻辑分支越多,理解起来也更复杂.圈复杂度可以成为编码及重构的重要参考指标,以指导撰写可读性高的代码.有关圈复杂度的定义,可以自行搜索.<代码大全>有如下的定义: 计算子程序中决策点数量的技术 (代码大全2,19章P458) 1.由1计数,一直往下通过程序. 2.一旦遇到以下关键字,或者其同类的词,就加1:   if, while, repeat, for,

圈复杂度-三元运算语句的复杂度是怎么计算的?

问题描述 三元运算语句的复杂度是怎么计算的? 装了一个sourcemonitor,看了网上的介绍三元云散符语句也包括在内,请问相关法则是什么?比如if(a || b)没搜到,多谢. 函数圈复杂度(Function Complexity):圈复杂度指示一个函数可执行路径的数目,以下语句为圈复杂度的值贡献1:if/else/for/while语句, 三元运算符语句,if/for/while判断条件中的"&&"或"||" ,switch语句,后接break

什么是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 Sour

如何通过程序获得好友朋友圈信息

问题描述 开发一个项目,遇到问题,在知道用户的用户名以及密码的情况下如何将用户好友圈的信息读出来.有类似经验的高手希望能指点一下,非常感谢. 解决方案 解决方案二:这个感觉像脉脉这种的APP,程序应该好解决,问题是用户和用户之间是好友是怎么存储的.第三张表吗.

分布式系统的复杂度度量思考

前言 在构建系统的时候,有时候自己会说,我的系统很复杂,但是这时候又遇到问题了,如何度量一个系统的复杂性呢,这个是个开放性的问题,本身答案见仁见智,这里记录一下自己的思考. 历史借鉴 算法的复杂度 在学习算法的时候,经常会有复杂度的分析,分为时间复杂度和空间复杂度: 自我感觉在时间和空间维度,能够比较清晰的表述清楚: 代码的圈复杂度 概念 循环复杂度(Cyclomatic complexity)也称为条件复杂度,是一种软件度量,是由老托马斯·J·麦凯布(英语:Thomas J. McCabe,

软件设计的复杂度

什么是软件设计的复杂度 软件技术发展的使命之一就是控制复杂度(Complexity).从高级语言的产生,到结构化编程,再到面向对象编程.组件化编程等等.关于复杂度的定义并不一致,想要详细了解的可以读读The Many Faces of Complexity in Software Design. 英文中Complex和Complicated有着微妙的不同.但总结起来,软件复杂度偏负面意义,包括两个要点: - 难以理解 (难以维护和扩展.) - 无法预测行为 复杂度是随着软件规模不断扩大而必然产生

[转载]VS2008 的计算代码度量值

VS2008 里面加了一个 计算代码度量值的功能,那么到底是什么呢?我在msdn 里找到了这个,拷贝下来做个记录.  摘自 http://msdn.microsoft.com/zh-cn/library/bb385914.aspx Visual Studio Team System 代码度量概述 代码度量是一组软件度量值,使开发人员可以更好地了解他们正在开发的代码.利用代码度量,开发人员可以了解哪些类型和/或方法应该返工或进行更彻底的测试.开发团队可以识别潜在的风险.了解项目的当前状态,并跟踪软

网站推广之链接广泛度分析

链接|推广|网站推广 Internet的变化日新月异,其庞大的容量对搜索引擎的索引更新和服务无疑是一种考验.搜索引擎也一直在努力寻求创新的途径,例如以关联站点的广泛度为基础进行排名,以此抵消对搜索引擎的spam伎俩和对页面因素恶意操纵的不良竞争结果,达到为用户提供最为精准和相关的搜索结果的目的.如今,通过将链接广泛度这个因素整合到其排名算法中,搜索引擎(例如Google)已然能够为冲浪者们提供卓越的搜索经验. 但这并不意味着我们就可以对页面因素和网站内容掉以轻心.正确的理解应该是:对于两个页面优