Czy złożoność NPath wynosząca ponad szesnaście octylionów jest realistyczna? A może złamałem narzędzie?

13

Właśnie zmierzyłem dużą część kodu PHP (1153 wierszy) przy użyciu PHPMD ( http://phpmd.org/ ) i mówi mi, że kod ma złożoność NPath 16244818757303403077832757824.

Dla mnie wygląda to na szalenie dużą liczbę, co sugeruje, że PHPMD w jakiś sposób się zepsuło. Czy to możliwe, że fragment kodu napisany przez ludzi ma tak wysoką złożoność NPath? Cyklomatyczna złożoność wynosi 351.

Dwa prawdopodobnie ważne szczegóły -

  1. Był to kod proceduralny, zmieszany z HTML, a PHPMD mierzy tylko kod obiektowy. Aby obejść ten problem, zapakowałem cały plik w klasę za pomocą jednej funkcji - jest to reprezentatywne dla sposobu jego użycia.

  2. Plik składa się z szeregu zagnieżdżonych instrukcji switch, a wewnątrz nich znajduje się wiele instrukcji if..else - więc jest to z pewnością dość skomplikowane.

Edytować

Chcę wyjaśnić, że nie wątpię, czy PHPMD mnie okłamuje. Wiem, że kod jest okropnym bałaganem, po prostu zastanawiam się, czy jest możliwe, aby jakikolwiek kod był tak zły. Wygląda na to, że odpowiedź brzmi tak, to bardzo możliwe.

Jez
źródło
2
Nie wiem, czy złamałeś narzędzie, ale numer 2 wskazuje, że kod prawdopodobnie mógłby stać się nieco refaktoryzowany.
LindaJeanne
1
@LindaJeanne Zgadzam się. Jestem tylko ciekawy, jak dokładnie jest w tym bałaganie.
Jez
2
WordPress ' WP_Query::get_posts()miał złożoność NPath 1,435 Quindecillion w 2013 roku. Obecnie jest jeszcze gorzej…
fuxia
@ toscho to moja nowa ulubiona informacja. Dzięki!
Jez

Odpowiedzi:

24

Jest to całkowicie możliwe. Załóżmy, że mamy 35 konstrukcji skrzynek z 10 przypadkami, co dałoby nam przybliżoną złożoność cykliczną wynoszącą 350, gdy każda zmiana następowałaby jedna po drugiej. Pierwszy przełącznik daje nam 10 ścieżek. Drugi przełącznik daje nam kolejne niezależne 10 ścieżek, dzięki czemu mamy do dyspozycji 10 · 10 ścieżek. Za pomocą trzeciego przełącznika otrzymujemy 10 · 10 · 10 = 10³ ścieżek i tak dalej, aż otrzymamy łącznie 10 35 ścieżek! Jest to nawet więcej niż wynik 1,6 · 10 28 ścieżek, co prawdopodobnie wynika z innego czynnika rozgałęziania oraz z zagnieżdżonych instrukcji sterowania, które zmniejszają liczbę ścieżek w kodzie.

Jako najgorszy scenariusz dla danej cyklicznej złożoności c, możemy mieć maksymalnie 2 c acyklicznych ścieżek przez kod (tutaj: 2 351 = 4,6 · 10 105 ).

Ocena narzędzia jest jasna: kod, którym się zajmujesz, jest zawiłym, niestabilnym i niemożliwym do utrzymania bałaganem. Rozważ podzielenie go na mniejsze, niezależne funkcje i wyodrębnienie powtórzeń. Na przykład można oddzielić generowanie HTML od głównej logiki skryptu PHP.

amon
źródło
14
Dziękuję za analizę. Czuję potrzebę wskazania, że ​​to nie jest mój kod ... ale, jak to często bywa, wydaje mi się, że to mój problem.
Jez
1
@Jez, jeśli to pociecha, nie jesteś w wyjątkowej pozycji.
Daniel Hollinrake
5

Zgodnie z tym opisem złożoność NPath ma charakter wykładniczy w cykliczności.

Biorąc po prostu proste instrukcje if, jeśli masz dwie z tych instrukcji, to w zasadzie 4 trasy przez twój kod, odpowiadające czterem możliwym kombinacjom wartości prawda / fałsz dla dwóch warunków instrukcji. Dodaj kolejną instrukcję if, a otrzymasz 8.

Innymi słowy, gdyby cała złożoność cyklomatyczna i NPath pochodziła z długiej listy instrukcji if, wówczas równanie byłoby NPath = 2^cyclomatic. Porównując to z twoimi liczbami, 2 ^ 351 = 4,6 * 10 ^ 105, znacznie więcej niż zgłoszona złożoność NPath.

Nie wiem, ile robi PHPMD, aby uniknąć zliczania ścieżek, które są w rzeczywistości niemożliwe (np. Dwa wzajemnie wykluczające się warunki, oba oceniające na prawdziwe). Być może ręczna analiza ujawniłaby, że wiele ścieżek jest w rzeczywistości niemożliwych, więc kod jest napisany w sposób, który zawyża metrykę NPath. Kontynuując powyższe, jeśli masz listę 351 instrukcji if, ale możesz zweryfikować, czy faktycznie wprowadzono tylko jedną, możesz przekształcić ją w łańcuch instrukcji if ... else, zmniejszając złożoność NPath z 4,6 * 10 ^ 105 do 353.

Ale mając tylko informacje zawarte w twoim pytaniu, nie wiedząc, ile tego rodzaju uproszczenia można zrobić lub już robi to PHPMD, liczba wydaje się realistyczna.

Ben Aaronson
źródło