Co oznacza „cykliczność złożoności” mojego kodu?

42

Jestem nowy w statycznej analizie kodu. Moja aplikacja ma złożoność cyklomatyczną wynoszącą 17 754. Sama aplikacja ma tylko 37 672 linii kodu. Czy można powiedzieć, że złożoność jest wysoka w oparciu o linie kodu? Co dokładnie mówi mi złożoność cyklomatyczna?

Wściekły ptak
źródło
To całkowicie zależy od tego, co robisz. Jeśli próbujesz zrobić coś prostego, to jest bardzo, bardzo wysoka. Na przykład nie powinieneś mieć takiego stosunku w „witaj świecie”.
cwallenpoole,

Odpowiedzi:

48

Co dokładnie mówi mi złożoność cyklomatyczna?

Cyklomatyczna złożoność nie jest miarą linii kodu, ale liczbą niezależnych ścieżek przez moduł. Cyklomatyczna złożoność wynosząca 17 754 oznacza, że ​​aplikacja ma 17 754 unikalne ścieżki. Ma to kilka implikacji, zazwyczaj pod względem trudności w zrozumieniu i przetestowaniu aplikacji. Na przykład złożoność cykliczna to liczba przypadków testowych potrzebnych do osiągnięcia 100% zasięgu gałęzi, przy założeniu dobrze napisanych testów.

Dobrym punktem wyjścia może być artykuł w Wikipedii na temat złożoności cyklicznej . Ma kilka fragmentów pseudokodu i kilka wykresów pokazujących, na czym polega złożoność cykliczna. Jeśli chcesz dowiedzieć się więcej, możesz także przeczytać artykuł McCabe'a, w którym zdefiniował złożoność cyklomatyczną .

Moja aplikacja ma cyklomatyczną złożoność 17 754 linii kodu. Sama aplikacja ma tylko 37 672 linii kodu. Czy można powiedzieć, że złożoność jest wysoka w oparciu o linie kodu?

Ani trochę. Aplikacja z kilkoma liniami kodu i dużą liczbą warunków warunkowych zagnieżdżonych w pętlach może mieć wyjątkowo wysoką złożoność cykliczną. Z drugiej strony aplikacja z kilkoma warunkami może mieć niską złożoność cykliczną. To bardzo upraszcza to duże, ale myślę, że to przenosi pomysł.

Nie wiedząc więcej o tym, co robi twoja aplikacja, normalne może być zwiększenie cykliczności. Sugerowałbym jednak mierzenie złożoności cyklicznej na poziomie klasy lub metody, a nie tylko na poziomie aplikacji. Wydaje mi się, że jest to nieco łatwiejsze do zarządzania, koncepcyjnie - łatwiej jest wizualizować lub konceptualizować ścieżki za pomocą metody niż ścieżki w dużej aplikacji.

Thomas Owens
źródło
36

Cyklomatyczna złożoność to sposób na określenie, czy kod wymaga refaktoryzacji. Kod jest analizowany i określana jest liczba złożoności. Złożoność jest określana przez rozgałęzienie (instrukcje if itp.) Złożoność może również uwzględniać zagnieżdżanie się pętli itp. I inne czynniki w zależności od zastosowanego algorytmu.

Liczba jest przydatna na poziomie metody. Na wyższych poziomach jest to tylko liczba.

Liczba 17 754 wskazuje na złożoność projektu (kod całkowity), co nie ma tak dużego znaczenia.

Szczegółowa analiza złożoności na poziomie klasy i metody określi obszary kodu, które należy przekształcić w mniejsze metody lub przeprojektować w celu wyeliminowania złożoności.

Rozważ CASEoświadczenie zawierające 50 przypadków w jednej metodzie. Może każdy stan ma inną logikę biznesową. To wygeneruje cykliczną złożoność 50. Istnieje 50 punktów decyzyjnych. Instrukcja CASE może wymagać przeprojektowania przy użyciu wzorca fabrycznego, aby pozbyć się logiki rozgałęziania. Czasami można dokonać refaktoryzacji (rozbić metodę na mniejsze części), aw niektórych przypadkach tylko przeprojektowanie zmniejszy złożoność.

Ogólnie dla złożoności na poziomie metody:

  • <10 Łatwy w utrzymaniu
  • 11-20 Trudniej w utrzymaniu
  • 21+ kandydatów do refaktoryzacji / przeprojektowania

Weź również pod uwagę, że większe złożoności utrudniają testowanie kodu.

Największa złożoność, jaką widziałem w przypadku jednej metody, to 560. Było to około 2000 wierszy instrukcji if w jednej metodzie. Zasadniczo nieusuwalny, niestabilny, pełen potencjalnych błędów. Wyobraź sobie wszystkie przypadki testów jednostkowych potrzebne dla tej logiki rozgałęziania! Niedobrze.

Spróbuj utrzymać wszystkie metody poniżej 20 lat i zdaj sobie sprawę, że refaktoryzacja dowolnej metody wiąże się z pewnym kosztem.

Jon Raynor
źródło
To lepsza odpowiedź.
Pacerier
2
@Pacerier W takim przypadku po prostu głosuj na odpowiedź;).
Zero3
> „Ogólnie rzecz biorąc, dla złożoności na poziomie metody” Cytat?
Benny Bottema
Jedną z oryginalnych aplikacji McCabe było ograniczenie złożoności procedur podczas opracowywania programu; zalecił, aby programiści policzyli złożoność modułów, które opracowują, i podzielili je na mniejsze moduły, ilekroć cykliczność złożoności modułu przekroczy 10.
Jon Raynor
„Może być konieczne przeprojektowanie instrukcji CASE przy użyciu wzorca fabrycznego, aby pozbyć się logiki rozgałęziania”. Dlaczego? To nie eliminuje złożoności logiki; po prostu to ukrywa i czyni go mniej widocznym, a przez to trudniejszym do utrzymania.
Mason Wheeler,
1

Jest to liczba różnych ścieżek w Twojej aplikacji. Sprawdź ten artykuł IBM na temat CC .

Wydaje się wysoki, ale w twoim przypadku jest to dodanie CC wszystkich metod wszystkich klas i metod. Moje przykłady są bardzo rozciągnięte, ponieważ nie wiem, jak ułożony jest twój kod, ale równie dobrze możesz mieć jedną metodę potwora z 37672 liniami kodu lub 3767 metod z około 10 liniami kodu. Chodzi mi o to, że na poziomie aplikacji wskaźnik ten niewiele znaczy, ale na poziomie metody może pomóc zoptymalizować / przepisać kod na mniejsze metody, aby były mniej podatne na błędy.

Wiele razy czytałem osobiście, że metody z CC wyższym niż 10 mają wyższe ryzyko wad.

Używam Sonaru do testowania jakości kodu moich aplikacji i domyślnie myślę, że wyświetla ostrzeżenie, jeśli masz metody z +10 CC. To jednak może nic nie znaczyć. Jeden konkretny przykład: jeśli użyjesz Eclipse do wygenerowania equalsmetody opartej na właściwościach twojej fasoli, CC bardzo szybko wyjdzie ponad dach ...

Jalayn
źródło
1
Domyślnym ustawieniem PMD jest alarmowanie o cyklicznej złożoności równej 10. Patrzenie na złożoność na poziomie poszczególnych metod pozwala również zignorować metody, które mogą mieć dobre powody wysokiego CC, takie jak equalsmetody generowane .
Thomas Owens
Nie byłem pewien, więc sprawdziłem, ale Sonar wewnętrznie używa PMD, aby uzyskać ten pomiar. To wszystko ma sens :-)
Jalayn
-1

To zależy od tego, jakiego narzędzia użyłeś. Niektóre dostępne tam narzędzia open source biorą klasę jako moduł lub inny poziom struktury jako moduł. Dlatego im większy jest projekt, tym większa jest jego cykliczność. Jednak dla mojego osobistego zrozumienia powinno to być oparte na funkcji. Ponieważ im większy projekt, tym funkcje, które ma on spełniać.

Polecam użyć narzędzia o nazwie Lizard. Możesz znaleźć kod zasobu i pobrać plik zip na github. Ma również wersję online, jeśli w kodzie nie ma zbyt wielu poufnych informacji.

Znaczący CCN, na który powinieneś się martwić, opiera się na funkcjach innych niż jakiekolwiek inne. Dodatkowo, utrzymywanie CCN każdej funkcji w stanie zerowym 15 byłoby idealnym zakresem.

Jiahang Li
źródło