Files
slm-design/docs/architecture/segments.md
2026-08-10 12:37:32 +03:00

107 lines
8.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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