mirror of
https://github.com/gromlab-ru/slm-design.git
synced 2026-08-22 07:30:16 +03:00
chore: Новый черновик DRAFT, удалить старые docs-v
This commit is contained in:
53
DRAFT/level-1/README.md
Normal file
53
DRAFT/level-1/README.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# SLM Level 1
|
||||
|
||||
> Статус: рабочий черновик. Документы в этой папке не являются спецификацией.
|
||||
|
||||
Level 1 задаёт основу SLM для лёгких проектов, которым нужна понятная организация без отдельной доменной архитектуры.
|
||||
|
||||
## Место в уровнях SLM
|
||||
|
||||
| Уровень | Назначение |
|
||||
|---|---|
|
||||
| Level 1 | Слои, зависимости, структурные сущности и жизненный цикл ресурсов |
|
||||
| Level 2 | Слой `domains` для модулей с доменной логикой |
|
||||
| Level 3 | Строгие правила доменов для крупных и критичных проектов |
|
||||
|
||||
Повышение уровня может требовать рефакторинга, но базовые понятия Level 1 сохраняются.
|
||||
|
||||
## Область Level 1
|
||||
|
||||
Level 1 описывает слои, модули, группы, сегменты, компоненты, публичный API, граф зависимостей и владение жизненным циклом ресурсов.
|
||||
|
||||
Level 1 не описывает домены, фабрики, порты, адаптеры, обязательный поток данных, монорепозитории, соглашения об именовании и файловый стайлгайд.
|
||||
|
||||
Появление самостоятельной доменной логики является сигналом рассмотреть Level 2.
|
||||
|
||||
## Виды утверждений
|
||||
|
||||
- **Определение** нормативно задаёт смысл архитектурного термина, но не получает код правила.
|
||||
- **Правило** задаёт блокирующий архитектурный инвариант и объявляется в каноническом реестре.
|
||||
- **Рекомендация** помогает принять решение, но не делает архитектуру невалидной.
|
||||
- **Пример** иллюстрирует модель и не задаёт обязательную структуру.
|
||||
|
||||
Нормативные определения находятся в [терминологии](./terminology.md). Канонический набор правил: [правила SLM Level 1](../rules/level-1.md). Формат и требования к ним: [Правила SLM](../rules/).
|
||||
|
||||
Остальные документы Level 1 объясняют и иллюстрируют модель, но не владеют точными формулировками определений и правил.
|
||||
|
||||
## Основная идея
|
||||
|
||||
Модуль является основной архитектурной единицей SLM. Слой задаёт роль и направление зависимостей. Группа помогает навигации, сегмент организует внутреннее содержимое, а компонент всегда принадлежит модулю.
|
||||
|
||||
Level 1 требует отдельную папку и единый публичный API модуля. Имена этих элементов, внутренняя файловая форма модулей, сегментов и компонентов определяются стайлгайдом проекта.
|
||||
|
||||
## Карта черновика
|
||||
|
||||
- [Терминология](./terminology.md)
|
||||
- [Слои](./layers.md)
|
||||
- [Зависимости](./dependencies.md)
|
||||
- [Модули](./modules.md)
|
||||
- [Группы](./groups.md)
|
||||
- [Сегменты](./segments.md)
|
||||
- [Компоненты](./components.md)
|
||||
- [Вложенные модули](./nested-modules.md)
|
||||
- [Жизненный цикл](./lifecycle.md)
|
||||
- [Проверка](./validation.md)
|
||||
65
DRAFT/level-1/components.md
Normal file
65
DRAFT/level-1/components.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Компоненты Level 1
|
||||
|
||||
> Пояснение нормативной модели компонентов Level 1.
|
||||
|
||||
Компонент является строительным элементом интерфейса, а не самостоятельной архитектурной единицей.
|
||||
|
||||
## Связанные правила
|
||||
|
||||
- [`SLM-L1-COMPONENT-R009`](../rules/level-1.md#slm-l1-component-r009)
|
||||
- [`SLM-L1-LAYER-A002`](../rules/level-1.md#slm-l1-layer-a002)
|
||||
- [`SLM-L1-MODULE-A004`](../rules/level-1.md#slm-l1-module-a004)
|
||||
- [`SLM-L1-DEPENDENCY-A005`](../rules/level-1.md#slm-l1-dependency-a005)
|
||||
- [`SLM-L1-MODULE-R011`](../rules/level-1.md#slm-l1-module-r011)
|
||||
- [`SLM-L1-LIFECYCLE-R013`](../rules/level-1.md#slm-l1-lifecycle-r013)
|
||||
|
||||
## Файловая форма
|
||||
|
||||
Файловую форму компонента определяет стайлгайд. Компонент может быть одним файлом фреймворка или каталогом со вспомогательными файлами.
|
||||
|
||||
```text
|
||||
landing/
|
||||
└── ui/
|
||||
└── hero.tsx
|
||||
```
|
||||
|
||||
```text
|
||||
landing/
|
||||
└── ui/
|
||||
└── hero/
|
||||
├── hero.tsx
|
||||
├── styles/
|
||||
│ └── hero.module.css
|
||||
└── types/
|
||||
└── hero-props.type.ts
|
||||
```
|
||||
|
||||
Наличие каталога, типов, стилей или локального `index.ts` не превращает компонент в модуль.
|
||||
|
||||
## Реализация
|
||||
|
||||
Компонент может отображать входные данные, вызывать переданные обработчики, условно строить интерфейс и хранить локальное состояние представления.
|
||||
|
||||
Level 1 не вводит отдельного запрета на импорты, выполняемые кодом компонента. Каждый такой импорт считается зависимостью родительского модуля и должен соблюдать направление слоёв, публичные API и запрет циклов.
|
||||
|
||||
Доступ к данным, состояние, контекст или код жизненного цикла внутри компонента сами по себе не создают новую архитектурную границу. Их источники, зависимости и область жизни определяет родительский модуль.
|
||||
|
||||
Провайдер может технически реализовывать контекст и жизненный цикл фреймворка, но владельцем состояния и ресурсов остаётся родительский модуль.
|
||||
|
||||
Файл в `app` может технически быть компонентом React или Vue. Архитектурно он является точкой входа фреймворка, а не компонентом SLM.
|
||||
|
||||
## Компонент и модуль
|
||||
|
||||
| Признак | Компонент | Модуль |
|
||||
|---|---|---|
|
||||
| Самостоятельная ответственность | Нет | Да |
|
||||
| Собственный публичный API | Нет | Да |
|
||||
| Собственная граница зависимостей | Нет | Да |
|
||||
| Вспомогательные файлы | Может иметь | Может иметь |
|
||||
| Сегменты и вложенные модули | Нет | Может иметь |
|
||||
|
||||
Модуль может состоять всего из одного корневого компонента. Различие определяется владением, а не количеством файлов.
|
||||
|
||||
## Когда нужен вложенный модуль
|
||||
|
||||
Если часть интерфейса получает самостоятельную ответственность, публичный API, собственную границу зависимостей, область жизни или внутреннюю модульную декомпозицию, она является модулем. При локальном использовании такой модуль может размещаться как вложенный.
|
||||
49
DRAFT/level-1/dependencies.md
Normal file
49
DRAFT/level-1/dependencies.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Зависимости Level 1
|
||||
|
||||
> Пояснение нормативной модели зависимостей Level 1.
|
||||
|
||||
Слои задают допустимое направление связей, а модули образуют граф зависимостей.
|
||||
|
||||
## Что считается зависимостью
|
||||
|
||||
- Обычный импорт, импорт типа и реэкспорт одинаково создают архитектурную зависимость.
|
||||
- Импорт между файлами одного модуля не пересекает модульную границу и не создаёт отдельный узел графа.
|
||||
- Импорт любого внутреннего файла, сегмента или компонента считается зависимостью ближайшего модуля-владельца.
|
||||
- Вложенный модуль является обычным самостоятельным узлом графа.
|
||||
- Группы, сегменты и компоненты не являются самостоятельными узлами графа.
|
||||
|
||||
Точка входа фреймворка не является модулем. Её импорты участвуют в проверке направления слоёв, но не образуют исходящий узел графа модулей.
|
||||
|
||||
Ресурс `shared` также не является модулем. Его прямой импорт участвует в проверке направления слоёв, но не нарушает требование о публичном API модуля.
|
||||
|
||||
## Направление
|
||||
|
||||
- Модуль может импортировать модули своего или любого нижнего слоя.
|
||||
- Модули одного слоя могут импортировать друг друга.
|
||||
- Промежуточный слой не является обязательным посредником.
|
||||
|
||||
Направление слоёв определено в [Слоях](./layers.md).
|
||||
|
||||
## Связанные правила
|
||||
|
||||
- [`SLM-L1-LAYER-A002`](../rules/level-1.md#slm-l1-layer-a002)
|
||||
- [`SLM-L1-MODULE-A004`](../rules/level-1.md#slm-l1-module-a004)
|
||||
- [`SLM-L1-DEPENDENCY-A005`](../rules/level-1.md#slm-l1-dependency-a005)
|
||||
- [`SLM-L1-NESTED_MODULE-A010`](../rules/level-1.md#slm-l1-nested_module-a010)
|
||||
|
||||
## Публичный API
|
||||
|
||||
```ts
|
||||
// Допустимо
|
||||
import { Button } from '@/ui/button'
|
||||
|
||||
// Недопустимо
|
||||
import { Button } from '@/ui/button/button'
|
||||
```
|
||||
|
||||
## Циклы
|
||||
|
||||
```text
|
||||
ui/modal → ui/button → ui/icon
|
||||
ui/icon -/→ ui/modal
|
||||
```
|
||||
25
DRAFT/level-1/groups.md
Normal file
25
DRAFT/level-1/groups.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Группы Level 1
|
||||
|
||||
> Пояснение нормативной модели групп Level 1.
|
||||
|
||||
Группа помогает ориентироваться в большом количестве модулей. Она классифицирует структуру, но ничего не реализует и не образует узел графа зависимостей.
|
||||
|
||||
## Связанное правило
|
||||
|
||||
- [`SLM-L1-GROUP-R007`](../rules/level-1.md#slm-l1-group-r007)
|
||||
- [`SLM-L1-MODULE-R011`](../rules/level-1.md#slm-l1-module-r011)
|
||||
|
||||
## Пример
|
||||
|
||||
```text
|
||||
compositions/
|
||||
├── pages/ # Группа
|
||||
│ ├── landing/ # Модуль
|
||||
│ └── contacts/ # Модуль
|
||||
└── layouts/ # Группа
|
||||
└── main/ # Модуль
|
||||
```
|
||||
|
||||
`pages` и `layouts` являются возможной группировкой проекта, а не обязательной структурой Level 1.
|
||||
|
||||
Рекомендуется создавать группу только при реальной навигационной потребности. Если папка начинает владеть файлами реализации, состоянием, жизненным циклом или публичным API, она является модулем и должна получить модульную границу.
|
||||
85
DRAFT/level-1/layers.md
Normal file
85
DRAFT/level-1/layers.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# Слои Level 1
|
||||
|
||||
> Пояснение нормативной модели слоёв Level 1.
|
||||
|
||||
## Базовая структура
|
||||
|
||||
```text
|
||||
src/
|
||||
├── app/
|
||||
├── compositions/
|
||||
├── infra/
|
||||
├── ui/
|
||||
└── shared/
|
||||
```
|
||||
|
||||
`src/` здесь является примером SLM root. Фактическую границу определяет устройство приложения.
|
||||
|
||||
Отсутствующая в проекте роль не требует пустой папки. Слой является доступной архитектурной ролью, а не обязательным элементом каркаса.
|
||||
|
||||
## Роли слоёв
|
||||
|
||||
### App
|
||||
|
||||
`app` связывает приложение с фреймворком: запускает его, объявляет маршруты, преобразует входные данные и подключает публичные API нижних модулей или ресурсы `shared`. Файлы `app` являются точками входа фреймворка, а не модулями SLM.
|
||||
|
||||
Точка входа может напрямую использовать `compositions`, `infra`, `ui` или `shared`, если зависимость разрешена общим порядком слоёв. Такое использование не переносит ответственность нижнего модуля в `app`.
|
||||
|
||||
### Compositions
|
||||
|
||||
`compositions` содержит продуктовый интерфейс: страницы, макеты, экраны, виджеты, точки входа и другие композиционные модули. Внутреннюю группировку слоя определяет проект.
|
||||
|
||||
### Infra
|
||||
|
||||
`infra` содержит технические сервисы приложения: аналитику, локализацию, тему, телеметрию и другие возможности среды выполнения без самостоятельной доменной модели.
|
||||
|
||||
### UI
|
||||
|
||||
`ui` содержит универсальные модули интерфейса, которые не зависят от конкретной страницы или продуктовой композиции.
|
||||
|
||||
### Shared
|
||||
|
||||
`shared` содержит независимый детерминированный фундамент без знания о продукте, изменяемого состояния и ввода-вывода.
|
||||
|
||||
В `shared` допускаются обычные модули и специальные немодульные ресурсы: небольшие чистые утилиты, общие типы, стили, конфигурация и статические файлы. Ресурс не имеет самостоятельной ответственности, публичного API или жизненного цикла и может импортироваться напрямую по пути, установленному стайлгайдом.
|
||||
|
||||
Если ресурсу нужны самостоятельная ответственность, собственные архитектурные зависимости, несколько файлов реализации, изменяемое состояние, ввод-вывод или область жизни, он оформляется как модуль. Каталог ресурсов не реэкспортирует модули и не используется для обхода их публичных API.
|
||||
|
||||
## Порядок слоёв
|
||||
|
||||
```text
|
||||
app
|
||||
↓
|
||||
compositions
|
||||
↓
|
||||
infra
|
||||
↓
|
||||
ui
|
||||
↓
|
||||
shared
|
||||
```
|
||||
|
||||
Код слоя может импортировать модули своего или любого нижнего слоя. Промежуточные слои можно пропускать.
|
||||
|
||||
| Слой | Может импортировать нижние слои |
|
||||
|---|---|
|
||||
| `app` | `compositions`, `infra`, `ui`, `shared` |
|
||||
| `compositions` | `infra`, `ui`, `shared` |
|
||||
| `infra` | `ui`, `shared` |
|
||||
| `ui` | `shared` |
|
||||
| `shared` | Нет |
|
||||
|
||||
Импорты внутри слоя, публичный API и циклы описаны отдельно в [Зависимостях](./dependencies.md).
|
||||
|
||||
## Связанные правила
|
||||
|
||||
- [`SLM-L1-LAYER-R001`](../rules/level-1.md#slm-l1-layer-r001)
|
||||
- [`SLM-L1-LAYER-A002`](../rules/level-1.md#slm-l1-layer-a002)
|
||||
- [`SLM-L1-LAYER-R003`](../rules/level-1.md#slm-l1-layer-r003)
|
||||
- [`SLM-L1-MODULE-R011`](../rules/level-1.md#slm-l1-module-r011)
|
||||
|
||||
## Граница Level 1
|
||||
|
||||
Разрешённый импорт не переносит владение. Например, `infra` может использовать `ui`, но продуктовый интерфейс по-прежнему принадлежит `compositions`.
|
||||
|
||||
Самостоятельная доменная модель или сценарий являются сигналом рассмотреть Level 2, а не расширять ответственность `shared` или `infra`.
|
||||
31
DRAFT/level-1/lifecycle.md
Normal file
31
DRAFT/level-1/lifecycle.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Жизненный цикл Level 1
|
||||
|
||||
> Пояснение нормативной модели владения ресурсами Level 1.
|
||||
|
||||
Жизненный цикл является частью ответственности модуля. Файл, компонент, провайдер или точка входа фреймворка могут технически создавать и останавливать ресурс, но архитектурным владельцем остаётся модуль.
|
||||
|
||||
## Связанные правила
|
||||
|
||||
- [`SLM-L1-MODULE-R011`](../rules/level-1.md#slm-l1-module-r011)
|
||||
- [`SLM-L1-LIFECYCLE-R013`](../rules/level-1.md#slm-l1-lifecycle-r013)
|
||||
|
||||
## Граница ресурса
|
||||
|
||||
Для ресурса определяются:
|
||||
|
||||
- модуль-владелец;
|
||||
- место создания;
|
||||
- момент начала работы;
|
||||
- область жизни;
|
||||
- допустимое число экземпляров;
|
||||
- способ остановки и очистки.
|
||||
|
||||
Ресурс начинает работу не раньше начала своей области жизни и не остаётся активным после её завершения. Подписки, слушатели, таймеры, наблюдатели, запросы и соединения рассматриваются одинаково, если требуют явного завершения или отмены.
|
||||
|
||||
## Реализация
|
||||
|
||||
Очистку может выполнять сам модуль, компонент, провайдер или фреймворк. Способ реализации не меняет владельца и не переносит ответственность в технический файл.
|
||||
|
||||
Одиночный экземпляр на всё приложение допустим только тогда, когда модуль действительно владеет областью жизни приложения или процесса. Размещение экземпляра на уровне файла само по себе этого не доказывает.
|
||||
|
||||
Точка входа `app` может запускать или подключать ресурс через публичный API нижнего модуля, но не становится его владельцем.
|
||||
43
DRAFT/level-1/modules.md
Normal file
43
DRAFT/level-1/modules.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Модули Level 1
|
||||
|
||||
> Пояснение нормативной модели модулей Level 1.
|
||||
|
||||
Модуль является основной архитектурной единицей SLM. Он размещается в отдельной папке, но может состоять только из публичной точки входа и одного файла реализации.
|
||||
|
||||
## Связанные правила
|
||||
|
||||
- [`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)
|
||||
|
||||
## Владение
|
||||
|
||||
Каждая самостоятельная ответственность имеет одного модуля-владельца. Модуль определяет её публичный API, зависимости, состояние, область жизни и внутреннее устройство независимо от того, в каком файле выполняется конкретный код.
|
||||
|
||||
Точки входа `app` и нормативные ресурсы `shared` являются единственными немодульными исключениями. Остальной код внутри SLM root либо принадлежит существующему модулю, либо образует новый модуль.
|
||||
|
||||
## Публичный API
|
||||
|
||||
Модуль предоставляет один логический публичный API. Конкретное имя точки входа и механизм экспорта определяет стайлгайд проекта.
|
||||
|
||||
Внешний код использует модуль только через публичный API. Сам API открывает только контракт, необходимый реальным внешним потребителям; внутренние механизмы, изменяемое состояние и детали жизненного цикла остаются закрытыми.
|
||||
|
||||
## Внутреннее устройство
|
||||
|
||||
Модуль может содержать корневые файлы, сегменты, компоненты и [вложенные модули](./nested-modules.md). Внутри своей границы он может использовать относительные импорты и не обязан обращаться к собственному публичному API; точную форму внутренних импортов определяет стайлгайд.
|
||||
|
||||
SLM не требует полного каркаса или обязательного каталога сегментов.
|
||||
|
||||
## Визуальный модуль
|
||||
|
||||
Визуальный модуль обычно имеет корневой компонент, который экспортируется через публичный API.
|
||||
|
||||
```text
|
||||
button/
|
||||
├── button.tsx
|
||||
└── index.ts
|
||||
```
|
||||
|
||||
Корневой компонент остаётся компонентом, а владельцем ответственности является модуль `button`.
|
||||
30
DRAFT/level-1/nested-modules.md
Normal file
30
DRAFT/level-1/nested-modules.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Вложенные модули Level 1
|
||||
|
||||
> Пояснение нормативной модели вложенных модулей Level 1.
|
||||
|
||||
Вложенный модуль является обычным модулем, размещённым внутри границы родительского модуля. Он имеет собственные ответственность, публичный API и узел графа зависимостей и подчиняется всем общим правилам модулей.
|
||||
|
||||
## Связанные правила
|
||||
|
||||
- [`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-DEPENDENCY-A005`](../rules/level-1.md#slm-l1-dependency-a005)
|
||||
- [`SLM-L1-NESTED_MODULE-A010`](../rules/level-1.md#slm-l1-nested_module-a010)
|
||||
|
||||
## Пример
|
||||
|
||||
```text
|
||||
landing/
|
||||
├── landing.page.tsx
|
||||
├── parts/
|
||||
│ └── hero/
|
||||
│ ├── hero.tsx
|
||||
│ └── index.ts
|
||||
└── index.ts
|
||||
```
|
||||
|
||||
`parts/` здесь является примером сегмента, а не обязательным именем.
|
||||
|
||||
Код родительского модуля использует вложенный модуль через его собственный публичный API. Код за пределами родительского модуля получает доступ только через публичный API родителя.
|
||||
|
||||
Если вложенный модуль становится нужен за пределами родителя, рекомендуется перенести его в минимальную общую область без изменения внутренней формы. Доступ через API родителя при этом остаётся допустимым и сам по себе не требует переноса.
|
||||
29
DRAFT/level-1/segments.md
Normal file
29
DRAFT/level-1/segments.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Сегменты Level 1
|
||||
|
||||
> Пояснение нормативной модели сегментов Level 1.
|
||||
|
||||
Сегмент организует внутреннее содержимое модуля. Level 1 определяет роль сегмента, но не задаёт обязательный список имён.
|
||||
|
||||
## Связанное правило
|
||||
|
||||
- [`SLM-L1-SEGMENT-R008`](../rules/level-1.md#slm-l1-segment-r008)
|
||||
- [`SLM-L1-MODULE-A004`](../rules/level-1.md#slm-l1-module-a004)
|
||||
|
||||
## Файловая форма
|
||||
|
||||
Названия, набор и содержимое сегментов определяет стайлгайд проекта. Сегмент может группировать файлы, компоненты или вложенные модули.
|
||||
|
||||
Файлы и компоненты сегмента принадлежат родительскому модулю. Вложенный модуль внутри сегмента сохраняет собственные ответственность, публичный API и узел графа зависимостей.
|
||||
|
||||
## Пример
|
||||
|
||||
```text
|
||||
landing/ # Модуль
|
||||
└── ui/ # Сегмент модуля
|
||||
└── hero/ # Каталог компонента
|
||||
├── hero.tsx
|
||||
├── styles/ # Вспомогательный каталог компонента
|
||||
└── types/ # Вспомогательный каталог компонента
|
||||
```
|
||||
|
||||
`styles/` и `types/` внутри каталога компонента не обязаны считаться сегментами SLM. Их форму определяет стайлгайд компонентов.
|
||||
117
DRAFT/level-1/terminology.md
Normal file
117
DRAFT/level-1/terminology.md
Normal file
@@ -0,0 +1,117 @@
|
||||
# Терминология Level 1
|
||||
|
||||
> Нормативные определения рабочего черновика. Этот раздел не объявляет правила.
|
||||
|
||||
Определения Level 1 задают обязательный смысл архитектурных терминов и используются при толковании всех правил. Код получают только блокирующие требования, а не сами определения.
|
||||
|
||||
## Базовые понятия
|
||||
|
||||
### SLM root
|
||||
|
||||
Граница структурной архитектуры одного приложения. Внутри неё определяются слои, модули и граф зависимостей Level 1. Монорепозиторий, пакеты и отношения между несколькими SLM root находятся за пределами Level 1.
|
||||
|
||||
### Ответственность
|
||||
|
||||
Связная часть приложения с одной причиной изменяться. Ответственность является самостоятельной, когда ей нужны собственные публичный API, зависимости, состояние или область жизни.
|
||||
|
||||
### Владелец
|
||||
|
||||
Модуль, который определяет публичный API ответственности, её зависимости, состояние, область жизни и внутреннее устройство. Место выполнения кода не переносит владение.
|
||||
|
||||
### Публичный API
|
||||
|
||||
Единая логическая точка внешнего доступа к модулю. Публичный API скрывает внутреннее устройство; конкретное имя файла и механизм экспорта определяет стайлгайд проекта.
|
||||
|
||||
### Зависимость
|
||||
|
||||
Статическая связь внутри одного SLM root, которую импорт или реэкспорт создаёт между архитектурными границами. Обычный импорт, импорт типа и реэкспорт одинаково создают архитектурную зависимость.
|
||||
|
||||
Зависимость любого внутреннего файла, сегмента или компонента относится к ближайшему модулю-владельцу. Вложенный модуль начинает собственную границу и становится отдельным узлом графа зависимостей.
|
||||
|
||||
### Область жизни
|
||||
|
||||
Период, в течение которого принадлежащие модулю состояние или долгоживущий ресурс должны оставаться активными.
|
||||
|
||||
### Ресурс жизненного цикла
|
||||
|
||||
Ресурс, работа которого продолжается после первоначального вызова и требует остановки, отмены, отписки или освобождения. Например, подписка, слушатель событий, таймер, наблюдатель, запрос или соединение.
|
||||
|
||||
### Очистка
|
||||
|
||||
Гарантированное прекращение работы ресурса не позже завершения его области жизни. Автоматическая очистка фреймворка считается очисткой владельца, если модуль устанавливает и контролирует соответствующую границу.
|
||||
|
||||
## Структурные сущности
|
||||
|
||||
### Слой
|
||||
|
||||
Одна из пяти верхнеуровневых ролей внутри SLM root:
|
||||
|
||||
| Слой | Роль |
|
||||
|---|---|
|
||||
| `app` | Связь приложения с фреймворком: запуск, маршруты и преобразование входных данных |
|
||||
| `compositions` | Сборка продуктового интерфейса: страницы, макеты, экраны, виджеты и другие композиции |
|
||||
| `infra` | Технические сервисы и возможности приложения |
|
||||
| `ui` | Универсальные модули интерфейса без зависимости от конкретной продуктовой композиции |
|
||||
| `shared` | Независимый детерминированный фундамент без знания о продукте, изменяемого состояния и ввода-вывода |
|
||||
|
||||
Слои образуют линейный порядок `app → compositions → infra → ui → shared`. Нижним считается любой слой справа от исходного; промежуточный слой не является обязательным посредником.
|
||||
|
||||
### Модуль
|
||||
|
||||
Минимальная самостоятельная архитектурная единица Level 1. Модуль владеет одной связной ответственностью, размещается в отдельной папке и предоставляет публичный API.
|
||||
|
||||
### Группа
|
||||
|
||||
Навигационная папка для модулей и других групп. Группа не является владельцем ответственности, состояния, области жизни, публичного API или узла графа зависимостей.
|
||||
|
||||
### Сегмент
|
||||
|
||||
Внутренняя часть одного модуля, которая группирует его содержимое по назначению. Сегмент не является самостоятельным владельцем, публичным API или узлом графа зависимостей.
|
||||
|
||||
### Компонент
|
||||
|
||||
Сущность фреймворка, которая реализует часть интерфейса родительского модуля. Компонент не образует собственного владельца, публичного API или узла графа зависимостей.
|
||||
|
||||
Импорты, состояние, доступ к данным и код жизненного цикла компонента принадлежат родительскому модулю. Их наличие само по себе не создаёт новый модуль; решающим признаком является самостоятельная ответственность.
|
||||
|
||||
### Вложенный модуль
|
||||
|
||||
Обычный модуль, размещённый внутри границы родительского модуля. Он имеет собственные ответственность, публичный API и узел графа зависимостей и подчиняется всем общим правилам модулей.
|
||||
|
||||
Публичный API вложенного модуля доступен коду родительской границы. Для кода за пределами родительского модуля вложенный модуль остаётся внутренней реализацией родителя.
|
||||
|
||||
### Точка входа фреймворка
|
||||
|
||||
Специальная немодульная единица слоя `app`, которая непосредственно связывает приложение с фреймворком. Её импорты участвуют в проверке направления слоёв, но сама точка входа не является узлом графа модулей.
|
||||
|
||||
### Ресурс shared
|
||||
|
||||
Специальная немодульная единица слоя `shared`: небольшая детерминированная утилита, общий тип, стиль, конфигурация или статический ресурс без продуктового знания, изменяемого состояния, ввода-вывода, области жизни и собственного публичного API.
|
||||
|
||||
Ресурс `shared` может импортироваться напрямую по пути, установленному стайлгайдом, и не является узлом графа модулей. Доступный по этому пути файл является всей единицей и не скрывает отдельное внутреннее устройство.
|
||||
|
||||
Если ресурсу нужны самостоятельная ответственность, собственные архитектурные зависимости, несколько файлов реализации, изменяемое состояние, ввод-вывод или область жизни, он оформляется как модуль.
|
||||
|
||||
## Структурная модель
|
||||
|
||||
```text
|
||||
SLM root
|
||||
├── app
|
||||
│ └── точка входа фреймворка
|
||||
├── compositions | infra | ui
|
||||
│ ├── группа
|
||||
│ │ └── модуль
|
||||
│ └── модуль
|
||||
│ ├── корневые файлы
|
||||
│ ├── сегмент
|
||||
│ │ ├── файлы
|
||||
│ │ ├── компоненты
|
||||
│ │ └── вложенные модули
|
||||
│ └── вложенный модуль
|
||||
└── shared
|
||||
├── группа
|
||||
├── модуль
|
||||
└── ресурс shared
|
||||
```
|
||||
|
||||
Путь и имя папки сами по себе не определяют сущность. Её определяют ответственность, владелец и публичная граница. Физическое сопоставление путей с сущностями задаётся стайлгайдом или конфигурацией проверки проекта.
|
||||
23
DRAFT/level-1/validation.md
Normal file
23
DRAFT/level-1/validation.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Проверка Level 1
|
||||
|
||||
> Граница автоматической проверки и архитектурного ревью Level 1.
|
||||
|
||||
## Автоматическая проверка
|
||||
|
||||
Проект, заявляющий соответствие Level 1, сопоставляет физические пути с SLM root, слоями, модулями, вложенными модулями, публичными точками входа, точками входа `app` и ресурсами `shared`. Такое сопоставление задаётся стайлгайдом или конфигурацией проверки и не изменяет нормативный смысл сущностей.
|
||||
|
||||
Каждое правило класса `A` должно быть реализовано проверкой проекта и блокировать её при нарушении. Level 1 не навязывает конкретный инструмент.
|
||||
|
||||
Скрипт `draft-rules.js` проверяет только целостность документов: формат и уникальность кодов, ссылки и наличие тематических упоминаний. Он не проверяет архитектуру приложения.
|
||||
|
||||
Актуальный список правил скрипт получает из [канонического реестра](../rules/level-1.md).
|
||||
|
||||
## Архитектурное ревью
|
||||
|
||||
Правила класса `R` проверяются вручную. Статический анализ может обнаружить подозрительный код, но не способен окончательно определить:
|
||||
|
||||
- ответственность и её владельца;
|
||||
- соответствие кода роли слоя;
|
||||
- необходимость экспортов публичного API;
|
||||
- область жизни ресурса и достаточность очистки;
|
||||
- наличие самостоятельной границы у компонента, группы или сегмента.
|
||||
Reference in New Issue
Block a user