56

我一直在尝试测量大型代码库的圈复杂度。

圈复杂度是通过程序源代码的线性独立路径的数量,并且有许多免费工具可供您选择的语言。

结果很有趣,但并不令人惊讶。也就是说,我知道最毛茸茸的部分实际上是最复杂的(评分> 50)。但是我发现有用的是每个方法都分配了一个具体的“坏”数字,作为我在决定从哪里开始重构时可以指出的东西。

你使用圈复杂度吗?你发现的最复杂的代码是什么?

4

15 回答 15

38

我们毫不留情地重构,并使用圈复杂度作为衡量我们“命中列表”代码的指标之一。1-6 我们不会标记复杂性(尽管它可能会因其他原因受到质疑),7-9 是有问题的,除非另有证明,否则任何超过 10 的方法都被认为是不好的。

我们见过的最糟糕的是 87 来自我们不得不接管的一些遗留代码中的一个巨大的 if-else-if 链。

于 2009-04-14T00:13:56.617 回答
19

实际上,圈复杂度可以在方法级别阈值之外使用。对于初学者来说,一个复杂度高的大方法可能会分解成几个复杂度较低的小方法。但它真的改进了代码库吗?当然,通过所有这些方法名称,您可能会获得更好的可读性。但总的条件逻辑并没有改变。并且通常可以通过用多态替换条件来减少总的条件逻辑。

我们需要一个不会仅仅通过方法分解而变绿的指标。我称之为CC100

CC100 = 100 *(代码库的总圈复杂度)/(代码总行数)

于 2009-06-28T07:00:44.233 回答
14

它对我的用处与 big-O 的用处相同:我知道它是什么,并且可以使用它来直觉地判断一种方法是好是坏,但我不需要为每个方法都计算它我写的函数。

我认为在大多数情况下,更简单的指标,如 LOC,至少同样好。如果一个功能不能在一个屏幕上显示,那么它的简单程度几乎无关紧要。如果一个函数接受 20 个参数并产生 40 个局部变量,那么它的圈复杂度是否为 1 无关紧要。

于 2009-04-14T01:00:08.533 回答
8

直到有一个工具可以很好地与 C++ 模板和元编程技术一起工作,它对我的​​情况没有多大帮助。无论如何只要记住这一点

“不是所有可以测量的东西都可以测量,也不是所有可以测量的东西都可以测量”爱因斯坦

因此,请记住也要通过人工过滤传递任何此类信息。

于 2009-04-14T00:42:26.173 回答
7

我们最近开始使用它。我们使用 NDepend 做一些静态代码分析,它测量圈复杂度。我同意,这是一种识别重构方法的好方法。

可悲的是,我们已经看到我们的开发人员在海外创建的一些方法的 # 超过 200。

于 2009-04-14T00:06:29.787 回答
6

当你看到它时,你就会知道复杂性。这种工具的主要用途是标记代码中没有引起您注意的部分。

于 2009-04-14T01:05:32.047 回答
4

我经常测量我的代码的圈复杂度。我发现它可以帮助我发现做得太多的代码区域。使用工具指出我的代码中的热点比阅读数千行代码试图找出哪些方法不遵循 SRP 所花费的时间要少得多。

然而,我发现当我对其他人的代码进行圈复杂度分析时,当我发现圈复杂度在 100 的代码时,通常会导致沮丧、焦虑和普遍愤怒的感觉。是什么迫使人们编写包含数千行代码的方法?!

于 2009-04-14T01:02:32.787 回答
3

这对于帮助确定重构的候选者很有帮助,但保持你的判断力很重要。我支持 kenj0418 的修剪指南范围。

于 2009-04-14T01:12:22.063 回答
2

有一个称为CRAP4J的 Java 度量标准,它根据经验结合了圈复杂度和 JUnit 测试覆盖率来提出一个单一的度量标准。他一直在做研究,试图改进他的经验公式。我不确定它有多普遍。

于 2009-04-14T00:52:49.877 回答
2

是的,我们使用它,我发现它也很有用。我们有一个庞大的遗留代码库要驯服,我们发现了惊人的高圈复杂度。(一种方法中有 387 个!)。CC 将您直接指向值得重构的领域。我们在 C++ 代码上使用 CCCC。

于 2009-09-09T10:51:50.277 回答
2

圈复杂度只是所谓的制造复杂度的一种组合。前段时间,我写了一篇文章总结了代码复杂度的几个维度: Fighting Fabricated Complexity

需要工具来有效地处理代码复杂性。用于 .NET 代码的工具NDepend将让您分析代码复杂性的许多方面,包括代码指标,例如:圈复杂性、嵌套深度、方法缺乏凝聚力、测试覆盖率......

包括依赖分析和包括一种语言(代码查询语言)专门用来问,我的代码中有什么复杂的,以及编写规则?

于 2010-08-28T08:56:44.763 回答
1

我有一段时间没有使用它了,但是在之前的项目中,它确实有助于识别其他人代码中的潜在问题(当然不是我的!)

在找到要检查的区域后,我很快发现了许多逻辑问题(你相信还有很多 GOTOS!)和一些非常奇怪的 WTF 代码。

圈复杂度非常适合显示可能正在做很多事情并因此打破单一责任主体的领域。理想情况下,这些应该分解为多个功能

于 2009-04-14T00:07:11.827 回答
1

恐怕对于我最想要像这样的指标的项目语言LPC,实际上并没有很多免费的工具可以用来生成它。所以不,对我没那么有用。

于 2009-04-14T00:15:10.000 回答
1

+1 为 kenj0418 的命中列表值。

我见过的最差的是 275。还有几个超过 200 的 CC,我们可以重构为更小的 CC;他们仍然很高,但这让他们更进一步。我们对 275 野兽的运气并不好——它(可能仍然是)一个过于复杂的 if 和 switch 语句网络。当他们决定重建系统时,唯一真正的价值是作为一个步骤。

我对高 CC 感到满意的例外是工厂。IMO,它们应该具有较高的 CC,但前提是它们仅进行简单的对象创建和返回。

于 2009-05-26T18:19:34.450 回答
1

了解了它的含义之后,我现在已经开始在“试用”的基础上使用它。到目前为止,我发现它很有用,因为通常高 CC 与Arrow Anti-Pattern齐头并进,这使得代码更难阅读和理解。我还没有一个固定的数字,但是 NDepend 会提醒所有高于 5 的东西,这看起来是研究方法的一个好的开始。

于 2009-06-09T09:39:38.557 回答