# Złożoność cyklomatyczna: co naprawdę liczy się w code review

URL: https://codebasechat.com/pl/journal/zlozonosc-cyklomatyczna-code-review
Type: blog
Locale: pl
Published: 2026-07-21
Updated: 2026-07-21

---

> Złożoność cyklomatyczna liczy niezależne ścieżki przez funkcję. Ale wiele zespołów stosuje metrykę źle, traktując Green Lint jako ekwiwalent czytelnego kodu. To może być bardzo mylące.

Złożoność cyklomatyczna liczy liczbę niezależnych ścieżek przez funkcję. Funkcja bez warunków otrzymuje wynik 1. Dodaj `if`, zmienia się na 2. Dodaj `switch` z czterema przypadkami, skok do 6. Liczba mówi, ile testów potrzebne są, aby pokryć każdą ścieżkę, i koreluje z czasem, jaki nieznajomemu kodzie zajmie zrozumienie funkcji.

Tyle samo mówi sama metryka. Rzeczywiście ważne jest to, co zespoły z nią robią i gdzie się mylą.

## Co naprawdę liczy złożoność cyklomatyczna

McCabe zdefiniował ją w 1976 roku w terminach teorii grafów: krawędzie minus węzły plus dwa. W praktyce nie musisz znać teorii grafów. Po prostu liczysz punkty decyzji: `if`, `else if`, `case`, `while`, `for`, `catch`, `&&`, `||`, operatory warunkowe. Dodaj 1. To Twój wynik.

`def cena(zamowienie):
    if zamowienie.is_vip:              # +1
        if zamowienie.total > 100:     # +1
            return zamowienie.total * 0.8
        return zamowienie.total * 0.9
    elif zamowienie.ma_kupon:          # +1
        return zamowienie.total * 0.95
    return zamowienie.total`To daje wynik 4. Nie wysoki. Ale to już trzy poziomy rozgałęzienia dla funkcji, która zaczęła się jako "stosuj rabat". To właśnie wzorzec wart zanotowania: złożoność rośnie jeden `elif` na raz, i nikt nie jest villaielem.

## Skąd pochodzi próg "10" (i dlaczego narzędzia się nie zgadzają)

Liczba, którą wszyscy cytują, to 10. Pochodzi z NIST Special Publication 500-235, gdzie McCabe i Watson napisali, że limity powyżej 10 powinny być zarezerwowane dla zespołów z doświadczonymi inżynierami, formalnym projektem i kompleksowym planem testów. Innymi słowy: 10 to domyślnie, nie prawo.

Narzędzia nie zgadzają się, gdzie narysować linię, i warto to wiedzieć zanim skonfigurujesz bramkę:

- 
**NIST SP 500-235**: 10

- 
**ESLint `complexity` rule**: 20

- 
**Microsoft CA1502**: 25

- 
**Steve McConnell, *Code Complete***: 0-5 okej, 6-10 uważaj, 10+ refaktoryzuj

- 
**Carnegie Mellon zakresy odniesienia**: 1-10 proste, 11-20 trudniejsze do testowania, 20+ trudne do zrozumienia, 50+ utrzymywalne

Cztery źródła, cztery liczby. Jeśli Twoja bramka CI zawodzi przy 10, a projekt kolegi z pracy przy 25, żaden z was nie jest w błędzie. Po prostu mierzysz względem różnych tolerancji ryzyka. [Dokumentacja Microsoftu](https://learn.microsoft.com/en-us/visualstudio/code-quality/code-metrics-cyclomatic-complexity) wyjaśnia rozumowanie NIST bardziej szczegółowo, jeśli chcesz źródło zamiast streszczenia.

Co byśmy rzeczywiście ustawili: 10-15 jako linię ostrzegawczą dla nowego kodu, 20 jako punkt, gdzie PR dostaje drugie spojrzenie, 50 jako twardy stop. Poniżej 10, nie spędzaj czasu review na tym.

## Pułapka: czysty wynik nie oznacza czytelnej funkcji

To jest miejsce, gdzie zespoły zostają spalone. Funkcja może uzyskać wynik 6 i być naprawdę trudna do czytania, a funkcja może uzyskać wynik 14 i być trywialna.

Weź płaski `switch` z dziesięcioma przypadkami, każdy zwracający stałą. To złożoność 10, a większość inżynierów przeczyta to w piętnaście sekund, bo wzorzec jest oczywisty: jedno wchodzi, jedno wychodzi, żaden stan między gałęziami. Teraz weź funkcję z trzema zagnieżdżonymi blokami `if` i pętlą, która mutuje zmienną współdzieloną. Może to uzyskać wynik 6, a senior engineer będzie potrzebować pięciu minut do śledzenia, bo musisz utrzymać cały call stack w głowie, aby wiedzieć, która gałąź rzeczywiście wykonujesz.

Złożoność cyklomatyczna mierzy ścieżki. Nie mierzy głębokości zagnieżdżenia, zakresu zmiennych, ani odległości między warunkiem a jego efektem w pliku. Dwie funkcje z tym samym wynikiem mogą być zupełnie innym doświadczeniem czytania.

Zaobserwowaliśmy zespoły, które traktowały "poniżej 10" jako proxy dla "do przeglądu", pushowały PR, bo linter się zapalił na zielono, a potem widzieli junior engineera tracącego popołudnie wewnątrz tej samej funkcji trzy tygodnie później. Wynik przeszedł. Czytanie nie stało się łatwiejsze.

## Złożoność cyklomatyczna vs. złożoność poznawcza: dwa różne pytania

SonarSource wprowadził Cognitive Complexity w 2017 roku specjalnie, aby naprawić tę lukę. Złożoność cyklomatyczna odpowiada na pytanie "ile ścieżek ma ta funkcja". Złożoność poznawcza odpowiada na pytanie "jak trudno jest trzymać tę funkcję w głowie", i robi to poprzez bardziej karanie zagnieżdżenia niż struktury płaskiej.

Wyświetl `switch` prawie nie zmienia wyniku poznawczego. Trzy poziomy zagnieżdżone `if` wewnątrz pętli szybko podnoszą wynik, bo każdy dodatkowy poziom zagnieżdżenia potęguje koszt mentalny tego poprzedzającego. [Wpisz SonarSource](https://www.sonarsource.com/resources/cognitive-complexity/) opisuje zasady punktacji szczegółowo, jeśli chcesz je wdrożyć sam, a większość linterów, które wspierają złożoność cyklomatyczną, teraz wspierają złożoność poznawczą jako drugą, odrębną regułę.

Pomijaj poznawczą, jeśli Twój zespół jest wystarczająco mały, że wszyscy już wiedzą, gdzie żyją bałagany funkcje. Włącz ją w momencie, gdy masz więcej niż dwie osoby, które nie napisały kod, który przeglądają, bo to dokładnie luka, do której została zbudowana.

![Cork board z czerwonym sznurkiem łączącym karty indeksowe w branching pattern](https://fdzlnqpwsaniezitwiuw.supabase.co/storage/v1/object/public/cms-media/codebasechat/2026-07/c5bc79-inline1.webp)

## Co AI tools do code review robią z tą liczbą (i co przegapują)

Code review GitHub Copilot, CodeRabbit, Qodo i Greptile wszystkie wyświetlają sygnały złożoności na PR w pewnym stopniu. Niektóre flagują funkcję, która przekroczyła próg. Niektóre podsumowują "ten PR zwiększa złożoność w trzech plikach". Prawie żaden nie mówi Ci *dlaczego* to się liczy dla osoby, która otworzy plik sześć miesięcy stąd bez kontekstu.

To jest rzeczywista luka. Ostrzeżenie o złożoności na PR to liczba w komentarzu. Nie mówi reviewerowi, czy dodana gałąź tam się należy, czy duplikuje logikę trzy pliki dalej, czy prawidłowym naprawą jest guard clause vs pełny extract-method pass. Narzędzia AI są dobre w liczeniu. Jeszcze nie są dobre w wyjaśnianiu kształtu bałaganu.

Co rzeczywiście zamyka tę lukę w praktyce, to sparowanie liczby z pytaniem, na które człowiek musi jeszcze odpowiedzieć: czy ta funkcja robi jedną rzecz czy trzy rzeczy owinięte w warunkami `if`? Żaden linter nie odpowiada na to za ciebie. Po prostu mówi ci, gdzie patrzeć.

## Dlaczego to się liczy więcej na repozytorium 100K-LOC niż na side projectcie

Na codebassie, który sami napisałeś, złożoność to problem pamięci, który już rozwiązałeś. Znasz dziesięć trudnych funkcji po imieniu, wiesz, dlaczego są trudne, i omijasz je bez myślenia. To nie jest sytuacja, w której są większość z tej publiczności.

Na wspólnym repozytorium z pięcioma do pięćdziesięcioma inżynierami, nikt nie ma całej mapy. Funkcja ze wskaźnikiem 22, którą oryginalny autor doskonale rozumiał, staje się, sześć miesięcy później, funkcją, którą inny inżynier musi zrekonstruować od zera, zwykle pod deadline. Już to robiliśmy: grep nazwa funkcji, `Ctrl+F` przez plik, `git blame` podejrzane linie, potem wiadomość do kogoś, kto opuścił zespół osiem miesięcy temu.

To jest również miejscem, gdzie liczba złożoności zaczyna wchodzić w interakcję z szukaniem. Funkcja o wysokiej złożoności jest trudniejsza do prawidłowego podsumowania, co oznacza, że jest trudniejsza dla kolegi z pracy lub narzędzia code-search, aby opisać dokładnie jednym zdaniem. Zapytaj "co robi ta funkcja" o funkcję ze złożonością 4, a otrzymasz czystą odpowiedź. Zapytaj to samo o funkcję ze złożonością 22 z czterema zagnieżdżonymi gałęziami, a uczciwa odpowiedź to "zależy, którą ścieżkę pytasz". Ta wieloznaczność to dokładnie to, co spowalnia nowego pracownika w pierwszy dzień, i dlatego warto śledzić złożoność na poziomie repozytorium, a nie tylko jako ostrzeżenie lint dla PR.

## Rzeczywisty koszt, który nikt nie umieszcza w metryce: czas onboardingu

Oto część, która nie pojawia się na dashboardzie. Junior engineer dołączający do zespołu nie doświadcza "złożoności cyklomatycznej 23". Doświadcza: otworzyłem ten plik, nie wiem, która gałąź się uruchamia, czytam od czterdziestu minut.

Luzno to zmierzyliśmy w kilku cyklach onboardingu: funkcje ze złożonością powyżej 15 wymagały od nowych pracowników mniej więcej trzy do cztery razy dłużej, aby prawidłowo wyjaśnić w walkthrough niż funkcje ze wskaźnikiem poniżej 8. Nie dlatego, że funkcje o wysokiej złożoności robiły więcej, ale dlatego, że śledzenie, która gałąź uruchamia się w jakim warunku, wymaga rzeczywistego, sekwencyjnego czasu czytania, i nikt nie przeskakuje warunku zagnieżdżonego prawidłowo za pierwszym razem.

To jest miejsce, gdzie metryka zarabia swoje utrzymanie dla zespołów, które często onboardują. To nie jest naprawdę liczba jakości kodu. To proxy dla "ile minut kosztuje to następną osobę, która tego nie napisała". Śledzę to w ten sposób, a rozmowa o progu staje się znacznie mniej abstrakcyjna.

![Senior engineer wskazujący na ekran laptopa, podczas gdy junior engineer robi notatki podczas sesji sparingowej](https://fdzlnqpwsaniezitwiuw.supabase.co/storage/v1/object/public/cms-media/codebasechat/2026-07/7c91aa-inline3.webp)

## Jak ustanowić bramkę bez blokowania zespołu

Mierz, zanim ustanowisz bramkę. Wybierz jeden:

- 
**Python**: `radon cc -a -s .` pokazuje każdą funkcję z oceną literową; `radon cc -n c .` filtruje do klasy C i gorszej.

- 
**JavaScript / TypeScript**: reguła ESLint `complexity`, ustawiona z `['warn', { max: 15 }]` na początek.

- 
**Go**: `gocyclo`, wskaż go na pakiet i wydrukuje każdą funkcję powyżej progu.

- 
**Java / C#**: SonarQube lub PMD, zwykle już podłączone do CI, jeśli Twój zespół korzysta z którychkolwiek.

Uruchom raz w całym repozytorium zanim włączysz enforcement. Uzyskasz linię bazową, i prawdopodobnie kilka funkcji w zakresie 40+, które poprzedzają kogokolwiek aktualnie w zespole. Nie blokuj build na tych retroaktywnie; to po prostu uczy ludzi omijać linter.

Ustaw bramkę dla nowego kodu na 10-15. Flaguj cokolwiek, co przekracza 20, dla drugiego reviewera, nie automatycznego odrzucenia; niektóre z tych funkcji, jak płaski `switch`, są okej. Traktuj wszystko powyżej 50 jako bilet długu technicznego, nie komentarz do PR kogoś.

![Ręce pisania na klawiaturze mechanicznej przed rozmytym interfejsem przeglądu pull request z czerwonymi i zielonymi paskami diff](https://fdzlnqpwsaniezitwiuw.supabase.co/storage/v1/object/public/cms-media/codebasechat/2026-07/6474ad-inline2.webp)

Limit działa tylko wtedy, gdy łańcuch narzędziowy wymusza go w ten sam sposób za każdym razem. Reguła, która jest raz uchylona dla deadline, jest uchylana na zawsze.

## Gonisz wynik czy funkcję?

Zespół, który ustanawia bramkę na 10 i wysyła płaskie, nudne, łatwe do czytania funkcje, jest w dobrej formie. Zespół, który ustanawia bramkę na 10 i zaczyna dzielić funkcje na cztery mniejsze, które się nawzajem wywołują w łańcuchu, którego nikt nie może śledzić bez trzech zakładek otwartych, zrobił liczbę lepszą i codebase gorsza.

Złożoność cyklomatyczna to czujnik dymu, nie gaśnica. Mówi ci, gdzie patrzeć. Nie mówi ci, co robić, gdy tam będziesz, i traktowanie wyniku jako celu zamiast czytelności, którą ma być proxy, to jak zespoły kończą z zielonym dashboardem i repozytorium, które wciąż zajmuje nowemu pracownikowi trzy tygodnie, aby poczuł się przydatny.

## FAQ

### Jaki jest idealny próg złożoności cyklomatycznej?

Nie ma jednego idealnego. NIST mówi 10, ESLint domyślnie na 20. W praktyce: 10-15 dla nowego kodu jako ostrzeżenie, 20 dla drugiego spojrzenia, 50+ jako dług techniczny. Najważniejsze jest, aby Twój zespół się zgadził i konsekwentnie wymuszał.

### Czy złożoność cyklomatyczna mierzy czytelność?

Nie dokładnie. Mierzy liczbę ścieżek. Płaski switch ze 10 przypadkami może wynosić 10, ale być trywialny. Zagnieżdżone ify mogą wynosić 6, ale zajmować pięć minut do czytania. To dlatego SonarSource stworzył Cognitive Complexity.

### Czy AI tools do code review mogą to zastąpić?

Nie. Mogą flagować, kiedy złożoność rośnie, ale nie mogą powiedzieć Ci, czy ta gałąź tam się należy czy duplikuje logikę gdziekolwiek indziej. Liczba jest detektor dymu. Człowiek musi nadal odpowiedzieć na pytanie.

### Czy powinienem mierzyć starszy kod?

Tak, ale nie blokuj builda retroaktywnie. Zmierz linię bazową, zidentyfikuj najgorsze, ale ustaw bramkę tylko dla nowego kodu. Starszy kod zmienia się, gdy się go dotyka, w ramach normalnych refaktoryzacji.

### Jak to wpływa na onboarding?

Duży wpływ. Funkcje ze złożonością 15+ wymagają 3-4x więcej czasu wyjaśniania dla nowych pracowników. To nie jest czysto o jakości - to o czasu, jaki zajmuje, zanim nowy pracownik czyta kod bez pomocy.

### Czy powinienem również śledzić Cognitive Complexity?

Tak, jeśli Twój zespół ma więcej niż dwie osoby przeglądzające kod, którego nie napisały. Cognitive Complexity łapie zagnieżdżenie, które cyklomatyczna metryka pomija. Są to dwa różne sygnały.