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 -
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.
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.
źródło
WP_Query::get_posts()
miał złożoność NPath 1,435 Quindecillion w 2013 roku. Obecnie jest jeszcze gorzej…Odpowiedzi:
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.
źródło
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.
źródło