mirror of
https://github.com/gromlab-ru/slm-design.git
synced 2026-08-22 07:30:16 +03:00
207 lines
9.0 KiB
Markdown
207 lines
9.0 KiB
Markdown
# Domain
|
||
|
||
> Рабочая заметка. Не является нормативным разделом спецификации.
|
||
|
||
## Определение
|
||
|
||
### DOM-N003: Domain является границей владения предметной областью
|
||
|
||
Domain группирует business-контракт, concrete integrations, готовые presets и framework-specific bindings одной предметной области.
|
||
|
||
Примеры Domain:
|
||
|
||
- `auth`;
|
||
- `user`;
|
||
- `catalog`;
|
||
- `orders`;
|
||
- `checkout`.
|
||
|
||
Domain не является одним большим module. Он является границей, внутри которой могут находиться modules и logical groups с заданным направлением зависимостей.
|
||
|
||
```text
|
||
Domain
|
||
├── business module
|
||
├── presets group
|
||
│ └── preset modules
|
||
├── framework binding module или group
|
||
└── optional reusable adapters group
|
||
└── adapter modules
|
||
```
|
||
|
||
## Предварительная структура
|
||
|
||
```text
|
||
domains/auth/
|
||
├── business/
|
||
│ ├── auth.factory.ts
|
||
│ ├── errors/
|
||
│ ├── lib/
|
||
│ ├── services/
|
||
│ ├── tests/
|
||
│ ├── types/
|
||
│ └── index.ts
|
||
├── presets/
|
||
│ └── {preset-name}/
|
||
│ ├── adapters/
|
||
│ ├── create-auth.ts
|
||
│ ├── create-auth.test.ts
|
||
│ └── index.ts
|
||
└── {framework-binding}/
|
||
├── hooks/
|
||
├── providers/
|
||
├── tests/
|
||
├── ui/
|
||
└── index.ts
|
||
```
|
||
|
||
`{preset-name}` и `{framework-binding}` являются placeholders, а не обязательными именами папок. Preset называется по своему scope или назначению. Framework binding может быть оформлен как `react`, `bindings/react`, `framework/react` или по другому локальному соглашению.
|
||
|
||
Environment-specific preset, включая server-only вариант, может быть добавлен отдельным preset module. SLM не требует заранее делить `presets` или `adapters` на `browser`, `server` и другие технические категории.
|
||
|
||
## Возможные ветки Domain
|
||
|
||
### DOM-N007: Domain не имеет фиксированного набора верхних папок
|
||
|
||
| Роль | Типичная форма | Статус |
|
||
|---|---|---|
|
||
| Business | Один business module | Основная гипотеза Domain |
|
||
| Presets | Logical group с preset modules | По наличию повторяемых assemblies |
|
||
| Framework bindings | Module или logical group | По наличию framework integration |
|
||
| Reusable adapters | Logical group с adapter modules | Только после promotion из владельца |
|
||
| Tests | Segment конкретного module | Не создаётся в корне Domain |
|
||
|
||
`model`, `types`, `errors`, `lib`, `ui`, `client` и `server` не становятся верхними Domain-разделами автоматически. Они размещаются внутри module-владельца либо появляются как локальное соглашение с отдельным обоснованием.
|
||
|
||
## Иерархия сущностей
|
||
|
||
### DOM-N004: Роль и структурный вид являются независимыми характеристиками
|
||
|
||
Архитектурная роль отвечает на вопрос «какую ответственность выполняет код»:
|
||
|
||
- business;
|
||
- preset;
|
||
- framework binding;
|
||
- adapter.
|
||
|
||
Структурный вид отвечает на вопрос «как оформлена граница кода»:
|
||
|
||
- Domain;
|
||
- module;
|
||
- group;
|
||
- segment;
|
||
- file.
|
||
|
||
```text
|
||
Domain
|
||
├── Module
|
||
│ ├── Segment
|
||
│ │ └── File
|
||
│ └── File
|
||
└── Group
|
||
├── Module
|
||
└── Group
|
||
└── Module
|
||
```
|
||
|
||
Правила структурных видов:
|
||
|
||
- Module владеет самостоятельной ответственностью и public API.
|
||
- Group является logical directory для навигации, не имеет `index.ts`, runtime и собственных файлов реализации.
|
||
- Segment существует внутри module, группирует его файлы по назначению и не имеет отдельного внешнего API.
|
||
- Имя папки само по себе не доказывает её структурный вид.
|
||
|
||
Пример классификации:
|
||
|
||
| Путь | Роль | Структурный вид |
|
||
|---|---|---|
|
||
| `domains/auth` | Предметная область Auth | Domain |
|
||
| `domains/auth/business` | Business | Module |
|
||
| `domains/auth/business/services` | Business scenarios | Segment |
|
||
| `domains/auth/business/tests` | Business tests | Segment |
|
||
| `domains/auth/presets` | Навигация presets | Group |
|
||
| `domains/auth/presets/{preset-name}` | Preset | Module |
|
||
| `domains/auth/presets/{preset-name}/adapters` | Private adapters preset | Segment |
|
||
| `domains/auth/{framework-binding}` | Framework binding | Module или Group по фактической границе |
|
||
| `domains/auth/adapters` | Навигация promoted adapters | Optional group |
|
||
| `domains/auth/adapters/{adapter-name}` | Reusable adapter | Module |
|
||
|
||
## Публичные границы
|
||
|
||
### DOM-N005: Domain предоставляет отдельные public submodules
|
||
|
||
Предварительно Domain не имеет обязательного общего facade. Каждый public module предоставляет собственный entrypoint:
|
||
|
||
```ts
|
||
import { authFactory, validateAuthPhone } from '@/domains/auth/business'
|
||
import { createApplicationAuth } from '@/domains/auth/presets/application'
|
||
import { AuthProvider, useAuth } from '@/domains/auth/react'
|
||
```
|
||
|
||
`application` и `react` здесь являются только примерами пользовательских имён. Отдельные entrypoints не смешивают business, concrete assembly и framework code в одном import graph.
|
||
|
||
Возможные public entrypoints:
|
||
|
||
```text
|
||
@/domains/auth/business
|
||
@/domains/auth/presets/{preset-name}
|
||
@/domains/auth/{framework-binding}
|
||
@/domains/auth/adapters/{adapter-name} # только для promoted adapter module
|
||
```
|
||
|
||
Private adapters внутри preset не получают собственного внешнего entrypoint.
|
||
|
||
### DOM-N006: Omnibus barrel для всего Domain опасен
|
||
|
||
Такой entrypoint может связать изоморфный, client-only и server-only graphs:
|
||
|
||
```ts
|
||
// Не использовать как default-подход.
|
||
export * from './business'
|
||
export * from './presets/application'
|
||
export * from './react'
|
||
```
|
||
|
||
Tree shaking не считается security boundary. Server-only submodule не должен быть достижим из изоморфного или client entrypoint даже через re-export.
|
||
|
||
## Предварительное направление зависимостей
|
||
|
||
```text
|
||
business
|
||
↑
|
||
preset + private adapters
|
||
|
||
готовый business API instance
|
||
↑
|
||
framework bindings / compositions
|
||
```
|
||
|
||
Более точная схема импортов:
|
||
|
||
```text
|
||
business -/→ adapters | presets | framework | infra concrete runtime
|
||
preset-private adapters → business contracts + concrete runtime
|
||
promoted adapter module → business contracts + concrete runtime
|
||
presets → business factory + private or promoted adapters
|
||
framework → business contracts + ready API or preset
|
||
compositions → ready business API + framework bindings
|
||
```
|
||
|
||
Framework module может одновременно быть assembly site, если он явно владеет lifecycle API instance. Наличие папки `presets/` не даёт ей монополию на вызов factory.
|
||
|
||
## Domain и compositions
|
||
|
||
Domain владеет повторяемой доменной ответственностью. Composition по-прежнему владеет страницей, route tree, экраном и конкретным пользовательским outcome.
|
||
|
||
Предварительная граница:
|
||
|
||
| Ответственность | Владелец |
|
||
|---|---|
|
||
| Auth scenarios и contracts | `domains/auth/business` |
|
||
| Private auth adapters одной assembly | Segment внутри соответствующего preset module |
|
||
| Reusable auth adapter | Optional adapter module после promotion |
|
||
| Повторяемая сборка AuthApi | Конкретный preset module или другой assembly site |
|
||
| Auth React provider/access hook | Выбранный framework binding module |
|
||
| Текст ошибки, redirect, экран и route outcome | Consumer composition |
|
||
|
||
Граница domain-specific UI пока остаётся открытым вопросом.
|