Files
slm-design/docs/architecture/segments.md

107 lines
8.5 KiB
Markdown
Raw Permalink Normal View History

2026-08-10 09:12:22 +03:00
# Сегменты
Сегмент организует внутреннее содержимое одного модуля по назначению. Он помогает ориентироваться в реализации владельца, но не создаёт новую ответственность или архитектурную границу.
## Место в модели
Сегмент появляется только внутри уже определённого модуля:
```text
Слой → [Группа*] → Модуль → [Сегмент*]
```
2026-08-10 12:37:32 +03:00
Группа классифицирует модули внутри слоя. Сегмент классифицирует код одного модуля. Ни группа, ни сегмент не являются владельцами.
2026-08-10 09:12:22 +03:00
2026-08-10 12:37:32 +03:00
Все файлы, framework-компоненты, состояние, зависимости и lifecycle-код сегмента принадлежат ближайшему модулю. Исключением является только вложенный модуль, который начинает собственную границу владения.
2026-08-10 09:12:22 +03:00
## Назначение
Сегмент используется, когда группировка внутренних файлов по назначению упрощает навигацию. Набор и названия сегментов определяет проект.
```text
profile/
2026-08-10 12:37:32 +03:00
├── index.ts # Публичный фасет
├── profile.tsx # Главная реализация
├── components/ # Возможный сегмент
├── hooks/ # Возможный сегмент
├── services/ # Возможный сегмент
├── stores/ # Возможный сегмент
├── types/ # Возможный сегмент
└── styles/ # Возможный сегмент
2026-08-10 09:12:22 +03:00
```
2026-08-10 12:37:32 +03:00
Ни один сегмент не создаётся заранее. Модуль может обойтись без сегментов, если помимо публичных фасетов содержит только один главный implementation- или assembly-файл, однозначно выражающий его ответственность. Любая остальная реализация размещается в подходящих сегментах. Если главный файл нельзя определить уверенно, вся реализация остаётся в сегментах.
2026-08-10 09:12:22 +03:00
Сегмент:
- не имеет самостоятельной ответственности;
- не предоставляет публичный API;
- не владеет состоянием или жизненным циклом;
- не является узлом графа зависимостей;
- не импортируется внешним кодом как отдельная архитектурная сущность.
2026-08-10 12:37:32 +03:00
Локальный `index.ts` может использоваться во внутренней единице сегмента. Он не превращает эту единицу или сегмент в модульную границу.
## Framework-компоненты
2026-08-10 09:12:22 +03:00
2026-08-10 12:37:32 +03:00
Framework-компоненты являются обычным внутренним кодом модуля. Они могут выполнять визуальные и невизуальные роли, включая Provider, Guard или Error Boundary, если используемый фреймворк считает соответствующую сущность компонентом.
2026-08-10 09:12:22 +03:00
2026-08-10 12:37:32 +03:00
Помимо опционального главного framework-файла в корне, остальные компонентные единицы размещаются на одном внутреннем уровне относительно модуля. Каталог такой единицы может содержать локальные `styles`, `types`, `hooks`, `tests` и внутренний `index.ts`, но не содержит другие компонентные единицы или вложенные модули.
2026-08-10 09:12:22 +03:00
```text
2026-08-10 12:37:32 +03:00
header/ # Модуль
├── index.ts # Публичный фасет
├── header.tsx # Главная реализация
└── components/ # Сегмент
├── button-submit/
│ ├── index.ts # Локальная точка входа
│ ├── button-submit.tsx
│ ├── styles/
│ ├── types/
│ └── hooks/
└── icon.tsx # Соседняя компонентная единица
2026-08-10 09:12:22 +03:00
```
2026-08-10 12:37:32 +03:00
`ButtonSubmit` может рендерить `Icon`, но их файловые области не вкладываются друг в друга. Ограничение относится к файловой структуре, а не к runtime-дереву.
2026-08-10 09:12:22 +03:00
Внешний код не импортирует `components/button-submit`. Если компонент нужен снаружи, модуль-владелец реэкспортирует его через собственный публичный фасет.
2026-08-10 12:37:32 +03:00
## Вложенные модули
Сегмент может содержать вложенные модули. В отличие от остальных файлов сегмента, каждый вложенный модуль владеет отдельно сформулированной подответственностью и имеет публичный API и границу зависимостей.
2026-08-10 09:12:22 +03:00
```text
landing/ # Родительский модуль
2026-08-10 12:37:32 +03:00
└── modules/ # Сегмент
2026-08-10 09:12:22 +03:00
└── hero/ # Вложенный модуль
2026-08-10 12:37:32 +03:00
├── index.ts # Публичный фасет вложенного модуля
├── hero.tsx # Главная реализация hero
└── modules/ # Допустимая модульная рекурсия
└── media/
└── index.ts
2026-08-10 09:12:22 +03:00
```
2026-08-10 12:37:32 +03:00
Компонентный каталог не содержит `components` или `modules`. Рекурсивная структурная вложенность допускается только через вложенные модули. Имена `components` и `modules` являются примерами локального стайлгайда, а не обязательными соглашениями SLM.
2026-08-10 09:12:22 +03:00
2026-08-10 12:37:32 +03:00
## Выбор размещения
2026-08-10 09:12:22 +03:00
| Ситуация | Решение |
|---|---|
2026-08-10 12:37:32 +03:00
| Код относится к существующему владельцу и группируется по назначению | Сегмент |
| Вспомогательный код нужен только одной компонентной единице | Колоцировать в её локальном каталоге |
| Выделена отдельная framework-компонентная единица | Разместить на общем внутреннем уровне модуля |
| Код нужен нескольким внутренним единицам модуля | Поднять в ближайший общий сегмент |
| Появилась самостоятельная связная подответственность | Создать вложенный модуль |
| Файл однозначно является главной реализацией или сборкой ответственности | Допустимо разместить в корне модуля |
| Файл не является главным или его роль неоднозначна | Разместить в подходящем сегменте |
2026-08-10 09:12:22 +03:00
2026-08-10 12:37:32 +03:00
Размер каталога и количество файлов не определяют модульную границу. Её создаёт только самостоятельная ответственность и назначение нового владельца.
2026-08-10 09:12:22 +03:00
## Связанные правила
- [`SLM-SEGMENT-R008`](../rules/registry.md#slm-segment-r008)
- [`SLM-MODULE-A004`](../rules/registry.md#slm-module-a004)
2026-08-10 12:37:32 +03:00
- [`SLM-MODULE-R020`](../rules/registry.md#slm-module-r020)
- [`SLM-MODULE-R021`](../rules/registry.md#slm-module-r021)
2026-08-10 09:12:22 +03:00
- [`SLM-NESTED_MODULE-A010`](../rules/registry.md#slm-nested_module-a010)