Оценки здоровья¶
Qualimetrix вычисляет 6 оценок здоровья для каждого класса, пространства имён и проекта — от 0 (худшее) до 100 (лучшее). Оценки здоровья сводят десятки метрик в быструю картину качества, позволяя моментально определить, какие участки кодовой базы требуют внимания.
Измерения¶
| Измерение | Что измеряет | Ключевые метрики | Пороги (warning / error) |
|---|---|---|---|
health.complexity |
Сложность методов и классов | CCN (avg, max, p95), Cognitive Complexity | 50 / 25 |
health.cohesion |
Связность методов внутри класса | TCC, LCOM4, количество методов | 50 / 25 |
health.coupling |
Зависимости между классами и пространствами имён | CBO, Distance from Main Sequence, efferent coupling | 50 / 25 |
health.typing |
Покрытие типами | Типы параметров, возвращаемых значений, свойств | 80 / 50 |
health.maintainability |
Лёгкость безопасной модификации | Maintainability Index (avg, p5, min) | 50 / 25 |
health.overall |
Взвешенное среднее всех измерений | Все вышеперечисленные | 50 / 30 |
Уровни оценки¶
Каждой оценке присваивается текстовый уровень на основе значения относительно порогов warning (W) и error (E):
- Excellent: score > W + (100 − W) × 0.6
- Good: score > W + (100 − W) × 0.3
- Fair: score > W
- Poor: score > E
- Critical: score ≤ E
Для стандартных измерений (W=50, E=25):
| Уровень | Диапазон |
|---|---|
| Excellent | > 80 |
| Good | 65 – 80 |
| Fair | 50 – 65 |
| Poor | 25 – 50 |
| Critical | ≤ 25 |
Пороги health.typing отличаются
У health.typing пороги по умолчанию W=80, E=50, поэтому границы уровней сдвинуты: Excellent > 92, Good > 86, Fair > 80, Poor > 50, Critical ≤ 50.
Как работают оценки¶
Все оценки здоровья используют штрафной подход: оценка начинается со 100 и уменьшается при обнаружении проблем. Результат ограничивается диапазоном 0–100 функцией clamp. Такой подход обеспечивает хорошую дифференциацию — проекты с умеренными проблемами не скатываются сразу в ноль, а различия между «хорошим» и «отличным» кодом остаются видны.
health.complexity¶
Штрафует за высокую цикломатическую и когнитивную сложность. На уровне класса учитывается средняя и максимальная сложность методов. На уровне пространства имён дополнительно анализируется p95 (95-й перцентиль), что позволяет обнаруживать выбросы — отдельные аномально сложные методы. Максимальная сложность масштабируется через квадратный корень, чтобы один метод-монстр не обрушивал оценку всего пространства имён.
Методы интерфейсов включены в агрегацию
Методы интерфейсов имеют минимальную сложность (CCN=1, cognitive=0, NPath=1) и включены в расчёт .avg и .p95 на уровне пространства имён. В проектах с большим количеством интерфейсов средняя сложность может оказаться ниже ожидаемой. Это сделано намеренно — интерфейсы являются частью кодовой базы — но добавление интерфейсов может немного улучшить оценку сложности без реальных изменений логики.
health.cohesion¶
Оценивает, насколько методы класса работают с общими данными. Основана на TCC (Tight Class Cohesion) и LCOM4. Формула корректирует «чистые» методы (без обращения к свойствам) — такие методы завышают LCOM и занижают TCC, не являясь реальной проблемой. Для классов с менее чем 6 методами применяется смягчённая оценка.
health.coupling¶
Измеряет зависимости на уровне класса и пространства имён. На уровне класса используется гиперболическое затухание: зависимости за пределами порога снижают оценку, но каждая следующая зависимость влияет слабее предыдущей. На уровне пространства имён дополнительно учитываются Distance from Main Sequence, средний и экстремальный CBO.
health.typing¶
Непосредственно отражает процент покрытия типами (Type Coverage): параметры, возвращаемые значения и свойства. На уровне пространства имён агрегирует суммы по всем классам.
health.maintainability¶
Основана на Maintainability Index. На уровне класса штрафует за низкий средний MI и за отдельные методы с экстремально низким MI (масштабирование через квадратный корень). На уровне пространства имён основные дифференциаторы — p5 (5-й перцентиль) и минимальное значение.
health.overall¶
Взвешенное среднее всех измерений. Веса различаются по уровням:
- Класс: complexity 35%, cohesion 25%, coupling 25%, typing 15% (maintainability исключена — MI является метрикой уровня метода и её сигнал уже учтён через complexity и cohesion)
- Пространство имён / проект: complexity 30%, cohesion 20%, coupling 20%, typing 10%, maintainability 20%
Чтение оценок здоровья¶
Оценки здоровья доступны в трёх форматах вывода:
summary (по умолчанию) — прогресс-бары в терминале:
Qualimetrix — 45 files analyzed, 1.23s
Complexity ████████████████░░░░ 78 Excellent
Cohesion ██████████████░░░░░░ 68 Good
Coupling ████████████░░░░░░░░ 59 Fair
Typing ██████████████████░░ 88 Excellent
Maintainability████████████████░░░░ 80 Good
Overall ██████████████░░░░░░ 72 Good
json — структурированные данные для CI/CD:
health — текстовая таблица оценок здоровья в терминале:
html — интерактивный отчёт с drill-down по пространствам имён и классам:
Подробнее о форматах вывода — в разделе Форматы вывода.
Настройка¶
Настройка порогов¶
Переопределите пороги warning/error для любого измерения здоровья:
Отключение измерения¶
Или только скрыть из отображения (оценки по-прежнему вычисляются):
Переопределение формул¶
Переопределите формулу для одного или нескольких уровней:
computed_metrics:
health.complexity:
formulas:
class: 'clamp(100 - max((ccn__avg ?? 1) - 5, 0) * 3.0, 0, 100)'
Используйте formula (единственное число), чтобы задать одну формулу для всех уровней:
computed_metrics:
health.complexity:
formula: 'clamp(100 - max((ccn__avg ?? 1) - 5, 0) * 3.0, 0, 100)'
Пользовательские вычисляемые метрики¶
Создавайте собственные метрики с произвольными формулами. Пользовательские метрики используют префикс computed.:
computed_metrics:
computed.my_score:
description: "Custom quality score"
formula: 'clamp((health__complexity ?? 75) * 0.5 + (health__coupling ?? 75) * 0.5, 0, 100)'
levels: [class, namespace, project]
inverted: true
warning: 60
error: 30
Всегда используйте оператор ??
Метрики могут отсутствовать для некоторых символов (например, у интерфейсов нет тела методов). Оператор ?? задаёт значение по умолчанию и предотвращает ошибки вычисления: (ccn__avg ?? 1).
Доступные переменные¶
В формулах доступны все метрики символа. Точки в именах метрик заменяются на __:
| Переменная | Описание | Доступна на уровне |
|---|---|---|
ccn__avg, ccn__max |
Средняя и максимальная цикломатическая сложность | class, namespace, project |
ccn__sum, ccn__p95 |
Сумма и 95-й перцентиль CCN | namespace, project |
cognitive__avg, cognitive__max |
Средняя и максимальная когнитивная сложность | class, namespace, project |
cognitive__sum, cognitive__p95 |
Сумма и 95-й перцентиль Cognitive | namespace, project |
tcc / tcc__avg |
Tight Class Cohesion (0–1) | class / namespace, project |
lcom / lcom__avg |
LCOM4 | class / namespace, project |
cbo__avg, cbo__max, cbo__p95 |
Агрегаты Coupling Between Objects | namespace, project |
ce, ce_packages |
Efferent coupling (зависимости, количество пакетов) | class |
distance / distance__avg |
Distance from Main Sequence | namespace / project |
mi__avg, mi__min |
Средний и минимальный Maintainability Index | class, namespace, project |
mi__p5 |
5-й перцентиль MI | namespace, project |
typeCoverage__pct |
Процент покрытия типами | class |
methodCount |
Количество методов в классе | class |
symbolMethodCount |
Количество методов в области видимости символа | namespace, project |
pureMethodCount_cohesion |
«Чистые» методы (без обращения к свойствам) | class |
health__complexity, health__cohesion, ... |
Значения других оценок здоровья | class, namespace, project |
Это не исчерпывающий список — в формулах можно использовать любую метрику, собираемую Qualimetrix. Команда bin/qmx check src/ --format=metrics-json покажет все доступные метрики для вашего проекта.
Неизвестные ссылки на метрики
Если формула ссылается на несуществующую метрику (например, опечатка ccn__abg вместо ccn__avg), Qualimetrix выдаст явную ошибку вместо молчаливого возврата нуля. Всегда используйте оператор ?? для метрик, которые могут обоснованно отсутствовать: (ccn__avg ?? 0).
Доступные функции¶
| Функция | Описание |
|---|---|
min(a, b) |
Минимум из двух значений |
max(a, b) |
Максимум из двух значений |
abs(x) |
Модуль числа |
sqrt(x) |
Квадратный корень |
log(x) |
Натуральный логарифм |
log10(x) |
Десятичный логарифм |
clamp(value, min, max) |
Ограничение значения диапазоном [min, max] |
Также поддерживаются стандартные операторы Symfony Expression Language: +, -, *, /, ** (возведение в степень), ?? (null coalescing), тернарный оператор.