N
— количество узлов в графе потока управленияP
— количество компонентов связности (обычно 1 для одного модуля)if
, elif
, else
, while
, for
, case
) увеличивает на 1and
, or
) увеличивает на 1try/except
увеличивает на 1def simple_func(x): # CC = 1
return x * 2
Сложность: 1 (только один путь выполнения)
def check_value(x): # CC = 2
if x > 0: # +1
return True
return False
Сложность: 2 (два возможных пути)
def process_value(x): # CC = 4
if x < 0: # +1
return "Negative"
elif x == 0: # +1
return "Zero"
else: # +1
if x > 100: # +1
return "Large"
return "Positive"
Сложность: 4 (четыре независимых пути)
Сложность | Уровень риска | Рекомендации |
---|---|---|
1-10 | Низкий | Код прост для понимания и поддержки |
11-20 | Умеренный | Рассмотреть рефакторинг |
21-30 | Высокий | Требуется рефакторинг |
31+ | Очень высокий | Критически сложный код |
# Установка: pip install radon
# Анализ кода:
bash
radon cc my_module.py -a
pylint --reports=y --disable=all --enable=cyclic-imports,design my_module.py
Интегрированная платформа для анализа качества кода с поддержкой многих метрик.
# Плохо:
def process_data(data): # CC = 8
if cond1:
...
elif cond2:
...
# ... много условий
# Хорошо:
def _process_case1(data):
...
def _process_case2(data):
...
def process_data(data): # CC = 3
if cond1:
return _process_case1(data)
elif cond2:
return _process_case2(data)
# Вместо множества if/elif
class DataProcessor:
def process(self):
raise NotImplementedError
class Type1Processor(DataProcessor):
def process(self):
...
class Type2Processor(DataProcessor):
def process(self):
...
# Использование словаря вместо условий
process_strategies = {
'type1': handle_type1,
'type2': handle_type2,
}
def process_data(data_type):
return process_strategies.get(data_type, default_handler)()
цикломатическая сложность — это важная метрика качества кода, помогающая оценивать его сложность и поддерживаемость. Поддержание низкой цикломатической сложности (желательно <10) делает код чище, надежнее и легче для тестирования.