mirror of
https://github.com/gromlab-ru/slm-design.git
synced 2026-08-22 07:30:16 +03:00
118 lines
7.0 KiB
Markdown
118 lines
7.0 KiB
Markdown
# Домены 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`, даже если сегодня используется одной композицией.
|