Od niedawna używam SonarLint do Eclipse , co bardzo mi pomogło. Podniosło mnie jednak pytanie o złożoność cykliczną.
SonarLint uważa za akceptowalny współczynnik CC wynoszący 10, a w niektórych przypadkach przekraczam ten limit, około 5 lub 6 jednostek. Części te są powiązane z elementami odwzorowującymi, w których wartości zależą od różnych zmiennych, na przykład:
- Pole A opiera się na String sA;
- Pole B opiera się na String sB;
- Pole C opiera się na String sC;
- itp ...
Nie mam innego wyboru niż postawienie if
dla każdego pola. To nie jest mój wybór (na szczęście), ale już istniejący i złożony system, którego sam nie mogę zmienić.
Rdzeń mojego pytania brzmi: dlaczego tak ważne jest, aby nie mieć zbyt wysokiego CC w jednej metodzie ? Jeśli przeniesiesz niektóre z twoich warunków w jednej lub więcej pod-metodach w celu zmniejszenia złożoności, nie obniży to kosztów ogólnej funkcji, po prostu przenosi problem gdzie indziej, tak myślę?
(Przepraszam za małe błędy, jeśli występują).
EDYTOWAĆ
Moje pytanie nie odnosi się do globalnej złożoności cyklomatycznej, ale tylko do złożoności pojedynczej metody i podziału metod (mam trudność z wyjaśnieniem, co dokładnie mam na myśli, przepraszam). Pytam, dlaczego dopuszczalne jest podzielenie waszych warunków na mniejsze metody, jeśli nadal należą one do „super metody”, która po prostu wykona każdą pod-metodę, zwiększając w ten sposób złożoność algorytmu.
Drugi link ( dotyczący anty-wzoru ) jest jednak bardzo pomocny.
źródło
Odpowiedzi:
Najważniejsze tutaj: „pojemność mózgu”.
Widzisz, jedną z głównych funkcji kodu jest ... do odczytania . Kod może być łatwy do odczytania i zrozumienia; lub trudne.
A wysokie CC oznacza po prostu wiele „poziomów” w ramach jednej metody. A to oznacza: ty, jako ludzki czytelnik, będziesz miał trudności ze zrozumieniem tej metody.
Kiedy czytasz kod źródłowy, twój mózg automatycznie próbuje spojrzeć z innej perspektywy: innymi słowy - próbuje stworzyć jakąś formę „kontekstu”.
A kiedy masz małą metodę (o dobrej nazwie), która składa się tylko z kilku linii i bardzo niskiego CC; wtedy twój mózg może łatwo zaakceptować ten „blok”. Czytasz to, rozumiesz; GOTOWY.
Z drugiej strony, jeśli twój kod ma wysokie CC, twój mózg wyda wiele „cykli” więcej, aby odjąć to, co się dzieje.
Innym sposobem powiedzenia tego jest: zawsze powinieneś skłaniać się ku preferowaniu złożonej sieci prostych rzeczy zamiast prostej sieci złożonych rzeczy. Ponieważ twój mózg lepiej rozumie małe rzeczy.
źródło
CC, podobnie jak wszystkie inne ogólne zasady dotyczące zapachów kodu, jest heurystyką . To nie jest bezpieczne kryterium, które mówi absolutną prawdę. Gdyby tak było, rozsądną rzeczą byłoby po prostu uczynienie takich metod nielegalnymi w języku i zmusić ludzi do osiągnięcia swoich celów w inny sposób.
Ale nie tak działają wskaźniki. Przez większość czasu ich funkcją jest ostrzeganie ludzi o rzeczach, o których nie byli świadomi. W twoim przypadku masz świadomość, że logika jest skomplikowana, a alternatywne rozwiązania sprawiłyby, że byłaby jeszcze bardziej skomplikowana. Dlatego nie ma sensu próbować spełniać prymitywnej reguły, kiedy jej głównym celem jest wydawanie ostrzeżeń osobom, które nie są świadome, że istnieje problem.
źródło
Krótko mówiąc: chodzi przede wszystkim o czytelność, a zatem i łatwość konserwacji twojego kodu.
Jeśli masz długą, złożoną metodę z dużą liczbą (zagnieżdżonych)
if
, trudno jest powiedzieć, co ona właściwie robi. Jeśli wyodrębnisz niektóre prywatne metody i nadasz im sensowne znaczenie, będzie to o wiele łatwiejsze.źródło
Cyklomatyczna złożoność metody jest związana z liczbą przypadków testowych wymaganych dla metody. W szczególności cykliczna złożoność wynosząca 10 oznacza, że 10 jest górną granicą dla przypadków testowych, aby uzyskać całkowite pokrycie gałęzi dla Twojej metody. Jest to również związane z liczbą ścieżek, które należy przetestować, pomniejszoną o ścieżki niemożliwe.
Poza tym zgadzam się z innymi odpowiedziami na inne względy - zdolności umysłowe dewelopera lub wskaźnik potencjalnych problemów lub refaktoryzacji lub miarę czytelności i możliwości utrzymania kodu .
źródło
CC to tylko heurystyka, a to, jak „zły” jest konkretny wynik, zależy od wielu rzeczy.
To powiedziawszy, zawsze powinieneś widzieć wysokie CC jako coś, co podkreśla kod, który można / powinien zostać zrefaktoryzowany. Mówisz, że przeniesienie
if
instrukcji na inną metodę ukrywa problem - ale czy istnieje tam wzorzec, który można streścić zamiast kopiować wklejanie n razy? Jeśli jest to długiif-else
łańcuch, czy możesz zamienić go w instrukcję switch, a może użyć polimorfizmu lub czegoś innego? Jeśli istnieje głębokie zagnieżdżanie, czy niektóre z waszych klauzul warunkowych można połączyć, czy też oznacza to oddzielne obowiązki, które należy podzielić na różne klasy?źródło
Widzę złożoność cykliczną jako ostrzeżenie. Jeśli umiesz czytać kod i nie jest to zbyt skomplikowane do zrozumienia, nie martwiłbym się tym zbytnio, prawdopodobnie są ważniejsze rzeczy, o które należy się martwić, zawsze takie są.
Jednym ze sposobów zmniejszenia wspomnianego CC jest użycie polimorfizmu, ponieważ otagowałeś swoje pytanie tagiem Java. Dlatego zamiast ciągów wpisywanych ścieżek kodu można używać dobrze nazwanych klas. Może to pomóc, ale czasami jest przesadne i może sprawić, że kod będzie jeszcze trudniejszy do zrozumienia.
Może to być jednak znak kodu, który będzie trudny do utrzymania. Czy czytając tę metodę, łatwo jest zobaczyć, którą ścieżkę kodu pójdziesz w dół dla każdego przypadku? Czy byłbyś w stanie pominąć tę metodę, jeśli nie znasz dobrze podstawy kodu i szukałeś czegoś związanego, ale dalej w kodzie? Wiem, że niektórzy opowiadają się za dzieleniem metod na wiele metod 1/2 liniowych z opisowymi nazwami, ale czasami myślę, że jest to trudniejsze do odczytania niż kod, który miał zastąpić.
Ostatecznie łatwość konserwacji jest trudnym problemem i to Ty decydujesz, który z nich będzie łatwiejszy do odczytania. Fakt, że w ogóle o tym myślisz, oznacza, że jesteś na dobrej drodze. Pamiętaj tylko, że opiekun, który za kilka lat będzie musiał odszyfrować ten kod, może być tobą. Ułatw im to, jak to możliwe.
źródło
Wszystko sprowadza się do tego, ile czasu spędza się na przeglądaniu kodu (cykli mózgowych) i zrozumieniu tego, co robi kod.
Również większe metody są trudniejsze do przetestowania i trudniejsze do przewidzenia, jakie zachowanie może wystąpić.
Cyklomatyczna złożoność jest miarą. W takim przypadku wyższe wartości są wskaźnikami potencjalnych problemów. Złożony kod wymaga więcej czasu na zrozumienie i prawdopodobnie nie jest tak dokładnie testowany jak mniej złożone metody. Dlatego ważne jest, aby pamiętać, które obszary kodu są złożone z tym środkiem do celów refaktoryzacji i konserwacji.
Inną rzeczą do rozważenia jest aktualizacja złożonego kodu. Wykonując analizę, deweloper może zgłosić, że zmiana kodu jest mniej lub bardziej ryzykowna, patrząc na jego złożoność.
Mierzenie złożoności ma więc dużą wartość, którą można wykorzystać i wykorzystać do celów decyzyjnych.
źródło