¿Es realista una complejidad NPath de más de dieciséis octillones? ¿O he roto la herramienta?

13

Acabo de medir una gran porción de código PHP (1153 líneas) usando PHPMD ( http://phpmd.org/ ) y me dice que el código tiene una complejidad NPath de 16244818757303403077832757824.

Eso me parece un número increíblemente grande, lo que sugiere que quizás PHPMD se ha roto de alguna manera. ¿Es posible que un código escrito por humanos tenga una complejidad NPath tan alta? La complejidad ciclomática es 351.

Dos detalles posiblemente importantes:

  1. Este era un código de procedimiento, mezclado con HTML, y PHPMD solo medirá el código orientado a objetos. Para evitar esto, envolví todo el archivo en una clase con una sola función: esto es representativo de cómo se usa.

  2. El archivo consta de una serie de instrucciones de conmutación anidadas, y dentro de ellas hay muchas instrucciones if..else, por lo que sin duda es bastante complicado.

Editar

Quiero aclarar que no estoy cuestionando si PHPMD me está mintiendo. Sé que el código es un desastre horrible, solo me pregunto si es posible que algún código sea realmente tan malo. Parece que la respuesta es sí, es muy posible.

Jez
fuente
2
No sé si rompió la herramienta, pero # 2 indica que el código probablemente podría ser refactorizado un poco.
LindaJeanne
1
@LindaJeanne Estoy de acuerdo. Sólo soy curioso en cuanto a exactamente cuánto de un desastre que se encuentra.
Jez
2
WordPress ' WP_Query::get_posts()tenía una complejidad NPath de 1.435 Quindecillion en 2013. Es aún peor hoy en día ...
fuxia
@toscho esa es mi nueva información favorita. ¡Gracias!
Jez

Respuestas:

24

Esto es completamente posible. Supongamos que tenemos 35 construcciones de caja de cambio de 10 casos cada una, lo que nos daría una complejidad ciclomática aproximada de 350 cuando cada cambio ocurre uno tras otro. El primer interruptor nos da 10 caminos. El segundo interruptor nos da otros 10 caminos independientes, de modo que tenemos 10 · 10 caminos hasta aquí. ¡Con el tercer interruptor, obtenemos 10 · 10 · 10 = 10³ rutas, y así sucesivamente hasta obtener 10 35 rutas en total! Esto es incluso mayor que el resultado de 1.6 · 10 28 rutas, lo que probablemente se deba a un factor de ramificación diferente, y a las declaraciones de flujo de control anidadas que reducen el número de rutas a través de su código.

Como el peor de los casos para una complejidad ciclomática dada c, podemos tener un máximo de 2 c rutas acíclicas a través del código (aquí: 2 351 = 4.6 · 10 105 ).

El criterio de la herramienta es claro: el código con el que está lidiando es un desastre complicado, no comprobable e imposible de mantener. Considere dividirlo en funciones más pequeñas e independientes y abstraer la repetición. Por ejemplo, podría separar la generación de HTML de la lógica principal de su script PHP.

amon
fuente
14
Gracias por el analisis. Siento la necesidad de señalar que no es mi código ... pero, como suele ser el caso, me parece mi problema.
Jez
1
@Jez, si te sirve de consuelo, no estás en una posición única.
Daniel Hollinrake
5

De acuerdo con esta descripción , la complejidad de NPath es exponencial en la complejidad ciclomática.

Tomando declaraciones if simples, si tiene dos de estas declaraciones, eso es esencialmente 4 rutas a través de su código correspondientes a las cuatro combinaciones posibles de verdadero / falso para las dos condiciones de la declaración. Agregue otra declaración if y obtendrá 8.

En otras palabras, si toda su complejidad ciclomática y NPath provenía de una larga lista de declaraciones if, entonces su ecuación sería NPath = 2^cyclomatic. Comparando eso con sus números, 2 ^ 351 = 4.6 * 10 ^ 105, mucho, mucho más alto que la complejidad de NPath que informó.

No sé cuánto PHPMD hace para evitar contar las rutas que son realmente imposibles (por ejemplo, dos condicionales mutuamente excluyentes que ambos se evalúan como verdaderos). Posiblemente un análisis manual revelaría que muchas de las rutas son realmente imposibles, por lo que el código está escrito de una manera que infla la métrica NPath. Para continuar con lo anterior, si tiene una lista de 351 declaraciones if, pero puede verificar que solo una haya sido ingresada, puede convertirla en una cadena de declaraciones if ... else, reduciendo su complejidad NPath de 4.6 * 10 ^ 105 a 353.

Pero con solo la información en su pregunta, sin saber cuánto de ese tipo de simplificación podría hacerse o si PHPMD ya lo está haciendo, el número parece realista.

Ben Aaronson
fuente