Калькулятор цикломатической сложности - инструмент Маккейба
Вычисляйте цикломатическую сложность по формуле графа Маккейба M = E − N + 2P или по краткой формуле через решения M = D + 1, чтобы оценить качество ПО.
Выберите метод расчёта, введите параметры графа или число решений и получите оценку цикломатической сложности по Маккейбу с классификацией риска.
Калькулятор цикломатической сложности - инструмент Маккейба
Вычисляйте цикломатическую сложность по формуле графа Маккейба M = E − N + 2P или по краткой формуле через решения M = D + 1, чтобы оценить качество ПО.
Используйте этот метод, если у вас есть граф потока управления. Подсчитайте направленные рёбра (E), узлы (N) и компоненты связности (P, обычно 1 для одной функции).
О калькуляторе цикломатической сложности
Цикломатическая сложность — это метрика качества ПО, предложенная Томасом Дж. Маккейбом в 1976 году. Она количественно оценивает структурную сложность программы, подсчитывая число линейно независимых путей через исходный код. Чем выше сложность, тем больше тестовых случаев нужно для проверки каждой ветви, и тем труднее понять, изменить и поддерживать код.
Метрика основана на теории графов. Программа моделируется как граф потока управления (CFG), в котором каждый узел представляет базовый блок — линейную последовательность инструкций с одной точкой входа и одной точкой выхода — а каждое направленное ребро обозначает возможную передачу управления от одного блока к другому. Условные операторы, циклы и обработчики исключений создают ветвления, увеличивая и число рёбер, и число независимых путей.
Формула Маккейба: M = E − N + 2P, где E — число рёбер в CFG, N — число узлов, а P — число компонент связности (обычно 1 для одной функции или процедуры). Для полностью линейной программы без ветвлений M равно 1. Каждый дополнительный бинарный узел решения увеличивает сложность ровно на 1. Оператор switch с k вариантами добавляет k к сложности, потому что вводит k новых путей.
На практике более простое правило подсчёта даёт тот же результат для структурированного кода: M = D + 1, где D — общее число точек решения. Точка решения — это любая конструкция, которая может направить выполнение по двум или более путям: if или else-if, case в switch, заголовок цикла for, while или do-while, тернарный оператор, логическое AND или OR с коротким замыканием, создающее ветвление, а также блок catch.
В отраслевых рекомендациях значения 1–4 считаются низким риском, 5–7 — умеренным, 8–10 — высоким, где следует подумать о рефакторинге, а выше 10 — очень высоким, где настоятельно рекомендуется разбить функцию. Значение сложности также показывает минимальное число тест-кейсов, необходимое для полного покрытия ветвей: функции с цикломатической сложностью 8 нужно не менее 8 тестов, чтобы пройти по каждому независимому пути.
Важно понимать, что именно цикломатическая сложность измеряет, а что нет. Она не измеряет напрямую количество строк кода, производительность или корректность алгоритма. Очень длинная, но полностью последовательная функция может иметь сложность 1, а короткая функция с глубоко вложенными условиями — сложность 20. Метрика специально отражает структуру путей решений, которая является главным источником трудозатрат на тестирование и наиболее частой причиной скрытых дефектов. В сочетании с код-ревью и другими метриками качества цикломатическая сложность служит практическим ориентиром для поиска функций, которые нужно в первую очередь рефакторить и тестировать.
Примеры цикломатической сложности
Три примера показывают оба метода расчёта на реалистичных структурах кода.
| Ввод | M | Пояснение |
|---|---|---|
| E = 9, N = 8, P = 1 | M = 3 | Графовый метод: 9 − 8 + 2×1 = 3. Простая функция с двумя if и одним циклом. |
| D = 4 decisions | M = 5 | Метод по решениям: 4 + 1 = 5. Функция с двумя цепочками if-else; умеренный риск, удобно контролировать с 5 тест-кейсами. |
| E = 14, N = 10, P = 1 | M = 6 | Графовый метод: 14 − 10 + 2 = 6. switch с 5 вариантами; умеренная сложность, полезно документировать каждую ветвь. |
Как пользоваться калькулятором цикломатической сложности
- Выберите метод расчёта. Используйте графовый метод, если у вас есть или вы можете посмотреть граф потока управления кода. Используйте метод по решениям для быстрой оценки по ключевым словам ветвления.
- Для графового метода: введите число рёбер (E), узлов (N) и компонентов связности (P). Для одной функции P равно 1; вводите фактическое значение только при анализе нескольких несвязанных компонентов вместе.
- Для метода по решениям: посчитайте каждый if, else-if, case, for, while, do-while, тернарный оператор (?:), catch, а также логические операторы короткого замыкания (&&, ||), создающие новую ветвь. Введите это число как D.
- Нажмите Рассчитать. Результат покажет сложность Маккейба M и классификацию риска — Низкий (1–4), Умеренный (5–7), Высокий (8–10) или Очень высокий (>10).
- Используйте значение сложности как минимальное число тест-кейсов, необходимое для полного покрытия ветвей, и рассматривайте рефакторинг любой функции с M > 10.
FAQ по цикломатической сложности
Что измеряет цикломатическая сложность?
Она измеряет число линейно независимых путей через граф потока управления функции — другими словами, сколько существует различных путей выполнения. Каждый дополнительный узел решения (if, цикл, case) добавляет ещё один путь. Это значение равно минимальному числу тест-кейсов, необходимому для полного покрытия ветвей.
Какое значение цикломатической сложности хорошее?
Исходная рекомендация Маккейба — держать M ≤ 10. Значения 1–4 — низкий риск и легко тестируются; 5–7 — умеренные; 8–10 — высокий риск; всё выше 10 — очень высокий риск, и настоятельно рекомендуется рефакторинг в более маленькие и целевые функции.
Метод по графу и метод по подсчёту решений одинаковы?
Для структурированных программ (без GOTO) они дают одинаковый результат. Краткая формула M = D + 1 считает каждое ключевое слово ветвления и прибавляет 1. Графовый метод M = E − N + 2P считает рёбра и узлы графа. Оба метода отражают одну и ту же структурную информацию.
Нужно ли считать каждый case в switch отдельно?
Да. Каждый case — это независимая ветвь, поэтому switch с пятью case добавляет 5 к числу решений (или 5 рёбер в CFG). Некоторые инструменты статического анализа считают только количество групп case, а не каждый case по отдельности; всегда проверяйте документацию инструмента, чтобы измерение было согласованным.
Как цикломатическая сложность связана с тестированием?
Значение сложности M равно минимальному числу независимых тест-кейсов, необходимых, чтобы пройти через каждую ветвь хотя бы один раз. Для функции с M = 8 нужно не менее 8 тщательно продуманных тестов для полного покрытия ветвей. Чем выше сложность, тем больше объём тестирования, выше вероятность дефектов и больше нагрузка на сопровождение — все это веские причины держать отдельные функции ниже M = 10.
Применима ли цикломатическая сложность ко всем языкам программирования?
Да. Метрика применима к любому языку с условными и итеративными конструкциями управления. Точки решения немного различаются по языкам — Python использует elif, Ruby использует case/when, SQL использует CASE/WHEN — но принцип подсчёта одинаков. Автоматические инструменты для Java, Python, JavaScript, C# и большинства других популярных языков реализуют сложность Маккейба как стандартную метрику качества.