Слой выбирается после определения ответственности. Похожее имя папки или наличие зависимости от конкретной библиотеки не являются основанием для выбора слоя.
## Роли слоёв
SLM определяет шесть ролей:
| Слой | Роль |
|---|---|
| `app` | Связь приложения с фреймворком: запуск, маршруты, преобразование внешних входных данных и подключение готовых публичных API |
| `compositions` | Представление и связывание готовых публичных API в страницы, макеты, экраны, виджеты и другие продуктовые композиции |
| `domains` | Полная реализация предметных ответственностей и сценариев, включая их модели, правила, состояние, операции с продуктовыми данными и доменный UI |
| `infra` | Технические сервисы и возможности приложения без собственной предметной модели |
| `ui` | Универсальные интерфейсные модули без зависимости от конкретной продуктовой композиции |
| `shared` | Детерминированный фундамент без знания о продукте, изменяемого состояния и ввода-вывода |
Отсутствующая роль не требует пустой папки. Проект создаёт слой только тогда, когда в нём появляется соответствующая ответственность.
### App
`app` содержит точки связи с фреймворком: запуск, файлы маршрутов и преобразование внешних входных данных. Они подключают готовые публичные API других слоёв, но не присваивают их ответственность.
Точки входа `app` являются специальным немодульным исключением. Самостоятельная продуктовая ответственность, даже если она представлена страницей, макетом или Provider, реализуется в подходящем модуле и только подключается из `app`.
`compositions` содержит владельцев представления продуктовых композиций: страниц, макетов, экранов, виджетов, результатов маршрутов и интерфейса, объединяющего несколько готовых модульных возможностей. Композиция размещает и связывает публичные API доменных, инфраструктурных и UI-модулей, но не присваивает их ответственность.
Модуль композиции может владеть структурой страницы, расположением частей интерфейса и состоянием, смысл которого существует только внутри этой композиции. Он не определяет, не реализует, не расширяет и не замещает доменный сценарий. Количество потребителей и использование сценария только на одной странице не меняют эту границу.
Конкретная организация слоя определяется продуктом и фреймворком. Названия `pages`, `layouts`, `screens` и `widgets` могут использоваться как [группы](./groups.md), но не являются дополнительными слоями и не задают направление импортов.
`domains` содержит модули-владельцы полных предметных ответственностей и доменных сценариев. Доменный модуль владеет не только моделями и бизнес-правилами, но и продуктовым состоянием, смыслом операций с продуктовыми данными, предметными исходами, доменным UI и framework-механизмами, которые обслуживают сценарий.
Домен является вертикальным владельцем ответственности, а не только каталогом независимой от интерфейса бизнес-логики. Внутри него могут находиться компоненты, Providers, hooks, stores, services и другой код, если он реализует принадлежащий домену результат. Универсальные визуальные элементы домен получает из `ui`, а технические возможности без предметной модели — из `infra`.
Домен является специализированным SLM-модулем: он сохраняет обычную модульную форму и получает дополнительные требования к предметному контракту, адаптации источников и ошибкам. Полная модель описана в разделе [Домены](./domains.md).
`infra` содержит технические возможности приложения: аналитику, локализацию, тему, телеметрию, интеграции с платформой и другие сервисы без собственной предметной модели.
Технический способ выполнения предметного сценария не переносит владение сценарием из `domains` в `infra`.
### UI
`ui` содержит универсальные интерфейсные модули, которые не знают о конкретной странице, маршруте или продуктовой композиции.
### Shared
`shared` содержит детерминированный фундамент, не зависящий от продукта и не имеющий ввода-вывода, изменяемого состояния или жизненного цикла.
В`shared` могут находиться обычные модули и небольшие немодульные ресурсы: чистые функции, общие типы, стили, декларативная конфигурация и статические файлы.
Если для нового доменного сценария ещё нет подходящего владельца, сначала выбирается существующий или создаётся новый модуль в `domains`. Реализация сценария в `compositions`с намерением перенести её позже не является допустимым промежуточным архитектурным решением.
Композиция может показать рядом несколько доменных возможностей и вызвать их готовые публичные операции. Если координация определяет продуктовый порядок действий, условия, общий предметный результат, политику ошибок или компенсацию между доменами, такая координация сама является доменным сценарием и требует владельца в `domains`.
Разрешённая зависимость `compositions` от `infra` сохраняется. Композиция может использовать тему, локализацию, доставку метрик и другие технические возможности для собственной ответственности. Эта связь не разрешает получать или изменять продуктовые данные через HTTP-клиент, SDK или storage непосредственно из композиции: техническим механизмом владеет `infra`, а смысл такой операции и её продуктовый результат принадлежат домену.
Смысл события метрики принадлежит владельцу наблюдаемого поведения. Домен определяет событие доменного сценария, композиция — событие показа или взаимодействия со своей раскладкой, `app` — событие запуска или маршрутизации, а`infra` отвечает за техническую доставку телеметрии.
Слой ограничивает только межслойное направление. Модули одного слоя могут зависеть друг от друга через публичные API, если общий граф остаётся ацикличным.
Модули могут находиться непосредственно в слое или объединяться в необязательные навигационные [группы](./groups.md). Группа не владеет кодом и не влияет на допустимость зависимостей.
Внутри SLM root код по умолчанию принадлежит модулю. Исключения ограничены двумя случаями:
- точка входа `app` непосредственно связывает приложение с фреймворком;
-ресурс`shared` является небольшой самостоятельной детерминированной единицей без внутренней границы.
Если ресурсу`shared` нужны несколько файлов реализации, собственные архитектурные зависимости, изменяемое состояние, ввод-вывод или жизненный цикл, ему требуется модуль-владелец.