超过16八百万的NPath复杂性是否现实?还是我损坏了工具?


13

我刚刚使用PHPMD(http://phpmd.org/)测量了一大段PHP代码(1153行),它告诉我代码的NPath复杂度为16244818757303303403077832757824。

在我看来,这似乎是一个疯狂的数字,这表明PHPMD可能已经以某种方式崩溃了。人类编写的一段代码甚至有可能具有如此高的NPath复杂性吗?圈复杂度为351。

两个可能重要的细节-

  1. 这是与HTML混合在一起的过程代码,PHPMD仅会测量面向对象的代码。为了解决这个问题,我用一个函数将整个文件包装在一个类中-这代表了如何使用它。

  2. 该文件由一系列嵌套的switch语句组成,并且在其中包含许多if..else语句-因此它确实非常复杂。

编辑

我想澄清的是,我不是在问PHPMD是否在骗我。我知道代码是一团糟,我只是想知道任何代码是否真的有那么糟糕。答案似乎是肯定的,这很有可能。


2
我不知道您是否破坏了该工具,但是#2表示该代码可能会被重构。
琳达珍妮(LindaJeanne)

1
@LindaJeanne我同意。我只是好奇,究竟是怎样一个烂摊子的多在不在。
杰斯

2
WordPress' 在2013年WP_Query::get_posts()NPath复杂度为1.435
十亿亿。

@toscho是我最喜欢的新信息。谢谢!
耶斯(Jez)2015年

Answers:


24

这完全有可能。假设我们有35个开关案例结构,每个案例10个案例,当每个开关一个接一个发生时,这将使我们大致具有350的圈复杂度。第一个开关给我们10条路径。第二个开关为我们提供了另一条独立的10条路径,因此到这里为止,我们有10条10条路径。使用第三个开关,我们得到10·10·10 =10³条路径,依此类推,直到总共获得10条35条路径!这甚至比您的1.6·10 28条路径的结果还要高,这可能是由于不同的分支因子以及嵌套的控制流语句所致,它们减少了代码中的路径数。

对于给定的圈复杂度c,在最坏的情况下,我们在代码中最多可以有2个c非循环路径(此处为:2 351 = 4.6·10 105)。

该工具的判断很明确:您要处理的代码是令人费解的,无法测试的和无法维护的混乱。考虑将其拆分为较小的独立功能,然后抽象出重复。例如,您可以将HTML生成与PHP脚本的主要逻辑分开。


14
感谢您的分析。我觉得有必要指出,这不是我的代码...但是,在通常情况下,这确实是我的问题。
耶斯(Jez),2015年

1
@Jez,如果有什么安慰的话,您的位置也不是唯一的。
Daniel Hollinrake 2015年

5

根据此描述,NPath复杂度在圈复杂度上是指数级的。

仅以简单的if语句为例,如果您有两个这样的语句,则基本上是通过代码的4条路由,对应于这两个语句条件的true / false的四种可能组合。添加另一个if语句,您得到8。

换句话说,如果所有循环和NPath复杂度都来自一长串if语句,则等式为NPath = 2^cyclomatic。与您的数字进行比较,2 ^ 351 = 4.6 * 10 ^ 105,远高于您报告的NPath复杂度。

我不知道PHPMD为避免计算实际上不可能的路径(例如两个互斥的条件都评估为true)做了多少工作。可能的情况是,手动分析可能会发现许多路径实际上是不可能的,因此编写代码时会夸大NPath指标。要继续上述操作,如果您有351个if语句列表,但可以验证只输入了一个,则可以将其变成一系列if ... else语句,从而使NPath复杂度从4.6 * 10降低^ 105至353。

但是,仅凭您的问题中的信息,不知道PHPMD可以完成或已经进行了多少简化,这个数字似乎是现实的。

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.