Skip to content

Рекомендации

Рекомендация — одно конкретное actionable наблюдение: конкретный модуль на разбивку, конкретный импорт на конвертацию, конкретный цикл на разрыв. У каждой есть данные, её породившие (чтобы можно было проверить), объяснение и — где это осмысленно — counterfactual («removes 7 of 12 cycles in this group»).

Каталог намеренно небольшой. Лучше пропустить пограничный случай, чем выдать вам 200 шумных карточек «consider reviewing X».

Как рекомендации скорятся

У каждой рекомендации есть severity (info / low / medium / high), вычисленный из лежащего в основе сигнала. Десктоп сортирует по severity, потом по импакту (циклов разорвано, модулей затронуто). CLI отдаёт те же данные в поле recommendations[] JSON-конверта.

--fail-on recommendations:N в check срабатывает, когда суммарных рекомендаций > N — полезен как «любой новый совет вообще» гейт; в большинстве проектов вы предпочтёте более конкретные cycles:0 или layer-violations:0.

Каталог

split-god-module

Модуль попадает в топ-5% проекта по fan-in, имеет fan-in ≥ 8 и длину ≥ 300 строк.

Все три порога важны. Один fan-in — over-flag для маленьких heavily-used утилит. Одни строки — over-flag для длинных, но изолированных файлов. Вместе они ловят паттерн «этот файл делает слишком много, и от него все зависят».

Типичный фикс: найти когезивные группы экспортов, вынести их в соседние файлы, подкрутить импорты. Часто один файл превращается в 3–4 файла половинного размера.

unused-utility

Файл, классифицированный как util (путь матчит utils|lib|helpers), с fan-in 0. Fan-in считает статические импорты, динамические импорты (включая template-literal import() и import.meta.glob), entry-точки и интеграционные файлы (loaders, plugins, registries) — последние из «unused» исключаются.

Типичный фикс: удалить файл. Одна из немногих рекомендаций, где действие однозначно.

cycle-break-candidate

Для каждого цикла — самое высокоскоренное внутреннее ребро по feedback-arc-set эвристике. Идёт с counterfactual removes N of M cycles in this group.

Типичный фикс: разрезать ребро — удалением, инверсией или переносом типа.

cycle-break-cluster

Группирует параллельные циклы, проходящие через одни и те же back-рёбра, в одну рекомендацию. Полезно, когда SCC содержит несколько циклов, делящих одно-два «закрывающих» импорта.

Для каждого back-ребра в кластере — точный (для маленьких) или оценочный (для больших) счётчик отдельных циклов, проходящих через него. Берите с самым высоким счётчиком первым.

type-only-candidate

Файл импортирует имя из другого файла, но все использования этого имени — типовые позиции (x: SomeType, extends SomeInterface, as SomeType). Замена import на import type безопасна и стирает импорт при сборке — а любой цикл, в котором он участвовал, исчезает с ним.

Одно value-использование (SomeType(), typeof SomeType) дисквалифицирует. Мы никогда не флагаем кандидата, если хотя бы одно использование — runtime-значение.

Типичный фикс: добавить модификатор type к существующему импорту. Однострочное изменение.

Это единственный вид рекомендации с встроенным auto-fix в десктоп-приложении. Иконка-палочка рядом с ? открывает side-by-side diff и предлагает Применить / Применить и пересканировать / Скопировать патч. Патч генерируется из AST (ts.createSourceFile): import { A, B } from 'x' становится import type { A, B } from 'x'; если только часть bindings — type-only, импорт разделяется (import { runtime } from 'x'; import type { Foo } from 'x';), чтобы value-сторона продолжала работать. Backup'ы пишутся в .archora/backups/. См. Работа с графом.

misplaced-by-layer

Модуль сидит в слое X, но ≥ 70% его dependents — в одном другом слое Y, при минимум 5 dependents всего.

Типичный фикс: перенести файл в слой Y. Убирает большинство cross-layer переходов разом.

top-violator

Один модуль — источник нескольких нарушений слоёв. Рекомендация суммирует количество и целевые слои.

Типичный фикс: ревью импортов этого одного модуля. Часто причина — смешанные ответственности; разбиение (или перенос) убирает несколько нарушений за один PR.

isolated-cluster

Связная компонента неориентированного графа импортов (без type-only рёбер) с ≥ 5 модулями, у которой:

  • нет entry-точек внутри,
  • нет инфраструктурных файлов,
  • размер не превышает половины кодбейза (чтобы не флагать основную компоненту как «изолированную»).

Типичный фикс: разобраться. Скорее всего dead code, удалённая фича, не до конца почистившаяся, или vendored-копия, которая не подключилась. Подтвердив — удалить или подключить.

Достижимый runtime-код (MFE-loader-ы, import.meta.glob, кастомные dynamic-loader-ы из archora.config) подцепляется до запуска этого правила, чтобы не было ложных срабатываний на лениво загружаемых маршрутах.

Почему нет других рекомендаций?

Мы намеренно не выводим:

  • «Функция X слишком длинная.» Файлы — да, function-level метрики — нет: пришлось бы лезть глубже в парсер, и сигнал слишком шумный.
  • «У модуля X слишком много импортов.» Один высокий fan-out не повод для карточки; если это важно — оно вылезет как hot zone или god-module.
  • «Модуль X часто меняется.» Git-churn — реальный сигнал, но он вне модели архитектуры; пусть его покрывают другие тулы — анализатор остаётся pure-of-graph.

См. также

Выпущено под лицензией BUSL-1.1.