mirror of
https://github.com/gromlab-ru/slm-design.git
synced 2026-08-22 07:30:16 +03:00
feat: переработать уровни SLM
This commit is contained in:
@@ -2,25 +2,24 @@
|
||||
|
||||
> Статус: рабочий черновик. Документы в этой папке не являются спецификацией.
|
||||
|
||||
Level 1 задаёт основу SLM для лёгких проектов, которым нужна понятная организация без отдельной доменной архитектуры.
|
||||
Level 1 задаёт полную структурную основу SLM: слои, модули, доменные модули, публичные границы, граф зависимостей и владение жизненным циклом.
|
||||
|
||||
## Место в уровнях SLM
|
||||
|
||||
| Уровень | Назначение |
|
||||
|---|---|
|
||||
| Level 1 | Слои, зависимости, структурные сущности и жизненный цикл ресурсов |
|
||||
| Level 2 | Слой `domains` и доменные модули без строгой внутренней формы |
|
||||
| Level 3 | Строгие роли и границы сред выполнения внутри доменов |
|
||||
| Level 1 | Слои, доменные модули, зависимости, структурные сущности и жизненный цикл ресурсов |
|
||||
| Level 2 | Доменные пакеты, единый `DomainApi`, сборки и явные границы сред выполнения |
|
||||
|
||||
Повышение уровня может требовать рефакторинга, но базовые понятия Level 1 сохраняются.
|
||||
|
||||
## Область Level 1
|
||||
|
||||
Level 1 описывает слои, модули, группы, сегменты, компоненты, публичный API, граф зависимостей и владение жизненным циклом ресурсов.
|
||||
Level 1 описывает слои, доменные модули, группы, сегменты, компоненты, публичный API, граф зависимостей и владение жизненным циклом ресурсов.
|
||||
|
||||
Level 1 не описывает домены, фабрики, порты, адаптеры, обязательный поток данных, монорепозитории, соглашения об именовании и файловый стайлгайд.
|
||||
Level 1 не задаёт обязательную внутреннюю форму доменного модуля, фабрики, порты, адаптеры, presets, обязательный поток данных, монорепозитории, соглашения об именовании и файловый стайлгайд.
|
||||
|
||||
Появление самостоятельной доменной логики является сигналом рассмотреть [Level 2](../level-2/).
|
||||
Появление нескольких сред выполнения, устойчивого `DomainApi` или необходимости разделить бизнес-логику и технические сборки является сигналом рассмотреть [Level 2](../level-2/).
|
||||
|
||||
## Виды утверждений
|
||||
|
||||
@@ -35,7 +34,7 @@ Level 1 не описывает домены, фабрики, порты, ада
|
||||
|
||||
## Основная идея
|
||||
|
||||
Модуль является основной архитектурной единицей SLM. Слой задаёт роль и направление зависимостей. Группа помогает навигации, сегмент организует внутреннее содержимое, а компонент всегда принадлежит модулю.
|
||||
Модуль является основной архитектурной единицей SLM. Слой задаёт роль и направление зависимостей. Доменный модуль представляет одну предметную область. Группа помогает навигации, сегмент организует внутреннее содержимое, а компонент всегда принадлежит модулю.
|
||||
|
||||
Level 1 требует отдельную папку и единый публичный API модуля. Имена этих элементов, внутренняя файловая форма модулей, сегментов и компонентов определяются стайлгайдом проекта.
|
||||
|
||||
@@ -43,6 +42,7 @@ Level 1 требует отдельную папку и единый публи
|
||||
|
||||
- [Терминология](./terminology.md)
|
||||
- [Слои](./layers.md)
|
||||
- [Доменные модули](./domains.md)
|
||||
- [Зависимости](./dependencies.md)
|
||||
- [Модули](./modules.md)
|
||||
- [Группы](./groups.md)
|
||||
|
||||
@@ -22,6 +22,15 @@
|
||||
- Модули одного слоя могут импортировать друг друга.
|
||||
- Промежуточный слой не является обязательным посредником.
|
||||
|
||||
Доменный модуль Level 1 может импортировать публичный API другого доменного модуля. Runtime- и type-only импорты одинаково создают ребро графа, поэтому общий граф обязан оставаться ацикличным.
|
||||
|
||||
```ts
|
||||
// domains/orders
|
||||
import type { Product } from '@/domains/catalog'
|
||||
```
|
||||
|
||||
Level 1 не требует отдельного механизма междоменной инъекции. Более строгая модель cross-domain зависимостей задаётся Level 2.
|
||||
|
||||
Направление слоёв определено в [Слоях](./layers.md).
|
||||
|
||||
## Связанные правила
|
||||
|
||||
61
DRAFT/level-1/domains.md
Normal file
61
DRAFT/level-1/domains.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# Доменные модули Level 1
|
||||
|
||||
> Пояснение базовой модели предметных областей без обязательной внутренней архитектуры.
|
||||
|
||||
## Связанные правила
|
||||
|
||||
- [`SLM-L1-DOMAIN-R015`](../rules/level-1.md#slm-l1-domain-r015)
|
||||
- [`SLM-L1-MODULE-A004`](../rules/level-1.md#slm-l1-module-a004)
|
||||
- [`SLM-L1-MODULE-R006`](../rules/level-1.md#slm-l1-module-r006)
|
||||
- [`SLM-L1-GROUP-R007`](../rules/level-1.md#slm-l1-group-r007)
|
||||
|
||||
## Один домен, один модуль
|
||||
|
||||
Связная предметная область получает один доменный модуль. Level 1 не требует выделять business, adapters, presets или framework bindings в самостоятельные соседние модули.
|
||||
|
||||
```text
|
||||
domains/auth/
|
||||
├── hooks/
|
||||
├── services/
|
||||
├── stores/
|
||||
├── types/
|
||||
├── ui/
|
||||
└── index.ts
|
||||
```
|
||||
|
||||
Показанные каталоги являются возможными сегментами, а не обязательным каркасом. Доменный модуль может содержать предметные типы, сценарии, состояние, framework-код, локальные адаптеры, компоненты и вложенные модули.
|
||||
|
||||
## Публичный API
|
||||
|
||||
Внешний код использует домен через обычный публичный API модуля:
|
||||
|
||||
```ts
|
||||
import { signOut, useSession } from '@/domains/auth'
|
||||
```
|
||||
|
||||
Глубокий импорт во внутренний сегмент нарушает модульную границу:
|
||||
|
||||
```ts
|
||||
import { useSession } from '@/domains/auth/hooks/use-session'
|
||||
```
|
||||
|
||||
## Groups
|
||||
|
||||
При большом количестве доменных модулей слой `domains` может содержать обычные навигационные Groups:
|
||||
|
||||
```text
|
||||
domains/
|
||||
├── shop/ # Group
|
||||
│ ├── catalog/ # Доменный модуль
|
||||
│ └── orders/ # Доменный модуль
|
||||
└── cabinet/ # Group
|
||||
└── profile/ # Доменный модуль
|
||||
```
|
||||
|
||||
Group не имеет `index.ts`, реализации, состояния или публичного API. Она не создаёт dependency boundary и не реэкспортирует содержащиеся в ней домены.
|
||||
|
||||
## Переход на Level 2
|
||||
|
||||
Доменный модуль переводится в доменный пакет Level 2, когда ему нужны устойчивый `DomainApi`, одна фабрика, несколько сред выполнения или независимые SLM-модули сборок и framework-интеграции.
|
||||
|
||||
Такой переход изменяет структурную границу: корневой доменный модуль исчезает, а его предметная ответственность переходит обязательному модулю `business` внутри доменного пакета.
|
||||
@@ -8,6 +8,7 @@
|
||||
src/
|
||||
├── app/
|
||||
├── compositions/
|
||||
├── domains/
|
||||
├── infra/
|
||||
├── ui/
|
||||
└── shared/
|
||||
@@ -29,6 +30,12 @@ src/
|
||||
|
||||
`compositions` содержит продуктовый интерфейс: страницы, макеты, экраны, виджеты, точки входа и другие композиционные модули. Внутреннюю группировку слоя определяет проект.
|
||||
|
||||
### Domains
|
||||
|
||||
`domains` содержит предметные области приложения: их модели, правила, сценарии и продуктовое состояние. Каждая самостоятельная предметная область представлена [доменным модулем](./domains.md).
|
||||
|
||||
Доменная логика не принадлежит устройству одной страницы или маршрута. Конкретный visual outcome и сборка нескольких доменов остаются в `compositions`.
|
||||
|
||||
### Infra
|
||||
|
||||
`infra` содержит технические сервисы приложения: аналитику, локализацию, тему, телеметрию и другие возможности среды выполнения без самостоятельной доменной модели.
|
||||
@@ -52,6 +59,8 @@ app
|
||||
↓
|
||||
compositions
|
||||
↓
|
||||
domains
|
||||
↓
|
||||
infra
|
||||
↓
|
||||
ui
|
||||
@@ -63,8 +72,9 @@ shared
|
||||
|
||||
| Слой | Может импортировать нижние слои |
|
||||
|---|---|
|
||||
| `app` | `compositions`, `infra`, `ui`, `shared` |
|
||||
| `compositions` | `infra`, `ui`, `shared` |
|
||||
| `app` | `compositions`, `domains`, `infra`, `ui`, `shared` |
|
||||
| `compositions` | `domains`, `infra`, `ui`, `shared` |
|
||||
| `domains` | `infra`, `ui`, `shared` |
|
||||
| `infra` | `ui`, `shared` |
|
||||
| `ui` | `shared` |
|
||||
| `shared` | Нет |
|
||||
@@ -80,6 +90,6 @@ shared
|
||||
|
||||
## Граница Level 1
|
||||
|
||||
Разрешённый импорт не переносит владение. Например, `infra` может использовать `ui`, но продуктовый интерфейс по-прежнему принадлежит `compositions`.
|
||||
Разрешённый импорт не переносит владение. Например, доменный модуль может использовать `infra` и `ui`, но технический сервис и универсальный интерфейс сохраняют собственных владельцев.
|
||||
|
||||
Самостоятельная доменная модель или сценарий являются сигналом рассмотреть [Level 2](../level-2/), а не расширять ответственность `shared` или `infra`.
|
||||
Если код определяет продуктовую модель, правило или сценарий, он принадлежит `domains`, а не `shared` или `infra`. Строгая внутренняя форма домена появляется только на [Level 2](../level-2/).
|
||||
|
||||
@@ -46,26 +46,37 @@
|
||||
|
||||
Полный линейный порядок слоёв выбранного уровня SLM. Он определяет, какой слой является нижним для проверки зависимостей.
|
||||
|
||||
Для Level 1 нормативным является порядок `app → compositions → infra → ui → shared`. Более высокий уровень может добавить новые роли и задаёт собственный полный порядок, сохраняя направление от верхних слоёв к нижним.
|
||||
Для Level 1 нормативным является порядок `app → compositions → domains → infra → ui → shared`. Level 2 сохраняет этот порядок и уточняет внутреннюю форму слоя `domains`.
|
||||
|
||||
### Слой
|
||||
|
||||
Одна из пяти верхнеуровневых ролей внутри SLM root:
|
||||
Одна из шести верхнеуровневых ролей внутри SLM root:
|
||||
|
||||
| Слой | Роль |
|
||||
|---|---|
|
||||
| `app` | Связь приложения с фреймворком: запуск, маршруты и преобразование входных данных |
|
||||
| `compositions` | Сборка продуктового интерфейса: страницы, макеты, экраны, виджеты и другие композиции |
|
||||
| `domains` | Предметные области, их модели, правила, сценарии и продуктовое состояние |
|
||||
| `infra` | Технические сервисы и возможности приложения |
|
||||
| `ui` | Универсальные модули интерфейса без зависимости от конкретной продуктовой композиции |
|
||||
| `shared` | Независимый детерминированный фундамент без знания о продукте, изменяемого состояния и ввода-вывода |
|
||||
|
||||
Слои образуют линейный порядок `app → compositions → infra → ui → shared`. Нижним считается любой слой справа от исходного; промежуточный слой не является обязательным посредником.
|
||||
Слои образуют линейный порядок `app → compositions → domains → infra → ui → shared`. Нижним считается любой слой справа от исходного; промежуточный слой не является обязательным посредником.
|
||||
|
||||
### Модуль
|
||||
|
||||
Минимальная самостоятельная архитектурная единица Level 1. Модуль владеет одной связной ответственностью, размещается в отдельной папке и предоставляет публичный API.
|
||||
|
||||
### Доменная ответственность
|
||||
|
||||
Связная предметная область приложения, которая может включать собственные модели, правила, сценарии и продуктовое состояние. Количество экранов, endpoint-ов, hooks или файлов само по себе не определяет её границу.
|
||||
|
||||
### Доменный модуль
|
||||
|
||||
Обычный SLM-модуль слоя `domains`, представляющий одну доменную ответственность. Он подчиняется всем правилам модулей, предоставляет единый публичный API и является узлом графа зависимостей.
|
||||
|
||||
Доменный модуль может содержать сегменты, компоненты и вложенные модули. Level 1 не требует разделять его внутреннее содержимое по техническим ролям.
|
||||
|
||||
### Группа
|
||||
|
||||
Навигационная папка для модулей и других групп. Группа не является владельцем ответственности, состояния, области жизни, публичного API или узла графа зависимостей.
|
||||
@@ -104,7 +115,7 @@
|
||||
SLM root
|
||||
├── app
|
||||
│ └── точка входа фреймворка
|
||||
├── compositions | infra | ui
|
||||
├── compositions | domains | infra | ui
|
||||
│ ├── группа
|
||||
│ │ └── модуль
|
||||
│ └── модуль
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
## Автоматическая проверка
|
||||
|
||||
Проект, заявляющий соответствие Level 1, сопоставляет физические пути с SLM root, слоями, модулями, вложенными модулями, публичными точками входа, точками входа `app` и ресурсами `shared`. Такое сопоставление задаётся стайлгайдом или конфигурацией проверки и не изменяет нормативный смысл сущностей.
|
||||
Проект, заявляющий соответствие Level 1, сопоставляет физические пути с SLM root, слоями, доменными модулями, остальными модулями, Groups, вложенными модулями, публичными точками входа, точками входа `app` и ресурсами `shared`. Такое сопоставление задаётся стайлгайдом или конфигурацией проверки и не изменяет нормативный смысл сущностей.
|
||||
|
||||
Каждое правило класса `A` должно быть реализовано проверкой проекта и блокировать её при нарушении. Level 1 не навязывает конкретный инструмент.
|
||||
|
||||
@@ -17,7 +17,18 @@
|
||||
Правила класса `R` проверяются вручную. Статический анализ может обнаружить подозрительный код, но не способен окончательно определить:
|
||||
|
||||
- ответственность и её владельца;
|
||||
- связность предметной области доменного модуля;
|
||||
- соответствие кода роли слоя;
|
||||
- необходимость экспортов публичного API;
|
||||
- область жизни ресурса и достаточность очистки;
|
||||
- наличие самостоятельной границы у компонента, группы или сегмента.
|
||||
|
||||
## Проверка доменных модулей
|
||||
|
||||
На ревью определяется:
|
||||
|
||||
- представляет ли доменный модуль одну связную предметную область;
|
||||
- не разделена ли одна область на соседние модули без самостоятельных владельцев;
|
||||
- не объединены ли в одном модуле несвязанные предметные области;
|
||||
- остаются ли страницы, маршруты и multi-domain UI в `compositions`;
|
||||
- остаются ли самостоятельные технические сервисы без предметной модели в `infra`.
|
||||
|
||||
Reference in New Issue
Block a user