Files
slm-design/docs/reference/validation.md

121 lines
11 KiB
Markdown
Raw Normal View History

2026-08-10 09:12:22 +03:00
# Проверка архитектуры
Проверка SLM подтверждает две разные стороны решения:
- смысловая проверка устанавливает ответственность, владельца и корректность границ;
- структурная проверка подтверждает, что решение правильно выражено путями, публичными фасетами и зависимостями.
Успешная сборка или корректно отображаемый интерфейс не доказывают архитектурную корректность.
## Карточка решения
Перед изменением структуры нужно ответить:
| Вопрос | Что зафиксировать |
|---|---|
| Ответственность | Какой результат или поведение изменяется как единое целое |
| Владелец | Какой модуль определяет контракт и внутреннюю реализацию |
| Слой | Какой архитектурной роли соответствует ответственность |
| Потребители | Кому действительно нужен публичный API |
| Зависимости | Какие другие владельцы и возможности необходимы |
| Состояние | Кто определяет смысл и допустимые изменения данных |
| Жизненный цикл | Кто создаёт ресурсы, какова их область жизни и очистка |
| Физическая форма | Какими путями и фасетами представлено принятое решение |
Если ответственность или владелец не определены, проверка путей откладывается: одинаковая файловая структура может представлять разные архитектурные решения.
## Архитектурное ревью
На ревью проверяется смысл кода, который нельзя надёжно вывести из файловой системы:
2026-08-10 12:37:32 +03:00
- одна ли связная ответственность находится внутри модульной границы;
- есть ли у каждой самостоятельной ответственности ровно один ближайший владелец;
2026-08-10 09:12:22 +03:00
- соответствует ли ответственность роли выбранного слоя;
2026-08-10 12:37:32 +03:00
- владеет ли вложенный модуль отдельно сформулированной подответственностью;
- не стали ли группа или сегмент скрытыми владельцами;
- реализует ли внутренний код ответственность ближайшего модуля;
- не принимаются ли props, Context, локальное состояние или lifecycle-код за достаточное основание для новой модульной границы;
- является ли главный файл в корне однозначной реализацией или сборкой ответственности;
- не лежат ли прочие файлы реализации в корне вместо подходящих сегментов;
2026-08-10 09:12:22 +03:00
- нужен ли каждый экспорт реальному внешнему потребителю;
- не раскрывает ли публичный API изменяемые внутренние механизмы;
2026-08-10 12:37:32 +03:00
- определены ли владелец, область жизни, число экземпляров и очистка каждого ресурса.
2026-08-10 09:12:22 +03:00
Окончательные смысловые требования имеют класс `R` в [реестре правил](../rules/registry.md).
## Автоматическая проверка
Проект сопоставляет физические пути с SLM root, слоями, группами, модулями, вложенными модулями, сегментами, фасетами, точками входа `app` и ресурсами `shared`. Сопоставление задаётся локальной конфигурацией и не меняет смысл сущностей.
2026-08-10 12:37:32 +03:00
Наличие `index.ts` само по себе не объявляет модуль. Проверка отличает объявленные корни модулей и их публичные фасеты от локальных точек входа и других внутренних единиц.
2026-08-10 09:12:22 +03:00
Автоматически проверяются:
- допустимое направление импортов по матрице слоёв;
- отдельная папка каждого модуля;
- доступ к чужому модулю только через объявленные фасеты;
2026-08-10 12:37:32 +03:00
- отсутствие циклов в свёрнутом модульном графе;
2026-08-10 09:12:22 +03:00
- отсутствие прямого внешнего доступа к вложенным модулям;
- допустимый транзитивный граф исполняемых импортов каждого фасета среды выполнения;
- динамическое подключение `browser`-фасета с отключённым SSR.
Каждое правило класса `A` должно полностью блокировать проверку при нарушении. SLM не требует конкретного lint-инструмента.
## Проверка зависимостей
Для каждого внешнего импорта определяется:
2026-08-10 12:37:32 +03:00
1. Ближайший модуль-владелец исходного файла.
2. Ближайший модуль-владелец целевого файла.
2026-08-10 09:12:22 +03:00
3. Слои исходного и целевого владельцев.
4. Публичный фасет, через который выполнен импорт.
2026-08-10 12:37:32 +03:00
5. Отсутствие цикла после добавления межмодульного ребра.
2026-08-10 09:12:22 +03:00
2026-08-10 12:37:32 +03:00
Импорты типов (`import type`) и реэкспорты проверяются как архитектурные связи. Импорты файлов одного модуля сворачиваются и не создают межмодульного ребра. Вложенный модуль считается отдельным узлом.
File-level проверка не заменяет модульную: два модуля могут зависеть друг от друга через разные файлы без замкнутого пути между конкретными файлами. Полный алгоритм описан в разделе [Зависимости](../architecture/dependencies.md#запрет-циклов).
## Проверка внутренней структуры
Ревью или дополнительный project lint подтверждают:
- помимо опционального главного framework-файла, остальные компонентные единицы размещены на одном внутреннем уровне модуля;
- их локальные каталоги не содержат другие компонентные единицы или вложенные модули;
- runtime-дерево компонентов не используется как файловая иерархия;
- рекурсивная структурная вложенность проходит только через вложенные модули;
- в корне модуля находятся только фасеты и опциональный главный implementation- или assembly-файл;
- остальная реализация организована сегментами.
2026-08-10 09:12:22 +03:00
## Проверка фасетов
Совместимость фасета определяется всем достижимым исполняемым кодом, а не только его собственным файлом.
Проверка подтверждает:
- `index` не достигает `client`, `browser` или `server`;
- `client` не достигает `browser` или `server`;
- `browser` и `server` не достигают друг друга;
2026-08-10 12:37:32 +03:00
- `browser` экспортирует только browser-only или предназначенный для динамического подключения клиентский код;
2026-08-10 09:12:22 +03:00
- `browser` доступен только через поддерживаемую динамическую границу без SSR;
- специализированный фасет существует ради реального потребителя;
- один исполняемый экспорт не дублируется между фасетами.
Импорт типа остаётся архитектурной зависимостью, но не добавляет исполняемый код в среду фасета.
## Критерий завершения
Изменение соответствует SLM, когда одновременно выполнены условия:
2026-08-10 12:37:32 +03:00
- ответственность и единственный ближайший владелец определены;
2026-08-10 09:12:22 +03:00
- роль слоя соответствует ответственности;
- публичный API минимален и используется всеми внешними потребителями;
2026-08-10 12:37:32 +03:00
- зависимости разрешены и не образуют модульных циклов;
2026-08-10 09:12:22 +03:00
- группа и сегменты не подменяют модульную границу;
2026-08-10 12:37:32 +03:00
- вложенные модули владеют отдельными подответственностями;
- внутренний код реализует ответственность ближайшего модуля;
- framework-компоненты имеют одноуровневую файловую организацию с единственным допустимым исключением для главного файла в корне;
- корень и сегменты соответствуют своим назначениям;
2026-08-10 09:12:22 +03:00
- состояние и ресурсы имеют владельца и корректную область жизни;
- физическая структура однозначно выражает принятое решение;
- применимые автоматические проверки и архитектурное ревью пройдены.