什么是环复杂性?


74

我时不时看到的一个术语是“循环复杂性”。在SO上,我看到了一些有关“如何计算语言X的CC”或“如何用最小的CC来做Y”的问题,但是我不确定我是否真正理解它是什么。

NDepend网站上,我看到一个解释,基本上是这样说的:“方法中的决策数。每个if,for,&&等都将CC的“分数”加+1)。真的吗?如果是,为什么呢?我可以看到有人可能希望将if语句的数量保持在相当低的水平,以使代码易于理解,但这真的是要解决的一切吗?

还是有一些更深层次的概念?

Answers:


55

我不了解更深的概念。我相信通常在可维护性指数的背景下考虑它。特定方法内的分支越多,维护该方法操作的思维模型(通常)就越困难。

具有较高圈复杂度的方法在单元测试中也很难获得完整的代码覆盖率。(谢谢马克·W!)

当然,这带来了可维护性的所有其他方面。错误/回归/可能性等。但是,核心概念非常简单。


10
同样,对单元测试和获得完整的代码覆盖范围进行难度也更大。
Marc W

1
是的,因为他们说您在任何给定的时刻只能将少数事情保留在您的良心中。
steamer25 2009年

4
方法的复杂度还表示实现该方法的100%代码覆盖率所需的单元测试用例数。
Anand Patel

'The more branches there are within a particular method'...您是说更多的IF-Else语句吗?
user20358 '16

40

循环复杂度衡量必须执行具有不同参数的代码块的次数,才能执行通过该块的每条路径。更高的数量是不好的,因为它增加了逻辑错误逃避测试策略的机会。


12
Cyclocmatic complexity = Number of decision points + 1

决策点可能是您的条件语句,例如if,if…else,switch,for循环,while循环等。

下表描述了应用程序的类型。

  • 圈复杂度为1 – 10被认为是常规应用

  • 圈复杂度为11 – 20 application适度应用

  • 圈复杂度为21 – 50 application有风险的应用

  • 循环复杂度超过50 application不稳定的应用程序


4
“循环复杂度=决策点数+ 1”对于我尝试过的所有情况,似乎都成立。我只有一个问题:为什么decision_points+1我们只需要流程图和公式呢?(无论如何,感谢您使用这种非常简单的方法!)
卢克,

11

维基百科可能是您的朋友:圈复杂度的定义

基本上,您必须将程序想象成一个控制流程图,然后

复杂度定义为(...):

M = E − N + 2P

哪里

  • M =圈复杂度,
  • E =图的边数
  • N =图的节点数
  • P =连接的组件数

CC是一个概念,它试图捕获程序的复杂程度以及用一个整数进行测试的难度。


7

是的,就是这样。您的代码可以采用的执行路径越多,必须测试的内容就越多,出错的可能性就越高。


5

我听到的另一个有趣的观点是:

您的代码中缩进最大的位置应具有最高CC。这些通常是确保测试覆盖率的最重要领域,因为预计它们将更难以阅读/维护。正如其他答案所指出的那样,这些也是确保覆盖率的更困难的代码区域。


3

圈复杂性确实只是一个可怕的流行词。实际上,这是在软件开发中用来指出更复杂的代码部分(更可能是错误的程序,因此必须非常仔细和彻底地测试)的度量。您可以使用E-N + 2P公式进行计算,但是我建议您使用插件自动计算得出。我听说有一个经验法则,您应该努力将CC保持在5以下,以保持良好的代码可读性和可维护性。

我最近在我的Java项目上试验了Eclipse Metrics插件,它有一个非常简洁明了的帮助文件,该文件当然会与您的常规Eclipse帮助集成,并且您可以阅读有关各种复杂性度量以及技巧和窍门的更多定义。改善您的代码。


2

就是这样,想法是CC较低的方法具有更少的派生,循环等,这些都使方法变得更加复杂。想象一下,使用分析仪查看500,000行代码,并看到几种CC的数量级更高的方法。这样一来,您便可以专注于重构这些方法以更好地理解(高CC且Bug发生率较高也很常见)


2

例程中的每个决策点(循环,切换,if等)本质上可以归结为一个if语句等效项。对于每个if您都有2个可以采用的代码路径。因此,在第一个分支中有2个代码路径,第二个分支中有4个可能的路径,第三个分支中有8个,依此类推。至少有2 ** N个代码路径,其中N是分支数。

这使得难以理解代码的行为并难以在N超过某个小数时对其进行测试。


2

到目前为止提供的答案没有提到软件质量与循环复杂性之间的关系。研究表明,具有较低的圈复杂度度量标准应该有助于开发质量更高的软件。它可以帮助提高软件质量的可读性,可维护性和可移植性。通常,应该尝试获得5-10之间的圈复杂度度量。

使用诸如圈复杂度之类的度量标准的原因之一是,一般而言,一个人只能在大脑中同时跟踪约7条(正负2条)信息。因此,如果您的软件过于复杂且具有多个决策路径,则您不太可能会看到软件的行为方式(即,它具有很高的圈复杂度指标)。这很可能会导致开发错误或漏洞四出的软件。关于此的更多信息可以在此处以及在Wikipedia上找到。



1

环行复杂度基本上是一种度量标准,用于确定需要更注意可维护性的代码区域。基本上,这将是重构的输入。在避免深度嵌套循环,条件等方面,它绝对可以指示代码的改进领域。


1

就是这样。但是,“ case”或“ switch”语句的每个分支趋向于计数为1。实际上,这意味着CC讨厌case语句以及需要它们的任何代码(命令处理器,状态机等)。


@TetsujinnoOni -五月是。问题是我的典型命令处理器正在从某个外部源读取命令,因此我不能只让编译器将数据项放在动态多态类必须的任何位置。
TED

1

考虑功能的控制流程图,从出口到入口还有一条附加的边。圈复杂度是我们可以在不将图形分为两部分的情况下进行的最大切割次数。

例如:

function F:
    if condition1:
       ...
    else:
       ...
    if condition2:
       ...
    else:
       ...

控制流程图

控制流程图

您可能可以直观地看到为什么链接图的圈复杂度为3。


1
您能否解释上图中的切割方式和切割位置?
Shashi Kumar Raja'Dec

0

Cyclomatric复杂度是衡量一个软件单元的复杂程度的一种度量。它度量程序使用条件逻辑构造(如果,同时,for,switch和case等)可能遵循的不同路径的数量。如果您想了解有关计算的更多信息,请观看以下精彩的youtube视频,您可以观看https://www.youtube.com/watch?v=PlCGomvu-NM

这对设计测试用例很重要,因为它揭示了程序可以采用的不同路径或方案。“为了具有良好的可测试性和可维护性,McCabe建议程序模块的循环复杂度不应超过10”(Marsic,2012,第232页)。

参考:Marsic。,I.(2012年9月)。软件工程。罗格斯大学。取自www.ece.rutgers.edu/~marsic/books/SE/book-SE_marsic.pdf

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.