mirror of
https://github.com/gromlab-ru/slm-design.git
synced 2026-08-22 07:30:16 +03:00
sync
This commit is contained in:
95
docs/reference/terminology.md
Normal file
95
docs/reference/terminology.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# Терминология SLM
|
||||
|
||||
Этот документ задаёт нормативный смысл терминов. Определения используются при толковании архитектуры и правил, но сами по себе не являются отдельными правилами.
|
||||
|
||||
## Владение
|
||||
|
||||
### SLM root
|
||||
|
||||
Граница структурной архитектуры одного приложения. Внутри неё определяются владельцы ответственностей, слои, модули и их зависимости.
|
||||
|
||||
### Ответственность
|
||||
|
||||
Связная часть приложения с одной причиной изменяться. Ответственность является самостоятельной, когда ей нужны собственный публичный API, зависимости, состояние или область жизни.
|
||||
|
||||
### Владелец
|
||||
|
||||
Модуль, который определяет публичный API ответственности, её зависимости, состояние, область жизни и внутреннюю реализацию. Место выполнения кода не переносит владение.
|
||||
|
||||
## Структурные сущности
|
||||
|
||||
### Слой
|
||||
|
||||
Архитектурная роль кода внутри SLM root. Слой классифицирует владельцев по назначению и ограничивает допустимые направления зависимостей. Нормативные роли и матрица определены в разделе [Слои](../architecture/layers.md).
|
||||
|
||||
### Группа
|
||||
|
||||
Необязательный навигационный классификатор модулей внутри одного слоя или другой группы. Группа не является владельцем, публичным API или границей зависимостей.
|
||||
|
||||
### Модуль
|
||||
|
||||
Минимальная самостоятельная архитектурная единица SLM. Модуль владеет одной связной ответственностью, имеет публичный API и физически размещается в отдельной папке.
|
||||
|
||||
### Сегмент
|
||||
|
||||
Необязательная внутренняя часть одного модуля, группирующая его содержимое по назначению. Сегмент не является владельцем, публичным API или границей зависимостей.
|
||||
|
||||
### Компонент
|
||||
|
||||
Сущность фреймворка, реализующая часть интерфейса родительского модуля. Зависимости, состояние и жизненный цикл компонента принадлежат этому модулю и сами по себе не создают нового владельца. Компонент может иметь внутренний `index.ts`, который не является публичным фасетом SLM.
|
||||
|
||||
### Вложенный модуль
|
||||
|
||||
Обычный модуль, физически размещённый внутри родительского модуля. Он сам владеет отдельной ответственностью и имеет публичный API и границу зависимостей, но остаётся внутренней реализацией родителя для внешнего кода.
|
||||
|
||||
## Публичная граница
|
||||
|
||||
### Публичный API
|
||||
|
||||
Единый логический контракт внешнего доступа к модулю. Он скрывает внутреннюю реализацию и физически представлен обязательным фасетом `index` и только необходимыми фасетами `client`, `browser` и `server`.
|
||||
|
||||
### Фасет
|
||||
|
||||
Объявленная публичная точка входа модуля, открывающая часть его единого API для определённой среды выполнения. Импорт фасета не является глубоким импортом; любой другой внешний путь внутрь модуля остаётся внутренним.
|
||||
|
||||
### Глубокий импорт
|
||||
|
||||
Импорт или реэкспорт внутреннего пути чужого модуля, который не объявлен его публичным фасетом.
|
||||
|
||||
## Зависимости
|
||||
|
||||
### Зависимость
|
||||
|
||||
Направленная статическая связь между архитектурными границами внутри одного SLM root. Обычный импорт, импорт типа (`import type`) и реэкспорт одинаково создают архитектурную зависимость.
|
||||
|
||||
Зависимость внутреннего файла, сегмента или компонента относится к ближайшему модулю-владельцу. Вложенный модуль начинает собственную границу зависимостей.
|
||||
|
||||
### Нормативная матрица слоёв
|
||||
|
||||
Отношение допустимой зависимости между слоями одного SLM root. Матрица определяет доступные целевые роли, но не требует проходить через каждый промежуточный слой.
|
||||
|
||||
## Жизненный цикл
|
||||
|
||||
### Область жизни
|
||||
|
||||
Период, в течение которого принадлежащие модулю состояние или долгоживущий ресурс должны оставаться активными.
|
||||
|
||||
### Ресурс жизненного цикла
|
||||
|
||||
Ресурс, работа которого продолжается после первоначального вызова и требует остановки, отмены, отписки или освобождения. Например, подписка, обработчик событий, таймер, наблюдатель, запрос или соединение.
|
||||
|
||||
### Очистка
|
||||
|
||||
Гарантированное прекращение работы ресурса не позже завершения его области жизни. Автоматическая очистка фреймворка считается очисткой владельца, если модуль устанавливает и контролирует соответствующую границу.
|
||||
|
||||
## Немодульные единицы
|
||||
|
||||
### Точка входа фреймворка
|
||||
|
||||
Специальная немодульная единица слоя `app`, которая запускает приложение, объявляет точку маршрута, преобразует внешние входные данные или подключает готовые публичные API.
|
||||
|
||||
### Ресурс shared
|
||||
|
||||
Небольшая детерминированная единица слоя `shared`, не зависящая от продукта и не скрывающая отдельного внутреннего устройства. У неё нет изменяемого состояния, ввода-вывода, области жизни или собственного публичного API.
|
||||
|
||||
Путь и имя сами по себе не определяют ни одну из перечисленных сущностей. Физическое сопоставление задаётся стайлгайдом или конфигурацией проверки после определения ответственности и владельца.
|
||||
98
docs/reference/validation.md
Normal file
98
docs/reference/validation.md
Normal file
@@ -0,0 +1,98 @@
|
||||
# Проверка архитектуры
|
||||
|
||||
Проверка SLM подтверждает две разные стороны решения:
|
||||
|
||||
- смысловая проверка устанавливает ответственность, владельца и корректность границ;
|
||||
- структурная проверка подтверждает, что решение правильно выражено путями, публичными фасетами и зависимостями.
|
||||
|
||||
Успешная сборка или корректно отображаемый интерфейс не доказывают архитектурную корректность.
|
||||
|
||||
## Карточка решения
|
||||
|
||||
Перед изменением структуры нужно ответить:
|
||||
|
||||
| Вопрос | Что зафиксировать |
|
||||
|---|---|
|
||||
| Ответственность | Какой результат или поведение изменяется как единое целое |
|
||||
| Владелец | Какой модуль определяет контракт и внутреннюю реализацию |
|
||||
| Слой | Какой архитектурной роли соответствует ответственность |
|
||||
| Потребители | Кому действительно нужен публичный API |
|
||||
| Зависимости | Какие другие владельцы и возможности необходимы |
|
||||
| Состояние | Кто определяет смысл и допустимые изменения данных |
|
||||
| Жизненный цикл | Кто создаёт ресурсы, какова их область жизни и очистка |
|
||||
| Физическая форма | Какими путями и фасетами представлено принятое решение |
|
||||
|
||||
Если ответственность или владелец не определены, проверка путей откладывается: одинаковая файловая структура может представлять разные архитектурные решения.
|
||||
|
||||
## Архитектурное ревью
|
||||
|
||||
На ревью проверяется смысл кода, который нельзя надёжно вывести из файловой системы:
|
||||
|
||||
- одна ли связная ответственность находится внутри модуля;
|
||||
- есть ли у каждой самостоятельной ответственности ровно один владелец;
|
||||
- соответствует ли ответственность роли выбранного слоя;
|
||||
- не стали ли группа, сегмент или компонент скрытыми владельцами;
|
||||
- нужен ли каждый экспорт реальному внешнему потребителю;
|
||||
- не раскрывает ли публичный API изменяемые внутренние механизмы;
|
||||
- определены ли владелец, область жизни, число экземпляров и очистка каждого ресурса;
|
||||
- не переносится ли владение из-за места вызова, провайдера фреймворка или точки маршрута.
|
||||
|
||||
Окончательные смысловые требования имеют класс `R` в [реестре правил](../rules/registry.md).
|
||||
|
||||
## Автоматическая проверка
|
||||
|
||||
Проект сопоставляет физические пути с SLM root, слоями, группами, модулями, вложенными модулями, сегментами, фасетами, точками входа `app` и ресурсами `shared`. Сопоставление задаётся локальной конфигурацией и не меняет смысл сущностей.
|
||||
|
||||
Наличие `index.ts` само по себе не объявляет модуль. Проверка отличает объявленные корни модулей и их публичные фасеты от локальных точек входа компонентов и других внутренних единиц.
|
||||
|
||||
Автоматически проверяются:
|
||||
|
||||
- допустимое направление импортов по матрице слоёв;
|
||||
- отдельная папка каждого модуля;
|
||||
- доступ к чужому модулю только через объявленные фасеты;
|
||||
- отсутствие циклов между модулями;
|
||||
- отсутствие прямого внешнего доступа к вложенным модулям;
|
||||
- допустимый транзитивный граф исполняемых импортов каждого фасета среды выполнения;
|
||||
- динамическое подключение `browser`-фасета с отключённым SSR.
|
||||
|
||||
Каждое правило класса `A` должно полностью блокировать проверку при нарушении. SLM не требует конкретного lint-инструмента.
|
||||
|
||||
## Проверка зависимостей
|
||||
|
||||
Для каждого внешнего импорта определяется:
|
||||
|
||||
1. Модуль-владелец исходного файла.
|
||||
2. Модуль-владелец целевого файла.
|
||||
3. Слои исходного и целевого владельцев.
|
||||
4. Публичный фасет, через который выполнен импорт.
|
||||
5. Отсутствие цикла после добавления связи.
|
||||
|
||||
Импорты типов (`import type`) и реэкспорты проверяются как архитектурные связи. Относительные импорты внутри одного модуля не пересекают модульную границу.
|
||||
|
||||
## Проверка фасетов
|
||||
|
||||
Совместимость фасета определяется всем достижимым исполняемым кодом, а не только его собственным файлом.
|
||||
|
||||
Проверка подтверждает:
|
||||
|
||||
- `index` не достигает `client`, `browser` или `server`;
|
||||
- `client` не достигает `browser` или `server`;
|
||||
- `browser` и `server` не достигают друг друга;
|
||||
- `browser` доступен только через поддерживаемую динамическую границу без SSR;
|
||||
- специализированный фасет существует ради реального потребителя;
|
||||
- один исполняемый экспорт не дублируется между фасетами.
|
||||
|
||||
Импорт типа остаётся архитектурной зависимостью, но не добавляет исполняемый код в среду фасета.
|
||||
|
||||
## Критерий завершения
|
||||
|
||||
Изменение соответствует SLM, когда одновременно выполнены условия:
|
||||
|
||||
- ответственность и единственный владелец определены;
|
||||
- роль слоя соответствует ответственности;
|
||||
- публичный API минимален и используется всеми внешними потребителями;
|
||||
- зависимости разрешены и не образуют циклов;
|
||||
- группа и сегменты не подменяют модульную границу;
|
||||
- состояние и ресурсы имеют владельца и корректную область жизни;
|
||||
- физическая структура однозначно выражает принятое решение;
|
||||
- применимые автоматические проверки и архитектурное ревью пройдены.
|
||||
Reference in New Issue
Block a user