feat: level-2 документация

This commit is contained in:
2026-07-30 10:56:48 +03:00
parent 4aa5547d20
commit bd479b346f
22 changed files with 516 additions and 77 deletions

49
DRAFT/level-2/README.md Normal file
View File

@@ -0,0 +1,49 @@
# SLM Level 2
> Статус: рабочий черновик. Документы в этой папке не являются спецификацией.
Level 2 расширяет архитектурную базу Level 1 слоем `domains`. Он предназначен для проектов, в которых появились самостоятельные предметные области, но ещё не требуется строгая runtime-архитектура доменов.
## Наследование Level 1
Проект Level 2 соблюдает все определения и правила Level 1, если терминология Level 2 не задаёт расширение для нового слоя. Модуль, Group, сегмент, компонент, вложенный модуль, публичный API, граф зависимостей и владение жизненным циклом сохраняют смысл Level 1.
Канонический набор требований образуют два реестра:
- [правила Level 1](../rules/level-1.md);
- [дополнительные правила Level 2](../rules/level-2.md).
## Место в уровнях SLM
| Уровень | Назначение |
|---|---|
| Level 1 | Слои, зависимости, структурные сущности и жизненный цикл ресурсов |
| Level 2 | Доменный слой и доменные модули без строгой внутренней формы |
| Level 3 | Строгая внутренняя архитектура и runtime-границы доменов |
## Основная идея
Домен Level 2 является обычным SLM-модулем слоя `domains`. Он владеет одной связной предметной областью и может содержать всю необходимую ей реализацию, сегменты, компоненты и вложенные модули.
По умолчанию доменные модули размещаются непосредственно в слое. При большом количестве доменов слой также может содержать обычные навигационные Groups Level 1.
```text
src/domains/
├── auth/ # Доменный модуль
├── catalog/ # Доменный модуль
└── orders/ # Доменный модуль
```
## Область Level 2
Level 2 описывает роль слоя `domains`, границу доменного модуля, опциональную группировку и зависимости с участием нового слоя.
Level 2 не задаёт обязательные внутренние роли, каталоги или способ сборки доменного модуля. Строгая внутренняя архитектура относится к Level 3.
## Карта черновика
- [Терминология](./terminology.md)
- [Слои](./layers.md)
- [Домены](./domains.md)
- [Зависимости](./dependencies.md)
- [Проверка](./validation.md)

View File

@@ -0,0 +1,50 @@
# Зависимости Level 2
> Расширение графа зависимостей Level 1 слоем `domains`.
Level 2 не вводит отдельный вид зависимости. Доменные модули являются обычными узлами графа модулей, а Groups не участвуют в графе.
## Направление
Модуль слоя `domains` может импортировать:
- публичные API других доменных модулей;
- публичные API модулей `infra`, `ui` и `shared`;
- нормативные ресурсы `shared`.
`infra`, `ui` и `shared` не импортируют `domains`. `compositions` и `app` могут использовать публичные API доменных модулей как код нижнего слоя.
## Междоменные зависимости
Импорт между доменными модулями разрешён независимо от их Group:
```ts
// domains/orders
import type { Product } from '@/domains/catalog'
```
Он создаёт обычное ребро графа модулей:
```text
orders → catalog
```
Обратная runtime- или type-only зависимость, создающая цикл, запрещена общим правилом Level 1.
## Groups и зависимости
Путь опциональной Group участвует в адресе модуля, но сама Group не является импортируемой сущностью. Размещение в разных Groups не запрещает импорт и не задаёт его направление.
Если двум бизнес-приложениям нужна гарантированная архитектурная изоляция, одной Group недостаточно: такая граница требует отдельных SLM roots или правил более высокого проектного уровня.
## Вложенные модули
Вложенный модуль домена остаётся внутренним для родительской границы. Другой домен не импортирует его напрямую и получает необходимые экспорты через API корневого доменного модуля.
## Связанные правила
- [`SLM-L1-LAYER-A002`](../rules/level-1.md#slm-l1-layer-a002)
- [`SLM-L1-MODULE-A004`](../rules/level-1.md#slm-l1-module-a004)
- [`SLM-L1-DEPENDENCY-A005`](../rules/level-1.md#slm-l1-dependency-a005)
- [`SLM-L1-GROUP-R007`](../rules/level-1.md#slm-l1-group-r007)
- [`SLM-L1-NESTED_MODULE-A010`](../rules/level-1.md#slm-l1-nested_module-a010)

117
DRAFT/level-2/domains.md Normal file
View File

@@ -0,0 +1,117 @@
# Домены Level 2
> Пояснение модели доменных модулей без строгой внутренней архитектуры Level 3.
Домен Level 2 является обычным SLM-модулем. Новый уровень добавляет доменную роль и место в порядке слоёв, но не вводит отдельную структурную сущность поверх модуля.
## Связанные правила
- [`SLM-L2-DOMAIN-R001`](../rules/level-2.md#slm-l2-domain-r001)
- [`SLM-L1-MODULE-A004`](../rules/level-1.md#slm-l1-module-a004)
- [`SLM-L1-MODULE-A014`](../rules/level-1.md#slm-l1-module-a014)
- [`SLM-L1-MODULE-R006`](../rules/level-1.md#slm-l1-module-r006)
- [`SLM-L1-MODULE-R011`](../rules/level-1.md#slm-l1-module-r011)
- [`SLM-L1-MODULE-R012`](../rules/level-1.md#slm-l1-module-r012)
- [`SLM-L1-GROUP-R007`](../rules/level-1.md#slm-l1-group-r007)
- [`SLM-L1-NESTED_MODULE-A010`](../rules/level-1.md#slm-l1-nested_module-a010)
- [`SLM-L1-LIFECYCLE-R013`](../rules/level-1.md#slm-l1-lifecycle-r013)
## Один домен, один модуль
Связная предметная область получает один корневой доменный модуль. Вся логика авторизации может находиться внутри `auth` без обязательного выделения `session`, `phone-login` или каждого сценария в соседний доменный модуль.
```text
domains/auth/
├── hooks/
├── services/
│ ├── session.service.ts
│ └── phone-login.service.ts
├── stores/
├── types/
├── ui/
└── index.ts
```
Названия и набор сегментов определяет стайлгайд проекта. Level 2 не требует показанный каркас.
## Внутренняя свобода
Доменный модуль может содержать всё, что нужно его ответственности:
- доменные типы, модели, правила и сценарии;
- продуктовое состояние и управление его жизненным циклом;
- framework hooks и domain-specific компоненты;
- вызовы переданных или импортированных технических сервисов;
- локальные adapters, mappers и интеграционный код;
- сегменты и вложенные модули.
Если техническая реализация становится самостоятельным сервисом без доменной семантики, она переносится в `infra` по общим правилам назначения слоёв.
## Когда нужен вложенный модуль
Часть домена становится вложенным модулем только при появлении самостоятельной ответственности, публичного API внутри родительской границы, собственных зависимостей или области жизни.
```text
domains/auth/
├── parts/
│ ├── auth-form/
│ │ ├── auth-form.tsx
│ │ └── index.ts
│ └── registration-form/
│ ├── registration-form.tsx
│ └── index.ts
├── auth.ts
└── index.ts
```
Внешний код по-прежнему получает `auth-form` и `registration-form` только через публичный API `auth`. Само наличие нескольких файлов или отдельного пользовательского сценария не требует вложенного модуля.
## Опциональная группировка
Если количество доменов затрудняет навигацию, Groups внутри `domains` могут классифицировать их по принадлежности к разным бизнес-приложениям или продуктовым областям.
```text
domains/
├── shop/ # Group
│ ├── auth/ # Доменный модуль Shop Auth
│ ├── catalog/ # Доменный модуль
│ └── orders/ # Доменный модуль
└── cabinet/ # Group
├── auth/ # Отдельный доменный модуль Cabinet Auth
├── profile/ # Доменный модуль
└── documents/ # Доменный модуль
```
`shop` и `cabinet` не имеют `index.ts`, состояния, реализации или публичного API. Они могут содержать только доменные модули и другие Groups.
Одинаковое имя модуля в разных Groups допустимо, если это разные владельцы и разные предметные области. Если авторизация действительно общая, ей нужен один общий модуль-владелец, а не две копии.
Group не создаёт dependency boundary. Импорт между модулями разных Groups проверяется так же, как любой импорт внутри слоя `domains`.
## Публичный API
Внешний код использует домен через обычный публичный API модуля:
```ts
import { signOut, useSession } from '@/domains/auth'
```
Deep import остаётся нарушением:
```ts
import { useSession } from '@/domains/auth/hooks/use-session'
```
Group не предоставляет агрегирующий API и не реэкспортирует содержащиеся в ней домены.
## Граница с другими слоями
| Ответственность | Владелец |
|---|---|
| Доменная модель, правило, сценарий или продуктовое состояние | Доменный модуль |
| Страница, маршрут, экран и конкретный visual outcome | Модуль `compositions` |
| Самостоятельный технический сервис без предметной модели | Модуль `infra` |
| Универсальный интерфейс без продуктовой семантики | Модуль `ui` |
| Независимая детерминированная утилита | `shared` или локальный владелец |
Число потребителей не является единственным критерием. Самостоятельная доменная ответственность может принадлежать `domains`, даже если сегодня используется одной композицией.

74
DRAFT/level-2/layers.md Normal file
View File

@@ -0,0 +1,74 @@
# Слои Level 2
> Пояснение нормативной модели слоёв Level 2.
Level 2 добавляет `domains` между продуктовой композицией и техническими сервисами приложения.
## Базовая структура
```text
src/
├── app/
├── compositions/
├── domains/
├── infra/
├── ui/
└── shared/
```
Отсутствующая роль не требует пустой папки. Проект без самостоятельной доменной ответственности может оставаться на Level 1.
## Роли слоёв
| Слой | Роль |
|---|---|
| `app` | Запуск, маршруты, преобразование входных данных и подключение готовых публичных API |
| `compositions` | Страницы, макеты, экраны, виджеты и конкретные продуктовые композиции |
| `domains` | Предметные области, их модели, правила, сценарии и продуктовое состояние |
| `infra` | Технические сервисы и возможности приложения без самостоятельной предметной модели |
| `ui` | Универсальные модули интерфейса без зависимости от конкретной продуктовой композиции |
| `shared` | Независимый детерминированный фундамент без знания о продукте, состояния и ввода-вывода |
## Порядок слоёв
```text
app
compositions
domains
infra
ui
shared
```
Код слоя может импортировать модули своего или любого нижнего слоя. Промежуточные слои можно пропускать.
| Слой | Может импортировать другие слои |
|---|---|
| `app` | `compositions`, `domains`, `infra`, `ui`, `shared` |
| `compositions` | `domains`, `infra`, `ui`, `shared` |
| `domains` | `infra`, `ui`, `shared` |
| `infra` | `ui`, `shared` |
| `ui` | `shared` |
| `shared` | Нет |
Импорты между модулями одного слоя разрешены. Поэтому один доменный модуль может зависеть от публичного API другого доменного модуля, если общий граф остаётся ацикличным.
## Границы ролей
`compositions` определяет устройство конкретной страницы, маршрута или визуального результата. `domains` определяет повторяемую предметную семантику, которая не принадлежит одной композиции.
`infra` предоставляет техническую возможность. Если код определяет продуктовую модель, правило или сценарий поверх этой возможности, владельцем такого кода является доменный модуль.
Разрешённый импорт не переносит владение. Доменный модуль может использовать `infra` и `ui`, но технический сервис и универсальный интерфейс сохраняют собственных владельцев.
## Связанные правила
- [`SLM-L1-LAYER-R001`](../rules/level-1.md#slm-l1-layer-r001)
- [`SLM-L1-LAYER-A002`](../rules/level-1.md#slm-l1-layer-a002)
- [`SLM-L1-LAYER-R003`](../rules/level-1.md#slm-l1-layer-r003)
- [`SLM-L2-DOMAIN-R001`](../rules/level-2.md#slm-l2-domain-r001)

View File

@@ -0,0 +1,54 @@
# Терминология Level 2
> Нормативные определения рабочего черновика. Этот раздел не объявляет правила.
Level 2 наследует терминологию Level 1 и добавляет определения, необходимые слою `domains`. Структурные сущности Level 1 не меняют смысл.
## Нормативный порядок слоёв
Для Level 2 нормативным является полный порядок:
```text
app → compositions → domains → infra → ui → shared
```
Нижним считается любой слой справа от исходного. Промежуточный слой не является обязательным посредником.
## Слой `domains`
Слой предметных областей приложения. Он содержит доменные модули и Groups, которые классифицируют эти модули.
Код слоя выражает продуктовые понятия, правила, сценарии или продуктовое состояние, которые не принадлежат устройству одной конкретной страницы, маршрута или визуальной композиции.
## Доменная ответственность
Связная предметная область приложения, которая может включать собственные модели, правила, сценарии и продуктовое состояние. Наличие каждого из этих элементов не является обязательным.
Количество экранов, endpoint-ов, хуков или файлов само по себе не определяет границу доменной ответственности.
## Доменный модуль
Обычный SLM-модуль слоя `domains`, представляющий одну доменную ответственность. Его ближайшей внешней структурной границей является слой `domains` или Group этого слоя, а не другой модуль.
Доменный модуль подчиняется всем правилам модулей Level 1: имеет отдельную папку, одного владельца, единый публичный API, собственный узел графа зависимостей и определённый жизненный цикл ресурсов.
Доменный модуль может содержать корневые файлы, сегменты, компоненты и вложенные модули. Вложенный модуль внутри него остаётся обычным вложенным модулем и не становится самостоятельным доменным модулем.
## Group слоя `domains`
Обычная Group Level 1, которая классифицирует доменные модули по принадлежности к бизнес-приложению, продуктовой области или другому понятному проекту признаку.
Такая Group не является доменом, владельцем ответственности или узлом графа зависимостей. Она не задаёт отдельного направления импортов и не изолирует содержащиеся в ней модули от других Groups.
## Структурная модель
```text
SLM root
└── domains
├── доменный модуль
│ ├── сегменты
│ └── вложенные модули
└── доменный модуль
```
Путь помогает определить структурную границу, но не доказывает корректность предметной декомпозиции. Решение о том, является ли ответственность самостоятельным доменом, требует понимания продукта.

View File

@@ -0,0 +1,48 @@
# Проверка Level 2
> Проверка расширенной модели слоёв и доменных границ.
Проект Level 2 выполняет все автоматические проверки и архитектурное ревью Level 1, используя нормативный порядок из шести слоёв.
## Сопоставление структуры
Конфигурация проверки проекта дополнительно определяет:
- физический путь слоя `domains`;
- доменные модули непосредственно в слое и внутри Groups;
- Groups слоя `domains`;
- вложенные модули внутри доменных модулей.
Сопоставление путей не определяет предметный смысл. Оно позволяет проверить направление импортов, публичные API, циклы и доступ к вложенным модулям.
## Автоматическая проверка
Новых автоматических правил Level 2 не требуется. Структурные инварианты обеспечивают правила Level 1:
- порядок `app → compositions → domains → infra → ui → shared`;
- импорт модулей только через публичные API;
- отсутствие циклов в графе модулей;
- отсутствие прямого доступа к вложенным модулям извне родителя;
- отсутствие реализации и API у Groups.
## Архитектурное ревью
Дополнительное правило Level 2 проверяется на ревью. Нужно определить:
- представляет ли доменный модуль одну связную предметную область;
- не разделена ли одна область на соседние доменные модули без самостоятельных владельцев;
- не объединены ли в одном модуле несвязанные предметные области;
- принадлежат ли модели, правила, сценарии и продуктовое состояние правильному домену;
- остаётся ли Group только навигационной классификацией;
- не размещены ли page-specific composition или самостоятельный технический сервис в `domains`.
## Связанные правила
- [`SLM-L2-DOMAIN-R001`](../rules/level-2.md#slm-l2-domain-r001)
- [`SLM-L1-LAYER-R001`](../rules/level-1.md#slm-l1-layer-r001)
- [`SLM-L1-LAYER-A002`](../rules/level-1.md#slm-l1-layer-a002)
- [`SLM-L1-MODULE-R006`](../rules/level-1.md#slm-l1-module-r006)
- [`SLM-L1-MODULE-R011`](../rules/level-1.md#slm-l1-module-r011)
- [`SLM-L1-GROUP-R007`](../rules/level-1.md#slm-l1-group-r007)
Скрипт `draft-rules.js` проверяет целостность реестров и ссылок документации, но не определяет предметные границы приложения.