Files
slm-design/DRAFT/architecture/terminology.md
S. Gromov 691069af8e sync
2026-08-10 09:12:22 +03:00

13 KiB
Raw Blame History

Терминология SLM

Нормативные определения рабочего черновика. Этот раздел не объявляет правила.

Определения задают обязательный смысл архитектурных терминов и используются при толковании всех правил. Код получают только блокирующие требования, а не сами определения.

Базовые понятия

SLM root

Граница структурной архитектуры одного приложения. Внутри неё определяются слои, модули и зависимости SLM. Монорепозиторий, пакеты и отношения между несколькими SLM root находятся за пределами текущего черновика.

Ответственность

Связная часть приложения с одной причиной изменяться. Ответственность является самостоятельной, когда ей нужны собственные публичный API, зависимости, состояние или область жизни.

Владелец

Модуль, который определяет публичный API ответственности, её зависимости, состояние, область жизни и внутреннее устройство. Место выполнения кода не переносит владение.

Публичный API

Единая логическая граница внешнего доступа к модулю. Публичный API скрывает внутреннее устройство и состоит из обязательного корневого фасета index и только реально необходимых environment-фасетов client, browser и server.

Фасет

Объявленная публичная точка входа модуля, которая открывает часть его единого логического API для определённой среды или способа выполнения. Импорт объявленного фасета не является deep import. Любой другой путь внутрь модуля остаётся внутренним.

Корневой фасет index является основным barrel модуля. Он экспортирует публичные типы и runtime-код, совместимый как с серверным рендерингом, включая React Server Components, так и с клиентским выполнением.

Необязательные environment-фасеты имеют следующий нормативный смысл:

Фасет Среда и способ выполнения
client Клиентская framework-граница, которая может участвовать в server prerender и затем выполняться при hydration и в браузере
browser Browser-only код, подключаемый только динамически с отключённым SSR
server Server-only код, недоступный через универсальный, клиентский и браузерный фасеты

Client Component, импортированный Server Component, не становится универсальным кодом и не экспортируется через index. Совместимость фасета со средой определяется всеми его runtime-импортами и реэкспортами, включая транзитивные.

Зависимость

Статическая связь внутри одного SLM root, которую импорт или реэкспорт создаёт между архитектурными границами. Обычный импорт, импорт типа и реэкспорт одинаково создают архитектурную зависимость.

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

Область жизни

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

Ресурс жизненного цикла

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

Очистка

Гарантированное прекращение работы ресурса не позже завершения его области жизни. Автоматическая очистка фреймворка считается очисткой владельца, если модуль устанавливает и контролирует соответствующую границу.

Структурные сущности

Нормативная матрица слоёв

Отношение допустимой зависимости между слоями одного SLM root. Матрица определяет, код каких слоёв может импортировать исходный слой; она не обязана образовывать линейный порядок.

Для SLM нормативно отношение app → compositions → domains → infra → ui → shared. infra может импортировать ui, а ui не импортирует infra. Промежуточный слой не является обязательным посредником.

Слой

Одна из шести верхнеуровневых ролей внутри SLM root:

Слой Роль
app Связь приложения с фреймворком: запуск, маршруты и преобразование входных данных
compositions Сборка продуктового интерфейса: страницы, макеты, экраны, виджеты и другие композиции
domains Предметные области, их модели, правила, сценарии и продуктовое состояние
infra Технические сервисы и возможности приложения
ui Универсальные модули интерфейса без зависимости от конкретной продуктовой композиции
shared Независимый детерминированный фундамент без знания о продукте, изменяемого состояния и ввода-вывода

Полная матрица допустимых зависимостей:

Исходный слой Допустимые целевые слои
app app, compositions, domains, infra, ui, shared
compositions compositions, domains, infra, ui, shared
domains domains, infra, ui, shared
infra infra, ui, shared
ui ui, shared
shared shared

Модуль

Минимальная самостоятельная архитектурная единица SLM. Модуль владеет одной связной ответственностью, размещается в отдельной папке и предоставляет публичный API.

Предметная ответственность

Связная предметная область приложения, которая может включать собственные модели, правила, сценарии и продуктовое состояние. Количество экранов, endpoint-ов, hooks или файлов само по себе не определяет её границу.

Группа

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

Сегмент

Внутренняя часть одного модуля, которая группирует его содержимое по назначению. Сегмент не является самостоятельным владельцем, публичным API или границей зависимостей.

Компонент

Сущность фреймворка, которая реализует часть интерфейса родительского модуля. Компонент не образует собственного владельца, публичного API или границы зависимостей.

Импорты, состояние, доступ к данным и код жизненного цикла компонента принадлежат родительскому модулю. Их наличие само по себе не создаёт новый модуль; решающим признаком является самостоятельная ответственность.

Вложенный модуль

Обычный модуль, размещённый внутри границы родительского модуля. Он имеет собственные ответственность, публичный API и границу зависимостей и подчиняется всем общим правилам модулей.

Публичный API вложенного модуля доступен коду родительской границы. Для кода за пределами родительского модуля вложенный модуль остаётся внутренней реализацией родителя.

Точка входа фреймворка

Специальная немодульная единица слоя app, которая непосредственно связывает приложение с фреймворком. Её импорты участвуют в проверке направления слоёв, но сама точка входа не является модулем.

Ресурс shared

Специальная немодульная единица слоя shared: небольшая детерминированная утилита, общий тип, стиль, конфигурация или статический ресурс без продуктового знания, изменяемого состояния, ввода-вывода, области жизни и собственного публичного API.

Ресурс shared может импортироваться напрямую по пути, установленному стайлгайдом, и не является модулем. Доступный по этому пути файл является всей единицей и не скрывает отдельное внутреннее устройство.

Если ресурсу нужны самостоятельная ответственность, собственные архитектурные зависимости, несколько файлов реализации, изменяемое состояние, ввод-вывод или область жизни, он оформляется как модуль.

Структурная модель

SLM root
├── app
│   └── точка входа фреймворка
├── compositions | domains | infra | ui
│   ├── группа
│   │   └── модуль
│   └── модуль
│       ├── корневые файлы
│       ├── сегмент
│       │   ├── файлы
│       │   ├── компоненты
│       │   └── вложенные модули
│       └── вложенный модуль
└── shared
    ├── группа
    ├── модуль
    └── ресурс shared

Путь и имя папки сами по себе не определяют сущность. Её определяют ответственность, владелец и публичная граница. Физическое сопоставление путей с сущностями задаётся стайлгайдом или конфигурацией проверки проекта.