Перейти к содержанию

Пороговые значения по умолчанию

На этой странице перечислены пороговые значения по умолчанию для каждого правила Qualimetrix. Для метрик, где больше означает хуже, значение на пороге warning или выше даёт предупреждение, а на пороге error или выше — ошибку. Правила, где хуже меньшая величина, используют обратное направление.

Правила сложности (Complexity)

Правила, которые измеряют, насколько сложно понять и протестировать код.

Правило ID Уровень Warning Error Область
Cyclomatic Complexity complexity.ccn Метод 10 20 Метод
Cyclomatic Complexity complexity.ccn Класс (макс.) 30 50 Класс
Cognitive Complexity complexity.cognitive Метод 15 30 Метод
Cognitive Complexity complexity.cognitive Класс (макс.) 30 50 Класс
NPath Complexity complexity.npath Метод 200 1000 Метод
NPath Complexity complexity.npath Класс (макс.) 500 1000 Класс (отключено)
WMC complexity.wmc - 50 80 Класс

Cyclomatic Complexity подсчитывает количество независимых путей выполнения в методе. Метод с CCN равным 10 имеет 10 различных путей для тестирования.

Cognitive Complexity измеряет, насколько сложно читать код. В отличие от цикломатической сложности, вложенные конструкции штрафуются сильнее.

NPath Complexity подсчитывает количество возможных путей выполнения. Растет гораздо быстрее, чем цикломатическая сложность для кода с большим количеством условий.

WMC (Weighted Methods per Class) -- сумма цикломатических сложностей всех методов класса. Высокий WMC означает, что класс делает слишком много.

Правила размера (Size)

Правила, которые проверяют, не стали ли классы и пространства имен слишком большими.

Правило ID Warning Error Область
Method Count size.method-count 20 30 Класс
Class Count size.class-count 15 25 Пространство имен
Property Count size.property-count 15 20 Класс

Правила проектирования (Design)

Правила, которые проверяют дизайн классов и структуру наследования.

Правило ID Warning Error Область
LCOM cohesion.lcom 3 5 Класс
NOC design.noc 10 15 Класс
DIT design.dit 4 6 Класс
Покрытие типами параметров design.type-coverage.param 80 (ниже) 50 (ниже) Класс
Покрытие типами возврата design.type-coverage.return 80 (ниже) 50 (ниже) Класс
Покрытие типами свойств design.type-coverage.property 80 (ниже) 50 (ниже) Класс

LCOM (Lack of Cohesion of Methods) измеряет, насколько хорошо методы в классе связаны друг с другом. Высокий LCOM говорит о том, что класс стоит разделить.

NOC (Number of Children) подсчитывает прямых наследников. Слишком много наследников означает, что родительский класс может быть слишком общим.

DIT (Depth of Inheritance Tree) подсчитывает количество уровней наследования. Глубокие иерархии сложнее понимать и поддерживать.

Type Coverage измеряет процент типизированных объявлений. В отличие от большинства правил, нарушения фиксируются, когда значения падают ниже порога.

Правила связанности (Coupling)

Правила, которые проверяют, насколько тесно классы и пространства имен связаны друг с другом.

Правило ID Warning Error Область
CBO coupling.cbo 14 20 Класс
CBO coupling.cbo 14 20 Пространство имен
Instability coupling.instability 0.8 0.95 Класс
Instability coupling.instability 0.8 0.95 Пространство имен
Distance coupling.distance 0.3 0.5 Пространство имен
ClassRank coupling.class-rank 5 10 Класс
Непривязанный неймспейс фреймворка coupling.unmatched-framework-namespace — (warning, фиксированная) — Проект

CBO (Coupling Between Objects) подсчитывает количество других классов, от которых зависит данный класс. Высокая связанность затрудняет внесение изменений.

Instability -- коэффициент от 0 (полностью стабильный) до 1 (полностью нестабильный). Класс, который зависит от многих других, но от которого никто не зависит -- нестабилен. По умолчанию min_afferent: 1 -- классы и пространства имён без зависимых (Ca=0) пропускаются, так как имеют I=1.0 по определению. Установите 2, чтобы также пропускать символы с единственным зависимым. На уровне пространства имён правило судит coupling.instability-own, а min_afferent считает coupling.ca-own; namespace.min_type_count (по умолчанию 3) пропускает пространство имён, объявляющее меньше собственных классов, трейтов, интерфейсов и енумов с implements.

Distance from the Main Sequence измеряет, насколько хорошо пространство имен балансирует между абстрактностью и стабильностью. Значение, близкое к 0 -- идеально.

ClassRank судит coupling.class-rank-share = coupling.class-rank * N, в единицах равномерного ранга различных измеренных логических вершин графа. Warning 5 и error 10 — фиксированные пороги доли; исходная вероятность PageRank сохраняется отдельной метрикой.

Непривязанный неймспейс фреймворка не имеет числового порога: сообщает о префиксе framework-namespaces, под который не попало ни одно имя прогона — по находке на префикс, с фиксированной severity warning. Это обычная находка, поэтому её видят --fail-on, --disable-rule и baseline. См. правила Coupling.

Правила сопровождаемости (Maintainability)

Эти правила работают наоборот: нарушение фиксируется, когда метрика падает ниже порога, а не превышает его.

Правило ID Warning (ниже) Error (ниже) Область
Maintainability Index maintainability.mi 40 20 Метод

Maintainability Index объединяет сложность, количество строк кода и метрики Холстеда в единую оценку от 0 до 100. Чем выше -- тем лучше. Оценка ниже 20 означает, что код очень сложно поддерживать.

Правила архитектуры (Architecture)

Правила, обнаруживающие структурные проблемы в графе зависимостей. У этих правил нет числовых порогов — они либо находят структурное нарушение, либо нет.

Правило ID Серьёзность По умолчанию Примечания
Циклические зависимости architecture.circular-dependency Error (прямые) / Warning (транзитивные) включено Прямые циклы (размер 2) — Error; более длинные — Warning. См. Правила архитектуры.
Нарушения слоёв architecture.layer-violation Warning (настраивается) включено (no-op без architecture.layers) Числовых порогов нет, только флаг enabled и выбор severity. Активируется, только если секция верхнего уровня architecture: объявляет слои. См. Правила архитектуры.
Диагностики объявления architecture.layer-declaration По каналу включено Собственный enabled; без severity/числовых порогов. Пять configuration errors FilterExempt и четыре ordinary Selectable: см. двери выбора.
Пересечение слоёв architecture.layer-overlap Info (фиксированная) включено через declaration producer Одна occurrence на reachable non-pattern pair, теряющую часть классов.
Невстреченный тип architecture.unmatched-type Warning (фиксированная) включено через declaration producer По authored positive/exclude позиции; требует measured scope и прочитанной Composer-установки.
Недостижимый слой architecture.unreachable-layer Error (фиксированная, не настраивается) включено (срабатывает только с architecture.layers) Один диагностик на каждый объявленный слой, паттерны которого не совпали ни с одним классом, ни с одним концом ребра зависимости. Ловит ситуацию, когда более широкий паттерн раньше в списке тихо перехватывает класс у более позднего слоя; учёт концов рёбер вдобавок к классам не даёт слоям, служащим только для классификации внешнего кода (например, вендорный неймспейс ClickHouseDB\**, видимый лишь как ЦЕЛЬ зависимости), ложно считаться недостижимыми. Это конфигурационная ошибка: она безусловно завершает прогон, независимо от --fail-on, и не может быть принята в baseline или подавлена. Удалённой опции unreachable_layer_severity больше не существует — серьёзность зафиксирована. Слой, объявленный pending: true, эта диагностика пропускает.
Сработавший задел architecture.pending-layer-matched Error (фиксированная, не настраивается) включено (срабатывает только для слоёв с pending: true) Один диагностик на каждый слой, объявленный pending: true — «код ещё не написан», декларация, подавляющая для него architecture.unreachable-layer, — чьи критерии всё же совпали хотя бы с одним классом или концом ребра зависимости. Совпадение засчитывается, даже если все назначения выиграл более широкий слой, объявленный раньше: именно этот случай подсчёт назначений и пропустил бы. Это конфигурационная ошибка: она безусловно завершает прогон, независимо от --fail-on, и не может быть принята в baseline или подавлена. См. Архитектурные правила.
Потенциальное затенение architecture.potential-shadow Error (фиксированная, не настраивается) включено (срабатывает только с architecture.layers) Сообщает о неосвобождённых установленных парах затенения в порядке объявления. Более узкий первый паттерн, получатель остатка и несравнимые непаттерновые критерии освобождены. Частичная потеря непаттернового слоя — обычный architecture.layer-overlap, полная — architecture.unreachable-layer. Эта ошибка конфигурации не подавляется и не принимается в baseline.
Пустой шаблон architecture.empty-template Error (фиксированная, не настраивается) включено (срабатывает только с шаблонными слоями) Один диагностик на каждый шаблонный слой, развернувшийся в ноль конкретных инстансов — фактически отключает привязанную к нему политику. Типичные причины: опечатка в шаблоне паттерна, все кандидаты исключены, или односегментный {var} там, где нужен {var:**}. Это конфигурационная ошибка: она безусловно завершает прогон, независимо от --fail-on, и не может быть принята в baseline или подавлена. Удалённой опции empty_template_severity больше не существует — серьёзность зафиксирована.
Покрытие слоёв architecture.coverage-gap Warning или Error (по режиму coverage-gap) выключено (coverage-gap: ignore) Один агрегированный диагностик, когда architecture.coverage-gap установлен в warn или error и анализируемые логические классы (включая изолированные классы без рёбер) либо концы рёбер зависимости находятся вне всех объявленных слоёв. Печатаемое слово соответствует настроенному режиму coverage-gap:, но это по-прежнему конфигурационная ошибка: при срабатывании она безусловно завершает прогон независимо от --fail-on и не может быть принята в baseline или подавлена. coverage-gap: ignore остаётся способом полностью отключить эту диагностику.
Неотнесённые объявления architecture.unassigned-class Warning или Error (по режиму mode) выключено (mode: ignore) Один агрегированный диагностик со счётом проанализированных class-like объявлений (классы, интерфейсы, трейты, енумы), не попавших ни в один объявленный слой. В отличие от architecture.coverage-gap концы рёбер зависимостей в счёт не входят, поэтому вендорный код, который проект классифицировать не может, в число не попадает. Метрическое значение — абсолютный счёт, поэтому текущее число можно принять в baseline и снижать постепенно. Настраивается собственной опцией mode (CLI: --unassigned-class-mode).

Правила обнаружения файлов (Discovery)

Встроенное правило discovery.unmatched-exclude сообщает о выборе файлов самим прогоном: значение --exclude или запись exclude:, не совпавшая ни с одним каталогом. Числовых порогов у него нет.

Канал Severity По умолчанию Примечания
discovery.unmatched-exclude Warning (фиксированная, ненастраиваемая) включено Обычная находка, а не ошибка конфигурации: общий конфиг может законно называть путь, которого нет в одном из репозиториев. Сообщается на уровне проекта и только на прогоне, чьи пути покрывают цели автозагрузки проекта (под include_autoload_dev — и autoload-dev).

Правила подавления (Suppression)

Встроенное правило suppression.configuration сообщает о конфигурации подавлений самого прогона: значение suppress_paths или suppress_namespaces, глобальное или per-rule, не назвавшее ничего из того, что содержит прогон. Числовых порогов у него нет.

Канал Severity По умолчанию Примечания
suppression.unmatched-path Warning (фиксированная, не настраивается) включено Глобальное значение suppress_paths, не совпавшее ни с одним проанализированным файлом. Уровень проекта, только на прогоне, покрывающем цели автозагрузки проекта (под include_autoload_dev — и autoload-dev); в baseline не пишется.
suppression.unmatched-namespace Warning (фиксированная, не настраивается) включено То же для suppress_namespaces против неймспейсов, объявленных прогоном.
suppression.unmatched-rule-ledger Warning (фиксированная, не настраивается) включено То же для любого из двух ключей, заданного под rules.<имя>.

Правила аннотаций

Встроенное правило annotation.directive сообщает об inline-директивах @qmx-*, которые ничего не адресуют, не могут быть применены, или больше ничего не делают. У него нет числовых порогов, оно сообщает через четыре канала, каждый — своя диагностика. Полный справочник — Правила аннотаций, а о том, как директивы взаимодействуют с подавлением и baseline — Baseline.

Канал Серьёзность По умолчанию Примечания
annotation.unresolved-directive Error (фиксированная, не настраивается) включено Конфигурационная ошибка: директива называет несуществующий канал. Безусловно завершает прогон независимо от --fail-on; не может быть принята в baseline или подавлена.
annotation.unsupported-threshold Error (фиксированная, не настраивается) включено Конфигурационная ошибка: @qmx-threshold нацелен на правило, не объявляющее поддержку override порога. Безусловно завершает прогон; не может быть принята в baseline или подавлена.
annotation.invalid-threshold Error (фиксированная, не настраивается) включено Конфигурационная ошибка: сам payload @qmx-threshold некорректен. Безусловно завершает прогон; не может быть принята в baseline или подавлена.
annotation.unused-directive Warning (настраивается через unused-directive-severity) включено Обычное нарушение, не конфигурационная ошибка: директива корректна, но ничего из адресованного ею не сработало за этот прогон. Может быть принята в baseline, убрана корневым suppress_paths или сужена git-скоупом; suppress_namespaces и собственные исключения правила до неё не достают. Как и duplication.clone, его нельзя адресовать @qmx-ignore.

Размещение, цитирование и границы членов: Inline-подавление.

Правила запахов кода (Code Smell)

Эти правила обнаруживают конкретные паттерны, которые обычно являются плохой практикой. У большинства нет числовых порогов -- они либо находят паттерн, либо нет. Два правила (Long Parameter List и Unreachable Code) используют числовые пороги.

Правило ID Warning Error Статус
Constructor Over-injection code-smell.constructor-overinjection 8 params (non-VO constructors) 12 params включено
Data Class design.data-class WOC ≤ 33%, WMC ≤ 10 — включено
God Class design.god-class WMC ≥ 47, TCC < 0.33, LCOM ≥ 3, LOC ≥ 300 (3 of 4) — включено
Boolean Argument code-smell.boolean-argument — — включено (allowed_prefixes: is, has, can, should, will, did, was; flag_promoted_properties: false)
count() in Loop code-smell.count-in-loop — — включено
Debug Code code-smell.debug-code — всегда включено
Empty Catch code-smell.empty-catch — всегда включено
Error Suppression code-smell.error-suppression всегда — включено (allowed_functions: [])
eval() code-smell.eval — всегда включено
exit()/die() code-smell.exit всегда — включено
goto code-smell.goto — всегда включено
Superglobals code-smell.superglobals всегда — включено
Long Parameter List code-smell.long-parameter-list 4 params (methods, functions; VO ctor: 8) 6 params (VO: 12) включено
Unreachable Code code-smell.unreachable-code 1 2 включено
Unused Private code-smell.unused-private всегда — включено
Identical Sub-expression code-smell.identical-subexpression всегда — включено

Правила дупликации (Duplication)

Правила, которые обнаруживают дублированный код.

Правило ID Warning Error Область
Code Duplication duplication.clone <50 строк кода >=50 строк кода Файл

Code Duplication обнаруживает дублированные блоки кода. Положительные значения по умолчанию: min_lines: 5, min_tokens: 70 и error: 50. Первые два допускают совпавший блок по максимальному числу покрытых строк кода в его копиях и количеству токенов. Каждая допущенная копия сообщается со своим codeLines: Warning ниже error и Error на границе или выше. warning, threshold и локальный @qmx-threshold не поддерживаются.

Правила безопасности (Security)

Правила, которые обнаруживают потенциальные уязвимости безопасности.

Правило ID Серьезность По умолчанию
Hardcoded Credentials security.hardcoded-credentials Error включено
SQL Injection security.sql-injection Error включено
XSS security.xss Error включено
Command Injection security.command-injection Error включено
Sensitive Parameter security.sensitive-parameter Warning включено

Hardcoded Credentials обнаруживает пароли, API-ключи и токены, захардкоженные непосредственно в исходном коде.

SQL Injection обнаруживает использование суперглобальных переменных при построении SQL-запросов без параметризации.

XSS обнаруживает вывод суперглобальных переменных без экранирования (htmlspecialchars и т.д.).

Command Injection обнаруживает использование суперглобальных переменных в функциях выполнения команд без санитизации.

Sensitive Parameter обнаруживает параметры с чувствительными именами без атрибута #[\SensitiveParameter].

Как настроить пороговые значения

С помощью YAML-файла конфигурации

Создайте файл qmx.yaml в корне вашего проекта:

rules:
  complexity.ccn:
    callable:
      warning: 15
      error: 30
    class:
      max_warning: 40
      max_error: 60

  size.method-count:
    warning: 25
    error: 40

  coupling.cbo:
    warning: 18
    error: 25

  maintainability.mi:
    warning: 30
    error: 15

Сокращённая запись threshold

Если вам нужен единый порог без разделения на warning и error (все нарушения — ошибки), используйте ключ threshold вместо отдельных warning/error:

rules:
  complexity.ccn:
    callable:
      threshold: 15    # equivalent to warning: 15, error: 15

  size.method-count:
    threshold: 25

  coupling.cbo:
    class:
      threshold: 18

Это задаёт warning и error одним и тем же значением, так что любое нарушение на этом уровне становится ошибкой. Полезно в CI, где нужен простой бинарный результат "прошёл/не прошёл". Нельзя смешивать threshold с явными ключами warning/error в одном и том же уровне правила.

Каждое измерение покрытия типами -- отдельное правило, и у каждого свой обычный threshold:

rules:
  design.type-coverage.param:
    threshold: 90
  design.type-coverage.return:
    threshold: 90
  design.type-coverage.property:
    threshold: 80

Вычисляемые метрики (health scores) тоже поддерживают threshold:

computed_metrics:
  health.complexity:
    threshold: 50      # score below 50 → error

Затем запустите анализ с указанием файла конфигурации:

vendor/bin/qmx check src/ --config=qmx.yaml

Отключение правил

Чтобы полностью отключить правило, установите enabled: false:

rules:
  code-smell.boolean-argument:
    enabled: false

Отключение группы правил

Вы можете отключить все правила в группе через CLI:

vendor/bin/qmx check src/ --disable-rule=code-smell.*

code-smell.* отключает всех потомков группы code-smell; голый префикс code-smell без звёздочки теперь ошибка, а не сокращение для всей группы.

Через командную строку

Переопределяйте настройки из командной строки:

vendor/bin/qmx check src/ --disable-rule=complexity.npath

Подавление отдельных нарушений

Добавьте @qmx-ignore в docblock, чтобы подавить конкретное нарушение. @qmx-ignore адресует канал, а complexity.ccn — один канал, публикующийся на двух уровнях (callable и class). Голое имя канала подавляет оба уровня; сузь его до одного через :callable или :class:

/**
 * @qmx-ignore complexity.ccn:callable
 */
function complexButNecessary(): void
{
    // ...
}

Можно также подавить все правила в группе тем же wildcard-видом:

/**
 * @qmx-ignore complexity.*
 */

Полный синтаксис селекторов — в Baseline.

Activation без смены defaults

Числа таблиц не меняются. Написанная class-пара NPath действует без лишнего enabled:true, class.enabled:false выключает её. Верхнее complexity shorthand больше не выключает class, effective bands проверяются с default halves. cohesion.unmatched-exclude-method — secondary project warning с magnitude 1, не новый LCOM threshold и не channel с configured warning boundary. См. конфигурацию.