feat: переработать уровни SLM

This commit is contained in:
2026-07-30 18:45:54 +03:00
parent c0956ed2a0
commit d3b37eb4bd
44 changed files with 1239 additions and 1449 deletions

View File

@@ -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)

View File

@@ -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
View 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` внутри доменного пакета.

View File

@@ -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/).

View File

@@ -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
│ ├── группа
│ │ └── модуль
│ └── модуль

View File

@@ -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`.