Ist eine NPath-Komplexität von über 16 Oktillionen realistisch? Oder habe ich das Werkzeug kaputt gemacht?

13

Ich habe gerade einen großen Teil des PHP-Codes (1153 Zeilen) mit PHPMD ( http://phpmd.org/ ) gemessen und es sagt mir, dass der Code eine NPath-Komplexität von 16244818757303403077832757824 hat.

Das sieht für mich nach einer verrückten Zahl aus, was darauf hindeutet, dass PHPMD vielleicht irgendwie kaputt gegangen ist. Ist es überhaupt möglich, dass ein von Menschen geschriebener Code eine so hohe NPath-Komplexität aufweist? Die zyklomatische Komplexität beträgt 351.

Zwei möglicherweise wichtige Details -

  1. Dies war Prozedurcode, gemischt mit HTML, und PHPMD misst nur objektorientierten Code. Um dies zu umgehen, habe ich die gesamte Datei in eine Klasse mit einer einzigen Funktion eingeschlossen - dies ist repräsentativ für die Art und Weise, wie sie verwendet wird.

  2. Die Datei besteht aus einer Reihe verschachtelter switch-Anweisungen, und in diesen befinden sich viele if..else-Anweisungen - es ist also sicherlich ziemlich kompliziert.

Bearbeiten

Ich möchte klarstellen, dass ich nicht in Frage stelle, ob PHPMD mich anlügt. Ich weiß, dass der Code ein schreckliches Durcheinander ist, ich frage mich nur, ob es möglich ist, dass irgendein Code wirklich so schlecht ist. Die Antwort scheint ja zu sein, es ist sehr gut möglich.

Jez
quelle
2
Ich weiß nicht, ob Sie das Tool kaputt gemacht haben, aber # 2 deutet darauf hin, dass der Code wahrscheinlich ein bisschen überarbeitet werden könnte.
LindaJeanne
1
@ LindaJeanne Ich stimme zu. Ich bin nur neugierig , wie viel Chaos es ist.
Jez
2
WordPress ' WP_Query::get_posts()hatte 2013 eine NPath-Komplexität von 1.435 Quindecillion . Heutzutage ist es noch schlimmer…
fuxia
@toscho, das ist meine neue Lieblingsinformation. Vielen Dank!
Jez

Antworten:

24

Das ist durchaus möglich. Nehmen wir an, wir haben 35 Switch-Case-Konstrukte mit jeweils 10 Fällen, was eine grobe zyklomatische Komplexität von 350 ergibt, wenn jeder Switch nach dem anderen ausgeführt wird. Der erste Schalter gibt uns 10 Pfade. Der zweite Schalter gibt uns weitere unabhängige 10 Pfade, so dass wir bis hier 10 · 10 Pfade haben. Mit dem dritten Schalter erhalten wir 10 · 10 · 10 = 10³ Pfade und so weiter, bis wir insgesamt 10 35 Pfade erhalten! Dies ist sogar höher als das Ergebnis von 1,6 · 10 28 Pfaden, was wahrscheinlich auf einen anderen Verzweigungsfaktor zurückzuführen ist, und auf verschachtelte Steuerflussanweisungen, die die Anzahl der Pfade durch Ihren Code verringern.

Als Worst-Case-Szenario für eine gegebene zyklomatische Komplexität c können wir maximal 2 c azyklische Pfade durch den Code haben (hier: 2 351 = 4,6 · 10 105 ).

Das Urteil des Tools ist klar: Der Code, mit dem Sie es zu tun haben, ist ein verworrenes, nicht testbares und nicht zu wartendes Durcheinander. Teilen Sie es in kleinere, unabhängige Funktionen auf und abstrahieren Sie die Wiederholung. Sie können beispielsweise die HTML-Generierung von der Hauptlogik Ihres PHP-Skripts trennen.

amon
quelle
14
Danke für die Analyse. Ich muss darauf hinweisen, dass es nicht mein Code ist ... aber wie so oft scheint es mir mein Problem zu sein.
Jez
1
@Jez, wenn es ein Trost ist, bist du nicht in einer einzigartigen Position.
Daniel Hollinrake
5

Nach dieser Beschreibung ist die NPath-Komplexität in der zyklomatischen Komplexität exponentiell.

Nehmen wir nur einfache if-Anweisungen, wenn Sie zwei dieser Anweisungen haben, sind das im Wesentlichen 4 Routen durch Ihren Code, entsprechend den vier möglichen Kombinationen von wahr / falsch für die beiden Anweisungsbedingungen. Wenn Sie eine weitere if-Anweisung hinzufügen, erhalten Sie 8.

Mit anderen Worten, wenn Ihre gesamte zyklomatische und NPath-Komplexität von einer langen Liste von if-Anweisungen herrühren würde, wäre dies Ihre Gleichung NPath = 2^cyclomatic. Vergleicht man das mit Ihren Zahlen, so ist 2 ^ 351 = 4,6 * 10 ^ 105, weitaus höher als die von Ihnen gemeldete NPath-Komplexität.

Ich weiß nicht, wie viel PHPMD tut, um das Zählen von Pfaden zu vermeiden, die eigentlich unmöglich sind (z. B. zwei sich gegenseitig ausschließende Bedingungen, die beide als wahr bewertet werden). Möglicherweise würde eine manuelle Analyse ergeben, dass viele der Pfade tatsächlich unmöglich sind, sodass der Code so geschrieben ist, dass die NPath-Metrik aufgeblasen wird. Wenn Sie eine Liste mit 351 if-Anweisungen hätten, aber überprüfen könnten, ob tatsächlich nur eine eingegeben wurde, könnten Sie die Liste in eine Kette von if ... else-Anweisungen umwandeln, wodurch sich Ihre NPath-Komplexität von 4,6 * 10 verringert ^ 105 bis 353.

Da Sie jedoch nur die Informationen in Ihrer Frage kennen und nicht wissen, wie viel von dieser Art der Vereinfachung durch PHPMD getan werden könnte oder bereits getan wird, erscheint die Zahl realistisch.

Ben Aaronson
quelle