Обзор правил¶
Qualimetrix содержит набор встроенных правил для проверки качества PHP-кода. Каждое правило анализирует определённый аспект кода -- сложность, размер, связанность, проектирование, поддерживаемость или распространённые плохие практики -- и сообщает о нарушениях при превышении пороговых значений.
Идентификаторы правил и судимые метрики¶
Идентификатор правила и ключ метрики -- это два имени из двух словарей, и они не одно и то же даже там, где выглядят похоже. Идентификатор правила -- complexity.ccn -- это то, что настраивают, подавляют и перенастраивают. Ключ метрики -- complexity.ccn -- это измеренное число, которое правило сравнивает со своими порогами.
Там, где правило берёт своё число из каталога метрик, раздел правила на странице группы называет его как Судимая метрика, сразу под идентификатором правила; ту же пару печатает bin/qmx rules. Правила, публикующие величину собственного изготовления -- размер цикла, число сработавших критериев, -- не называют метрики, и вывод команды тоже.
Уровни серьёзности¶
Каждое нарушение имеет один из двух уровней серьёзности:
- Warning (предупреждение) -- код становится сложнее в поддержке. Стоит задуматься о рефакторинге, но ситуация пока не критична.
- Error (ошибка) -- код перешёл порог, за которым вероятны реальные проблемы: баги, трудности с тестированием или сопротивление изменениям. Требуется внимание.
Все пороговые значения можно настроить через конфигурационный файл или параметры командной строки.
Сводная таблица правил¶
Правила сложности¶
Эти правила измеряют, насколько запутан и ветвист ваш код. Сложный код труднее понять, протестировать и безопасно изменить.
| Правило | ID | Что проверяет | Warning | Error |
|---|---|---|---|---|
| Цикломатическая сложность | complexity.ccn |
Количество путей принятия решений в методе | 10 (метод) | 20 (метод) |
| Когнитивная сложность | complexity.cognitive |
Насколько трудно понять код | 15 (метод) | 30 (метод) |
| NPath-сложность | complexity.npath |
Общее количество возможных путей выполнения | 200 (метод) | 1000 (метод) |
| WMC | complexity.wmc |
Суммарная сложность всех методов класса | 50 | 80 |
Подробнее о правилах сложности -->
Правила размера¶
Эти правила проверяют, не разрослись ли ваши классы и пространства имён. Большие классы, как правило, делают слишком много всего сразу.
| Правило | ID | Что проверяет | Warning | Error |
|---|---|---|---|---|
| Количество методов | size.method-count |
Число методов в классе | 20 | 30 |
| Количество классов | size.class-count |
Число классов в пространстве имён | 15 | 25 |
| Количество свойств | size.property-count |
Число свойств в классе | 15 | 20 |
Подробнее о правилах размера -->
Правила проектирования¶
Эти правила проверяют глубину наследования, покрытие типами и структурные проблемы.
| Правило | ID | Что проверяет | Warning | Error |
|---|---|---|---|---|
| Глубина наследования | design.dit |
Глубина цепочки наследования | 4 | 6 |
| NOC | design.noc |
Количество классов, наследующих от данного | 10 | 15 |
| Покрытие типами параметров | design.type-coverage.param |
Процент типизированных параметров | 80% (ниже) | 50% (ниже) |
| Покрытие типами возврата | design.type-coverage.return |
Процент типизированных возвращаемых значений | 80% (ниже) | 50% (ниже) |
| Покрытие типами свойств | design.type-coverage.property |
Процент типизированных свойств | 80% (ниже) | 50% (ниже) |
| Data-класс | design.data-class |
Публичный интерфейс в основном отдаёт данные, низкая сложность | Warning | -- |
| God-класс | design.god-class |
Чрезмерно сложные, большие классы с низкой связностью | 3+ критерия | все критерии |
Подробнее о правилах проектирования -->
Правила связности (Cohesion)¶
Эти правила измеряют, насколько хорошо методы внутри класса работают вместе. Низкая связность указывает на то, что класс занимается слишком многими несвязанными вещами.
| Правило | ID | Что проверяет | Warning | Error |
|---|---|---|---|---|
| LCOM | cohesion.lcom |
Занимается ли класс слишком многими несвязанными вещами | 3 | 5 |
| Метрика | ID | Что проверяет | Рекомендация |
|---|---|---|---|
| TCC | cohesion.tcc |
Доля пар публичных методов, разделяющих свойства | >= 0.5 |
| LCC | cohesion.lcc |
Доля с учётом транзитивных связей | >= 0.5 |
Note
TCC и LCC — это метрики, а не правила. Их нельзя включить или отключить через --disable-rule / --only-rule, и они не генерируют нарушений. В отчётах они отображаются как информационные значения и используются правилом God Class в качестве входных данных. LCOM выше — правило со своими порогами.
Подробнее о правилах связности -->
Правила связанности¶
Эти правила измеряют, насколько тесно ваши классы зависят друг от друга. Тесно связанный код хрупок -- изменение в одном месте может сломать многое в других.
| Правило | ID | Что проверяет | Warning | Error |
|---|---|---|---|---|
| CBO | coupling.cbo |
Общее количество зависимостей | 14 | 20 |
| Нестабильность | coupling.instability |
Насколько класс зависит от других по сравнению с тем, сколько зависят от него | 0.8 | 0.95 |
| Расстояние | coupling.distance |
Баланс между абстрактностью и стабильностью | 0.3 | 0.5 |
| ClassRank | coupling.class-rank |
Критичные узловые классы через алгоритм PageRank | 0.02 | 0.05 |
Подробнее о правилах связанности -->
Правила поддерживаемости¶
| Правило | ID | Что проверяет | Warning | Error |
|---|---|---|---|---|
| Индекс поддерживаемости | maintainability.mi |
Общая оценка поддерживаемости кода | <40 | <20 |
Подробнее о правилах поддерживаемости -->
Правила архитектуры¶
| Правило | ID | Что проверяет | Warning | Error |
|---|---|---|---|---|
| Циклические зависимости | architecture.circular-dependency |
Классы, которые зависят друг от друга по кругу | -- | Error |
| Нарушения слоёв | architecture.layer-violation |
Зависимости между слоями, не разрешённые архитектурной политикой | -- | Warning |
Подробнее о правилах архитектуры -->
Правила дублирования¶
Эти правила обнаруживают дублированные блоки кода по всей кодовой базе с помощью анализа потока токенов.
| Правило | ID | Что обнаруживает | Warning | Error |
|---|---|---|---|---|
| Дублирование кода | duplication.clone |
Структурно идентичные блоки кода между файлами | < 50 строк | >= 50 строк |
Подробнее о правилах дублирования -->
Правила запахов кода¶
Эти правила обнаруживают распространённые плохие практики, которые почти всегда нежелательны вне зависимости от контекста. Большинство по умолчанию выдают уровень Error.
| Правило | ID | Что обнаруживает |
|---|---|---|
| Булевый аргумент | code-smell.boolean-argument |
Параметры типа bool в сигнатурах методов |
| Count в цикле | code-smell.count-in-loop |
Вызов count() в условии цикла |
| Отладочный код | code-smell.debug-code |
var_dump, print_r, debug_backtrace и т.д. |
| Пустой catch | code-smell.empty-catch |
Блоки catch без тела |
| Подавление ошибок | code-smell.error-suppression |
Оператор подавления ошибок @ |
| Eval | code-smell.eval |
Использование eval() |
| Exit | code-smell.exit |
Использование exit() или die() |
| Goto | code-smell.goto |
Использование goto |
| Суперглобальные переменные | code-smell.superglobals |
Прямой доступ к $_GET, $_POST и т.д. |
| Длинный список параметров | code-smell.long-parameter-list |
Методы с чрезмерным количеством параметров |
| Недостижимый код | code-smell.unreachable-code |
Код после return/throw/exit |
| Идентичные подвыражения | code-smell.identical-subexpression |
Одинаковые операнды, дублирующиеся условия, идентичные ветки тернарного оператора |
| Избыточная инъекция в конструктор | code-smell.constructor-overinjection |
Слишком много зависимостей в конструкторе |
| Неиспользуемый private | code-smell.unused-private |
Неиспользуемые приватные методы, свойства, константы |
Подробнее о правилах запахов кода -->
Правила безопасности¶
Эти правила обнаруживают паттерны, которые могут привести к уязвимостям безопасности.
| Правило | ID | Что обнаруживает |
|---|---|---|
| Захардкоженные учётные данные | security.hardcoded-credentials |
Пароли, API-ключи, токены в коде |
| SQL-инъекция | security.sql-injection |
Суперглобальные переменные в SQL-запросах |
| XSS | security.xss |
Несанитизированные суперглобальные в echo/print |
| Внедрение команд | security.command-injection |
Суперглобальные переменные в shell-функциях |
| Чувствительные параметры | security.sensitive-parameter |
Отсутствующий атрибут #[\SensitiveParameter] |
Подробнее о правилах безопасности -->
Правила аннотаций¶
Это правило проверяет сами аннотации @qmx-ignore / @qmx-threshold, написанные в коде, а не код. Оно публикуется через четыре канала — annotation.unresolved-directive, annotation.unsupported-threshold и annotation.invalid-threshold являются ошибками конфигурации и валят прогон безусловно; annotation.unused-directive — обычный долг с настраиваемой severity и единственный канал, который нельзя адресовать @qmx-ignore.
| Правило | ID | Что обнаруживает |
|---|---|---|
| Валидация директив | annotation.directive |
Некорректные, неподдерживаемые, неразбираемые или неиспользуемые директивы @qmx-ignore / @qmx-threshold |
Подробнее о правилах аннотаций -->
Правила обнаружения файлов (Discovery)¶
Это правило сообщает о выборе файлов самим прогоном, а не о коде: значение --exclude или запись exclude:, не совпавшая ни с одним каталогом. Отчёт тогда покрывает файлы, которые автор собирался исключить, а без этого канала промахнувшееся исключение и его отсутствие давали побайтно одинаковый вывод.
| Правило | ID | Что обнаруживает |
|---|---|---|
| Непривязанное исключение | discovery.unmatched-exclude |
Паттерн исключения, не убравший ни одного каталога |
Подробнее о правилах обнаружения файлов -->
Правила подавления (Suppression)¶
Это правило сообщает о конфигурации подавлений самого прогона, а не о коде: значение suppress_paths или suppress_namespaces — глобальное или под rules.<имя> — не назвавшее ни одного проанализированного файла и ни одного объявленного неймспейса. Такое значение ничего не прячет и не спрячет, тогда как автор считает, что прячет.
| Правило | ID | Что обнаруживает |
|---|---|---|
| Конфигурация подавлений | suppression.configuration |
Значение подавления, не назвавшее ничего из измеренного |
Подробнее о правилах подавления -->
Отключение правил¶
Можно отключить отдельные правила или целые группы:
# Отключить одно правило
bin/qmx check src/ --disable-rule=complexity.npath
# Отключить целую группу (wildcard-сопоставление; захватывает только потомков, не сам "code-smell")
bin/qmx check src/ --disable-rule=code-smell.*
Исключение неймспейсов¶
Любое правило поддерживает suppress_namespaces для подавления нарушений из конкретных пространств имён (сопоставление по префиксу). Файлы по-прежнему анализируются и метрики собираются, но нарушения не выводятся:
Это полезно для тестового кода, сгенерированного кода или legacy-модулей, которые вы хотите сохранить в метриках, но исключить из отчёта о нарушениях для конкретного правила.
Настройка пороговых значений¶
Переопределение любого порога через командную строку:
bin/qmx check src/ --rule-opt="complexity.ccn:callable.warning=15"
bin/qmx check src/ --rule-opt="size.method-count:warning=25"
Или в конфигурационном файле qmx.yaml: