Baseline¶
Baseline -- это снимок всех текущих нарушений в вашем проекте. Когда baseline создан, Qualimetrix сообщает только о новых нарушениях -- всё, что уже было, молча игнорируется.
Зачем нужен baseline?¶
Когда вы добавляете Qualimetrix в существующий проект, первый запуск может показать сотни нарушений. Исправить их все сразу невозможно. Baseline позволяет:
- Начать прямо сейчас -- внедрить Qualimetrix, не исправляя каждую legacy-проблему
- Предотвращать новый долг -- каждое новое нарушение обнаруживается сразу
- Отслеживать прогресс -- видеть, сколько старых нарушений вы уже исправили
Создание baseline¶
Запустите анализ с флагом --generate-baseline:
Это выполнит полный анализ и сохранит все нарушения в baseline.json. Файл содержит стабильные хеши для каждого нарушения, поэтому он работает даже при сдвиге номеров строк.
Совет
Коммитьте baseline.json в репозиторий. Так вся команда будет использовать один и тот же baseline.
Использование baseline¶
Передайте флаг --baseline при последующих запусках:
Qualimetrix загружает baseline, выполняет анализ и показывает только нарушения, которых нет в baseline. Если вы добавили новое нарушение -- вы его увидите. Если исправили старое -- оно молча исчезнет из совпадений.
Как это работает¶
Каждое нарушение в baseline идентифицируется по:
- Путь к файлу -- относительный путь к исходному файлу
- Код нарушения -- идентификатор правила (например,
complexity.cyclomatic.method) - Путь символа -- класс, метод или пространство имён, где возникло нарушение
- Хеш содержимого -- стабильный хеш содержимого файла
При запуске с baseline Qualimetrix сопоставляет текущие нарушения с записями baseline. Если совпадение найдено, нарушение отфильтровывается.
Отслеживание прогресса с --show-resolved¶
Хотите узнать, сколько старых нарушений вы исправили? Используйте --show-resolved:
Это добавляет строку сводки с количеством исправленных нарушений -- записей, которые есть в baseline, но больше не обнаруживаются при текущем анализе.
Устаревшие записи¶
Запись baseline становится "устаревшей", когда файл, на который она ссылается, больше не существует (например, файл был удалён или переименован).
По умолчанию Qualimetrix сообщает об ошибке при обнаружении устаревших записей. У вас два варианта:
Вариант 1: Игнорировать устаревшие записи¶
Вариант 2: Очистить baseline¶
Удалить все устаревшие записи:
Совет
Запускайте baseline:cleanup периодически (например, после крупного рефакторинга), чтобы поддерживать файл baseline в чистоте.
Подавление в коде с @qmx-ignore¶
Для случаев, когда нарушение сделано намеренно и вы не хотите включать его в baseline, можно подавить его прямо в коде через комментарии.
Теги подавления работают во всех стилях комментариев:
- PHPDoc-блоки:
/** @qmx-ignore rule */ - Строчные комментарии:
// @qmx-ignore rule - Блочные комментарии:
/* @qmx-ignore rule */
Ограничение
Inline-комментарии на одной строке с кодом не поддерживаются: $x = foo(); // @qmx-ignore rule не сработает.
Размещайте комментарий на отдельной строке перед целевым кодом.
Подавление конкретного правила¶
class LegacyProcessor
{
/**
* @qmx-ignore complexity.cyclomatic Этот метод обрабатывает все legacy-форматы
*/
public function process(array $data): array
{
// сложная, но намеренная логика
}
}
Подавление всех правил для символа¶
Подавление всех правил для всего файла¶
Добавьте docblock на уровне файла в его начале:
Подавление на следующей строке¶
Используйте @qmx-ignore-next-line в комментарии, чтобы подавить нарушение только на следующей строке:
class CliApplication
{
public function run(): void
{
// обработка команд...
// @qmx-ignore-next-line code-smell.exit Точка входа CLI
exit(0);
}
}
Это удобно для точечных подавлений, когда тег на уровне docblock был бы слишком широким.
Также работает для подавления нарушений пустого catch:
try {
$cache->delete($key);
} catch (CacheException) {
// @qmx-ignore code-smell.empty-catch Кеширование best-effort
}
Синтаксис тегов подавления¶
| Тег | Область | Пример |
|---|---|---|
@qmx-ignore <правило> [причина] |
Символ, которому принадлежит комментарий | @qmx-ignore complexity.cyclomatic Legacy-код |
@qmx-ignore * [причина] |
Все правила для данного символа | @qmx-ignore * Сгенерированный код |
@qmx-ignore-next-line <правило> [причина] |
Только следующая строка | @qmx-ignore-next-line code-smell.exit Точка входа CLI |
@qmx-ignore-file |
Весь файл | @qmx-ignore-file |
Имя правила поддерживает сопоставление по префиксу: @qmx-ignore complexity подавляет все правила complexity.*.
Просмотр подавленных нарушений¶
Чтобы увидеть, что было подавлено:
Игнорирование тегов подавления¶
Чтобы запустить анализ так, как будто тегов @qmx-ignore нет:
Переопределение порогов для символа с @qmx-threshold¶
Иногда классу или методу обоснованно нужны другие пороговые значения, чем установлены по умолчанию для проекта. Вместо полного подавления нарушения через @qmx-ignore можно переопределить конкретные пороги с помощью аннотации @qmx-threshold.
Переопределение порога для класса¶
/**
* @qmx-threshold complexity.cyclomatic method.warning=20 method.error=40
*/
class ComplexStateMachine
{
// Методы этого класса используют повышенные пороги сложности
}
Переопределение порога для метода¶
class OrderProcessor
{
/**
* @qmx-threshold complexity.cyclomatic warning=25 error=50
* @qmx-threshold complexity.npath warning=500 error=2000
*/
public function processLegacyOrder(array $data): Order
{
// Этот метод обрабатывает множество legacy edge cases
}
}
Синтаксис¶
- Имя правила использует тот же формат с точками, что и конфигурация (
complexity.cyclomatic,coupling.cboи т.д.) - Опции используют те же ключи, что и YAML-конфигурация и CLI-флаг
--rule-opt - На одном символе можно использовать несколько тегов
@qmx-thresholdдля разных правил - Переопределения порогов действуют только на аннотированный символ -- они не распространяются на дочерние символы
Совет
Используйте @qmx-threshold, когда нарушение ожидаемо, но вы всё равно хотите, чтобы Qualimetrix контролировал какой-то лимит. Используйте @qmx-ignore, когда хотите полностью подавить нарушение.
Лучшие практики¶
1. Коммитьте baseline¶
Это гарантирует, что каждый член команды и CI-пайплайн используют один и тот же baseline.
2. Обновляйте baseline периодически¶
После исправления пачки нарушений перегенерируйте baseline:
bin/qmx check src/ --generate-baseline=baseline.json
git add baseline.json
git commit -m "chore: update Qualimetrix baseline (15 violations resolved)"
3. Используйте --show-resolved в CI¶
Добавьте --show-resolved в ваш CI-пайплайн для отслеживания прогресса:
4. Предпочитайте baseline вместо inline-подавления¶
Используйте @qmx-ignore для намеренных исключений (например, сгенерированный код, осознанные компромиссы). Используйте baseline для legacy-нарушений, которые вы планируете исправить.
5. Очищайте устаревшие записи после рефакторинга¶
bin/qmx baseline:cleanup baseline.json
git add baseline.json
git commit -m "chore: clean up stale baseline entries"
6. Экранируйте теги в документации¶
Если вы упоминаете @qmx-ignore или @qmx-threshold в docblock'ах как документацию (описания формата, примеры использования), оборачивайте их в обратные кавычки, чтобы парсер не интерпретировал их как настоящие теги:
/**
* Используйте `@qmx-ignore complexity` для подавления правила. // экранировано — не парсится
* Используйте `@qmx-threshold complexity.cyclomatic 15`. // экранировано — не парсится
*
* @qmx-ignore coupling Настоящий тег подавления // настоящий — будет распарсен
*/
Одиночная обратная кавычка без пары безопасна — тег будет распарсен как обычно.