mirror of
https://github.com/gromlab-ru/slm-design.git
synced 2026-08-22 15: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`, даже если сегодня используется одной композицией.
|