forked from templates/nextjs-template
style: Обновлены правила код стайла
This commit is contained in:
@@ -1,11 +1,20 @@
|
||||
---
|
||||
title: SLM Design
|
||||
description: "Архитектурный подход проекта: что такое SLM и как он устроен."
|
||||
description: Назначение архитектуры, ключевые принципы и карта разделов документации
|
||||
---
|
||||
|
||||
# SLM Design
|
||||
Scoped Layered Module Design — модульная архитектура фронтенд-приложений. Код организован по слоям ответственности, а модуль содержит всё, что ему нужно: компоненты, хуки, сторы, типы, стили.
|
||||
|
||||
Архитектурный подход проекта: что такое SLM и как он устроен.
|
||||
## Разделы спецификации
|
||||
|
||||
Спецификация SLM Design состоит из нескольких связанных разделов. Этот обзор даёт общий контекст, а детальные правила описаны дальше:
|
||||
|
||||
- [Слои](./layers.md) — уровни организации `src/`, направление зависимостей и зона ответственности каждого слоя.
|
||||
- [Модули](./modules.md) — границы ответственности, публичный API, типы модулей и отличие модуля от компонента.
|
||||
- [Сегменты](./segments.md) — внутренние папки модуля (`ui/`, `parts/`, `hooks/`, `types/` и другие) и правила размещения файлов.
|
||||
|
||||
Рекомендуемый порядок чтения: обзор → слои → модули → сегменты.
|
||||
|
||||
## Преимущества
|
||||
|
||||
@@ -19,7 +28,7 @@ Cross-domain зависимости в бизнес-слое реализуют
|
||||
|
||||
### Разделение ответственности без перегрузки слоёв
|
||||
|
||||
Сервисы приложения (`infrastructure/`), UI-кит (`ui/`) и общие ресурсы (`shared/`) — три разных слоя с разной природой. Ни один слой не превращается в свалку разнородного кода.
|
||||
Сервисы приложения (`infra/`), UI-кит (`ui/`) и общие ресурсы (`shared/`) — три разных слоя с разной природой. Ни один слой не превращается в свалку разнородного кода.
|
||||
|
||||
### Горизонтальная инкапсуляция
|
||||
|
||||
@@ -73,7 +82,7 @@ src/
|
||||
│ ├── orders/
|
||||
│ └── chat/
|
||||
│
|
||||
├── infrastructure/
|
||||
├── infra/
|
||||
│ ├── theme/
|
||||
│ ├── i18n/
|
||||
│ ├── backend-api/
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
title: Слои SLM
|
||||
description: Из каких слоёв состоит SLM-архитектура и как они связаны.
|
||||
title: Слои
|
||||
description: Иерархия слоёв от app до shared, правила зависимостей и зона ответственности каждого слоя
|
||||
---
|
||||
|
||||
# Слои SLM
|
||||
# Слои
|
||||
|
||||
Из каких слоёв состоит SLM-архитектура и как они связаны.
|
||||
Раздел описывает слои SLM: что такое слой, какие бывают, как между ними направлены зависимости и какие правила действуют на каждом.
|
||||
|
||||
## Определение
|
||||
|
||||
@@ -18,7 +18,7 @@ description: Из каких слоёв состоит SLM-архитектур
|
||||
| Группа | Слои | Описание |
|
||||
|--------|------|----------|
|
||||
| Композиция | `app`, `layouts`, `screens`, `widgets` | Собирают интерфейс из готовых блоков: маршруты, каркасы, страницы |
|
||||
| Ядро | `business`, `infrastructure`, `ui` | Реализация продукта: бизнес-домены, техсервисы, UI-кит |
|
||||
| Ядро | `business`, `infra`, `ui` | Реализация продукта: бизнес-домены, техсервисы, UI-кит |
|
||||
| Фундамент | `shared` | Общие ресурсы: утилиты, хелперы, стили, конфиги |
|
||||
|
||||
## Направление зависимостей
|
||||
@@ -26,12 +26,12 @@ description: Из каких слоёв состоит SLM-архитектур
|
||||
Любой импорт между модулями — только через публичный API.
|
||||
|
||||
```
|
||||
app → [ layouts | screens ] → widgets → business → infrastructure → ui → shared
|
||||
app → [ layouts | screens ] → widgets → business → infra → ui → shared
|
||||
```
|
||||
|
||||
- `layouts` и `screens` — параллельные слои, не импортируют друг друга
|
||||
- Модули одного слоя в группе «Композиция» изолированы друг от друга
|
||||
- Модули одного слоя `infrastructure` и `ui` могут импортировать друг друга через публичный API
|
||||
- Модули одного слоя `infra` и `ui` могут импортировать друг друга через публичный API
|
||||
- Модули `business` — cross-domain зависимости по коду через фабрику, `import type` напрямую
|
||||
- Импорт типов (`import type`) в «Ядре» разрешён в обоих направлениях
|
||||
|
||||
@@ -129,7 +129,7 @@ src/widgets/
|
||||
|
||||
Бизнес-домены приложения: auth, catalog, orders, checkout, chat. Каждый домен — отдельный модуль со своими типами, логикой, UI и сервисами.
|
||||
|
||||
Слой входит в группу «Ядро». Импортирует `infrastructure/`, `ui/`, `shared/`. Cross-domain зависимости по коду реализуются через фабрику. `import type` между доменами разрешён напрямую.
|
||||
Слой входит в группу «Ядро». Импортирует `infra/`, `ui/`, `shared/`. Каждый бизнес-модуль создаёт публичный runtime API через фабрику в корне. Cross-domain зависимости: runtime — через аргументы фабрики, типы — напрямую через `import type`.
|
||||
|
||||
Business объединяет то, что в FSD разделено на `features` и `entities`: пользовательские сценарии и бизнес-сущности живут вместе, внутри одного домена. Внутри домена сегменты разделяют ответственность: `types/` — доменная модель, `hooks/` и `services/` — сценарии и логика, `mappers/` — трансформация данных, `parts/` — составные блоки.
|
||||
|
||||
@@ -160,19 +160,20 @@ src/business/
|
||||
|
||||
- Один модуль = один бизнес-домен
|
||||
- Циклические зависимости между доменами запрещены
|
||||
- Импорт кода между доменами — через фабрику. `import type` — напрямую
|
||||
- Публичный runtime API — через фабрику в корне модуля (`{name}.factory.ts`). `index.ts` экспортирует только фабрику и type-only экспорты
|
||||
- Импорт runtime-кода между доменами — через фабрику. `import type` — напрямую
|
||||
- Доменные типы (`User`, `Product`) живут здесь, не в `shared/`
|
||||
|
||||
## Слой Infrastructure
|
||||
## Слой infra
|
||||
|
||||
Техсервисы приложения: theme, i18n, API-адаптеры, logger, realtime. Каждый сервис — отдельный модуль.
|
||||
|
||||
Слой входит в группу «Ядро». Импортирует `infrastructure/`, `ui/`, `shared/`.
|
||||
Слой входит в группу «Ядро». Импортирует `infra/`, `ui/`, `shared/`.
|
||||
|
||||
Отличие от `shared/`: infrastructure — инфраструктура приложения (сервисы, темы, адаптеры к API), `shared/` — общие ресурсы (утилиты, хелперы, стили, конфиги).
|
||||
Отличие от `shared/`: infra — инфраструктура приложения (сервисы, темы, адаптеры к API), `shared/` — общие ресурсы (утилиты, хелперы, стили, конфиги).
|
||||
|
||||
```text
|
||||
src/infrastructure/
|
||||
src/infra/
|
||||
├── theme/
|
||||
├── i18n/
|
||||
├── backend-api/
|
||||
@@ -185,7 +186,7 @@ src/infrastructure/
|
||||
### Требования
|
||||
|
||||
- Один модуль = один техсервис
|
||||
- Импортирует `infrastructure/`, `ui/`, `shared/`
|
||||
- Импортирует `infra/`, `ui/`, `shared/`
|
||||
|
||||
## Слой UI
|
||||
|
||||
@@ -236,7 +237,7 @@ src/ui/
|
||||
|
||||
Слой входит в группу «Фундамент» — ни о ком не знает, никого не импортирует.
|
||||
|
||||
Отличие от `infrastructure/`: infrastructure — инфраструктура приложения (сервисы, темы, адаптеры к API), `shared/` — общие ресурсы (утилиты, хелперы, стили, конфиги).
|
||||
Отличие от `infra/`: infra — инфраструктура приложения (сервисы, темы, адаптеры к API), `shared/` — общие ресурсы (утилиты, хелперы, стили, конфиги).
|
||||
|
||||
Отличие от `ui/`: UI-компоненты (button, carousel, modal) живут в слое `ui/`, а не здесь.
|
||||
|
||||
289
ai/nextjs-style-guide/basics/architecture/modules.md
Normal file
289
ai/nextjs-style-guide/basics/architecture/modules.md
Normal file
@@ -0,0 +1,289 @@
|
||||
---
|
||||
title: Модули
|
||||
description: Структура модуля, типы (UI, бизнес, инфра), публичный API, отличие модуля от компонента
|
||||
---
|
||||
|
||||
# Модули
|
||||
|
||||
Раздел описывает модуль как границу ответственности в SLM: что считается модулем, что такое компонент внутри модуля и как модуль взаимодействует с остальным кодом.
|
||||
|
||||
## Определение
|
||||
|
||||
**Модуль — минимальная архитектурная единица SLM. Он живёт на одном из слоёв, владеет конкретной областью ответственности и предоставляет наружу только публичный API.**
|
||||
|
||||
Модуль может содержать всё, что нужно этой области: компоненты, вложенные модули, хуки, сторы, сервисы, типы, стили, конфиги и утилиты. Набор сегментов не фиксирован — модуль включает только то, что реально нужно.
|
||||
|
||||
Модуль не обязан быть UI-блоком. Это может быть страница, виджет, бизнес-домен, инфраструктурный сервис или UI-kit сущность.
|
||||
|
||||
Главная граница модуля — не папка, а ответственность.
|
||||
|
||||
## Компонент
|
||||
|
||||
**Компонент — презентационная единица модуля, которая находится только в `ui/` своего родительского модуля и отвечает за отображение части интерфейса.**
|
||||
|
||||
Компонент не является архитектурной единицей: он не владеет сценарием, зависимостями, данными или внутренней структурой. Он работает только внутри границы родительского модуля.
|
||||
|
||||
> Компонент отображает. Модуль организует.
|
||||
|
||||
Компонент не может:
|
||||
|
||||
- Импортировать код проекта за пределами родительского модуля.
|
||||
- Владеть архитектурными зависимостями.
|
||||
- Содержать любые компоненты.
|
||||
- Содержать любые модули.
|
||||
- Делать внешние запросы.
|
||||
- Самостоятельно получать данные.
|
||||
- Выбирать источник данных.
|
||||
- Композировать данные.
|
||||
- Вызывать сценарные хуки.
|
||||
- Оркестрировать сценарий.
|
||||
- Композировать модули.
|
||||
- Решать, как устроен процесс.
|
||||
- Содержать бизнес-логику.
|
||||
- Содержать сценарную логику.
|
||||
|
||||
Если компоненту требуется что-то из этого списка, он перестаёт быть компонентом и должен быть оформлен как модуль.
|
||||
|
||||
```text
|
||||
auth/
|
||||
├── ui/
|
||||
│ └── logout-button/
|
||||
│ ├── logout-button.tsx
|
||||
│ ├── styles/
|
||||
│ │ └── logout-button.module.css
|
||||
│ ├── types/
|
||||
│ │ └── logout-button-props.type.ts
|
||||
│ └── index.ts
|
||||
└── index.ts
|
||||
```
|
||||
|
||||
## Что считается модулем
|
||||
|
||||
Модулем считается папка, которая представляет самостоятельную область ответственности и имеет публичную границу.
|
||||
|
||||
Примеры модулей:
|
||||
|
||||
- `screens/home/` — модуль страницы.
|
||||
- `widgets/page-heading/` — модуль виджета.
|
||||
- `business/auth/` — модуль бизнес-домена.
|
||||
- `infra/theme/` — модуль инфраструктурного сервиса.
|
||||
- `ui/button/` — модуль UI-kit сущности.
|
||||
- `screens/home/parts/hero-section/` — вложенный модуль страницы.
|
||||
|
||||
Не считаются модулями:
|
||||
|
||||
- `ui/`, `parts/`, `hooks/`, `types/`, `styles/`, `config/` — это сегменты.
|
||||
- `screens/shop/`, `business/commerce/` — это группы, если в них нет `index.ts`.
|
||||
- `screens/home/ui/user-card/` — это компонент, если он находится в `ui/` и соблюдает ограничения компонента.
|
||||
|
||||
## Типы модулей
|
||||
|
||||
Тип модуля определяет обязательный корневой файл и стартовую структуру.
|
||||
|
||||
### UI-модуль
|
||||
|
||||
Модуль строится вокруг основного UI-компонента и обязан иметь основной `.tsx` файл в корне:
|
||||
|
||||
```text
|
||||
header/
|
||||
├── header.tsx
|
||||
└── index.ts
|
||||
```
|
||||
|
||||
`ui/` внутри такого модуля используется только для компонентов, которые помогают корневому `.tsx` файлу.
|
||||
|
||||
### Бизнес-модуль
|
||||
|
||||
Бизнес-модуль — модуль, который строится вокруг публичного runtime API.
|
||||
|
||||
Бизнес-модуль обязан иметь фабрику в корне:
|
||||
|
||||
```text
|
||||
auth/
|
||||
├── auth.factory.ts
|
||||
├── index.ts
|
||||
└── types/
|
||||
```
|
||||
|
||||
Фабрика возвращает публичный runtime API модуля.
|
||||
|
||||
### Инфраструктурный модуль
|
||||
|
||||
Инфраструктурный модуль — модуль, который строится вокруг технического сервиса или интеграции.
|
||||
|
||||
Инфраструктурный модуль не обязан иметь фиксированный корневой файл. Его структура определяется природой сервиса.
|
||||
|
||||
```text
|
||||
theme/
|
||||
├── index.ts
|
||||
├── config/
|
||||
├── hooks/
|
||||
├── styles/
|
||||
└── ui/
|
||||
```
|
||||
|
||||
```text
|
||||
backend-api/
|
||||
├── backend-api.client.ts
|
||||
├── config/
|
||||
├── types/
|
||||
└── index.ts
|
||||
```
|
||||
|
||||
## Структура
|
||||
|
||||
Модуль состоит из сегментов. Ни один сегмент не обязателен — модуль включает только те части, которые нужны его ответственности.
|
||||
|
||||
```text
|
||||
{module-name}/
|
||||
├── {module-name}.factory.ts # фабрика (для business-модулей)
|
||||
├── {module-name}.tsx # корневой файл модуля (опционален)
|
||||
├── ui/ # компоненты модуля
|
||||
├── parts/ # вложенные модули
|
||||
├── hooks/ # хуки
|
||||
├── stores/ # сторы состояния
|
||||
├── services/ # внешние источники данных
|
||||
├── mappers/ # трансформация данных между форматами
|
||||
├── types/ # типы
|
||||
├── styles/ # стили
|
||||
├── lib/ # утилиты модуля
|
||||
├── config/ # константы и конфигурация
|
||||
└── index.ts # публичный API
|
||||
```
|
||||
|
||||
Подробное описание сегментов — в разделе [Сегменты](./segments.md).
|
||||
|
||||
## Публичный API
|
||||
|
||||
Внешний код импортирует модуль только через публичный API.
|
||||
|
||||
```ts
|
||||
// Хорошо
|
||||
import { customerFactory } from '@/business/customer'
|
||||
import type { Customer } from '@/business/customer'
|
||||
```
|
||||
|
||||
```ts
|
||||
// Плохо
|
||||
import { validateToken } from '@/business/auth/lib/tokens'
|
||||
```
|
||||
|
||||
`index.ts` модуля не обязан экспортировать всё содержимое. Он экспортирует только то, что действительно нужно снаружи.
|
||||
|
||||
Внутренние сегменты модуля остаются деталями реализации.
|
||||
|
||||
Business-модуль экспортирует из `index.ts` только фабрику и type-only экспорты. Хуки, компоненты, сервисы, мапперы и утилиты напрямую из `index.ts` не экспортируются — они доступны через API, который возвращает фабрика.
|
||||
|
||||
```ts
|
||||
// business/customer/index.ts
|
||||
export { customerFactory } from './customer.factory'
|
||||
|
||||
export type { Customer } from './types/customer.type'
|
||||
export type { CustomerApi } from './types/customer-api.type'
|
||||
export type { CustomerDeps } from './types/customer-deps.type'
|
||||
export type { CustomerFactory } from './types/customer-factory.type'
|
||||
```
|
||||
|
||||
## Фабрика
|
||||
|
||||
Business-модуль всегда экспортирует фабрику. Фабрика лежит в корне модуля (`{name}.factory.ts`), типизируется через `{Name}Factory` и возвращает публичный runtime API модуля.
|
||||
|
||||
Всё, что нужно внешнему коду в runtime, должно быть частью API, который возвращает фабрика.
|
||||
|
||||
Модуль без cross-domain зависимостей экспортирует фабрику без аргументов. Модуль с зависимостями — фабрику, принимающую зависимости доменными именами. Типы всегда экспортируются напрямую через `export type` — `import type` не является runtime-зависимостью.
|
||||
|
||||
Компоновка фабрик происходит на уровне модуля-потребителя: screen, layout, widget или любой другой модуль группы «Композиция».
|
||||
|
||||
### Структура business-модуля
|
||||
|
||||
```text
|
||||
business/customer/
|
||||
├── customer.factory.ts
|
||||
├── index.ts
|
||||
└── types/
|
||||
├── customer.type.ts
|
||||
├── customer-api.type.ts
|
||||
├── customer-deps.type.ts
|
||||
└── customer-factory.type.ts
|
||||
```
|
||||
|
||||
### Типы
|
||||
|
||||
```ts
|
||||
// business/customer/types/customer-api.type.ts
|
||||
export type CustomerApi = {
|
||||
useCustomer: () => Customer
|
||||
CustomerCard: (props: CustomerCardProps) => ReactNode
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
// business/order/types/order-deps.type.ts
|
||||
export type OrderDeps = {
|
||||
customer: Pick<CustomerApi, 'useCustomer'>
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
// business/order/types/order-factory.type.ts
|
||||
export type OrderFactory = (deps: OrderDeps) => OrderApi
|
||||
```
|
||||
|
||||
### Фабрика без зависимостей
|
||||
|
||||
```ts
|
||||
// business/customer/customer.factory.ts
|
||||
import type { CustomerFactory } from './types/customer-factory.type'
|
||||
|
||||
export const customerFactory: CustomerFactory = () => {
|
||||
return {
|
||||
useCustomer,
|
||||
CustomerCard,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Фабрика с зависимостями
|
||||
|
||||
```ts
|
||||
// business/order/order.factory.ts
|
||||
import type { OrderFactory } from './types/order-factory.type'
|
||||
|
||||
export const orderFactory: OrderFactory = (deps) => {
|
||||
return {
|
||||
useOrder,
|
||||
OrderCard,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Композиция на уровне screen
|
||||
|
||||
```tsx
|
||||
// screens/home/home.screen.tsx
|
||||
import { customerFactory } from '@/business/customer'
|
||||
import { orderFactory } from '@/business/order'
|
||||
|
||||
const customer = customerFactory()
|
||||
const order = orderFactory({ customer })
|
||||
|
||||
const { useOrder, OrderCard } = order
|
||||
|
||||
export const HomeScreen = () => {
|
||||
const currentOrder = useOrder()
|
||||
|
||||
return <OrderCard order={currentOrder} />
|
||||
}
|
||||
```
|
||||
|
||||
## Жизненный цикл
|
||||
|
||||
Модуль рождается на самом низком уровне использования и поднимается выше только при реальной потребности.
|
||||
|
||||
- Нужен на одной странице → `screens/{name}/parts/`
|
||||
- Появился в 2+ местах → поднимается по природе:
|
||||
- абстрактный UI → `ui/`
|
||||
- блок с данными/логикой → `widgets/`
|
||||
- представление бизнес-домена → `business/{area}/parts/`
|
||||
|
||||
Подъём — обычный рефакторинг в рамках задачи, а не отдельная активность.
|
||||
@@ -1,165 +0,0 @@
|
||||
---
|
||||
title: Модули SLM
|
||||
description: Что такое модуль в SLM-архитектуре и как он устроен.
|
||||
---
|
||||
|
||||
# Модули SLM
|
||||
|
||||
Что такое модуль в SLM-архитектуре и как он устроен.
|
||||
|
||||
## Определение
|
||||
|
||||
**Модуль — универсальный строительный блок архитектуры. Живёт на слое и содержит всё необходимое для своей работы: компоненты, хуки, сторы, сервисы, типы, стили. Набор содержимого не фиксирован — включаются только нужные части.**
|
||||
|
||||
## Модуль vs компонент
|
||||
|
||||
**Компонент** — один `.tsx` файл. Не имеет своих сегментов, использует сегменты родительского модуля. Живёт в корне или `ui/` сегменте модуля.
|
||||
|
||||
**Модуль** — папка, которая может содержать корневой компонент, сегменты (`hooks/`, `types/`, `styles/`, `ui/`, `parts/` и т.д.) и публичный API (`index.ts`).
|
||||
|
||||
```text
|
||||
auth/
|
||||
├── ui/
|
||||
│ ├── auth-guard.tsx
|
||||
│ └── logout-button.tsx
|
||||
├── parts/
|
||||
│ ├── login-form/
|
||||
│ ├── registration-form/
|
||||
│ └── restore-form/
|
||||
├── hooks/
|
||||
├── stores/
|
||||
├── types/
|
||||
├── auth.tsx # корневой компонент (опционален)
|
||||
└── index.ts
|
||||
```
|
||||
|
||||
## Структура
|
||||
|
||||
Модуль состоит из сегментов. Ни один сегмент не обязателен — модуль может состоять даже из одного `index.ts` с реэкспортом типов.
|
||||
|
||||
```text
|
||||
{module-name}/
|
||||
├── {module-name}.tsx # корневой компонент (опционален)
|
||||
├── ui/ # компоненты модуля (только .tsx)
|
||||
├── parts/ # вложенные модули (со своими сегментами)
|
||||
├── hooks/ # хуки
|
||||
├── stores/ # сторы состояния
|
||||
├── services/ # внешние источники данных
|
||||
├── mappers/ # трансформация данных между форматами
|
||||
├── types/ # типы
|
||||
├── styles/ # стили
|
||||
├── lib/ # утилиты модуля
|
||||
├── config/ # константы
|
||||
└── index.ts # публичный API
|
||||
```
|
||||
|
||||
Подробное описание каждого сегмента — в разделе [Сегменты](./segments.md).
|
||||
|
||||
## Публичный API
|
||||
|
||||
Модуль экспортирует наружу только то, что нужно другим. Всё остальное — внутреннее.
|
||||
|
||||
```ts
|
||||
// business/auth/index.ts
|
||||
export type { User, Session } from './types/user.types'
|
||||
export { useAuth } from './hooks/use-auth.hook'
|
||||
export { AuthGuard } from './ui/auth-guard'
|
||||
```
|
||||
|
||||
Импорт в обход `index.ts` запрещён:
|
||||
|
||||
```ts
|
||||
// Плохо
|
||||
import { validateToken } from '@/business/auth/lib/tokens'
|
||||
|
||||
// Хорошо
|
||||
import { useAuth } from '@/business/auth'
|
||||
```
|
||||
|
||||
## Фабрика
|
||||
|
||||
Если модуль зависит от кода другого бизнес-домена — он экспортирует фабрику. Фабрика декларирует необходимые зависимости и возвращает API модуля. Точка использования (screen, widget, layout) предоставляет зависимости при вызове.
|
||||
|
||||
Модуль без cross-domain зависимостей экспортирует API напрямую. Типы всегда экспортируются напрямую — `import type` не является runtime-зависимостью.
|
||||
|
||||
### Модуль без зависимостей — прямой экспорт:
|
||||
|
||||
```ts
|
||||
// business/auth/index.ts
|
||||
export { useAuth } from './hooks/use-auth'
|
||||
export { useCurrentUser } from './hooks/use-current-user'
|
||||
export type { User, Session } from './types'
|
||||
```
|
||||
|
||||
### Модуль с зависимостями — фабрика:
|
||||
|
||||
```ts
|
||||
// business/chat/types/deps.ts
|
||||
import type { User } from '@/business/auth'
|
||||
|
||||
export interface ChatDeps {
|
||||
useCurrentUser: () => User | null
|
||||
}
|
||||
```
|
||||
|
||||
```ts
|
||||
// business/chat/index.ts
|
||||
import type { ChatDeps } from './types/deps'
|
||||
|
||||
export function chatFactory(deps: ChatDeps) {
|
||||
return {
|
||||
useMessages: (roomId: string) => {
|
||||
const user = deps.useCurrentUser()
|
||||
// ...
|
||||
},
|
||||
useSendMessage: (roomId: string) => {
|
||||
const user = deps.useCurrentUser()
|
||||
return (text: string) => { /* ... */ }
|
||||
},
|
||||
useChatRooms: () => {
|
||||
const user = deps.useCurrentUser()
|
||||
// ...
|
||||
},
|
||||
ChatBadge: ({ count }: { count: number }) => { /* ... */ },
|
||||
}
|
||||
}
|
||||
|
||||
export type { Message, ChatRoom } from './types'
|
||||
export type { ChatDeps } from './types/deps'
|
||||
```
|
||||
|
||||
### Использование на странице:
|
||||
|
||||
```tsx
|
||||
// screens/support/support.tsx
|
||||
import { useCurrentUser } from '@/business/auth'
|
||||
import { chatFactory } from '@/business/chat'
|
||||
|
||||
const chat = chatFactory({ useCurrentUser })
|
||||
|
||||
export function SupportScreen() {
|
||||
const { useMessages, useSendMessage, ChatBadge } = chat
|
||||
const messages = useMessages('support')
|
||||
const sendMessage = useSendMessage('support')
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ChatBadge count={messages.length} />
|
||||
{messages.map(m => <MessageBubble key={m.id} {...m} />)}
|
||||
<MessageInput onSend={sendMessage} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Жизненный цикл
|
||||
|
||||
Модуль рождается на самом низком уровне использования и поднимается выше только при реальной потребности.
|
||||
|
||||
- Нужен на одной странице → `screens/{name}/parts/`
|
||||
- Появился в 2+ местах → поднимается по природе:
|
||||
- абстрактный UI → `ui/`
|
||||
- блок с данными/логикой → `widgets/`
|
||||
- представление бизнес-домена → `business/{area}/parts/`
|
||||
|
||||
Подъём — обычный рефакторинг в рамках задачи, а не отдельная активность.
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
title: Сегменты SLM
|
||||
description: Что такое сегмент модуля в SLM-архитектуре и какие они бывают.
|
||||
title: Сегменты
|
||||
description: Сегменты внутри модуля (ui/, model/, lib/ и др.), назначение и правила размещения файлов
|
||||
---
|
||||
|
||||
# Сегменты SLM
|
||||
# Сегменты
|
||||
|
||||
Что такое сегмент модуля в SLM-архитектуре и какие они бывают.
|
||||
Раздел описывает сегменты SLM: что такое сегмент, какие бывают и что в каждом из них лежит.
|
||||
|
||||
## Определение
|
||||
|
||||
@@ -15,7 +15,7 @@ description: Что такое сегмент модуля в SLM-архитек
|
||||
|
||||
| Сегмент | Содержимое |
|
||||
|---------|------------|
|
||||
| `ui/` | Вспомогательные компоненты модуля — только `.tsx` файлы |
|
||||
| `ui/` | Презентационные компоненты родительского модуля |
|
||||
| `parts/` | Вложенные модули со своими сегментами |
|
||||
| `hooks/` | React-хуки |
|
||||
| `stores/` | Сторы состояния |
|
||||
@@ -28,22 +28,44 @@ description: Что такое сегмент модуля в SLM-архитек
|
||||
|
||||
## Сегмент ui/
|
||||
|
||||
Вспомогательные компоненты модуля. Содержит только `.tsx` файлы — без своих сегментов, стилей, типов, хуков и публичного API. Использует сегменты родительского модуля.
|
||||
Презентационные компоненты родительского модуля. `ui/` содержит только компоненты, которые отвечают за отображение части интерфейса и не выходят за границы своего модуля.
|
||||
|
||||
Корневой компонент модуля в `ui/` не размещается. Он лежит в корне модуля: `{module-name}.tsx`.
|
||||
Компонент в `ui/`:
|
||||
|
||||
- Находится в собственной папке.
|
||||
- Может содержать только `{name}.tsx`, `index.ts`, `styles/`, `types/`.
|
||||
- Не содержит любые компоненты.
|
||||
- Не содержит любые модули.
|
||||
- Не импортирует код проекта за пределами родительского модуля.
|
||||
- Не делает внешние запросы.
|
||||
- Не вызывает сценарные хуки.
|
||||
- Не получает данные самостоятельно, не выбирает источник данных и не композирует данные.
|
||||
- Не содержит бизнес-логику или сценарную логику.
|
||||
|
||||
Если UI-сущности нужно что-то за пределами этих ограничений, она должна быть оформлена как модуль. Полная граница описана в разделе [Компонент](./modules.md#компонент).
|
||||
|
||||
Корневой файл модуля в `ui/` не размещается. Он лежит в корне модуля: `{module-name}.tsx`.
|
||||
|
||||
```text
|
||||
user/
|
||||
├── ui/
|
||||
│ ├── user-avatar.tsx
|
||||
│ └── user-status.tsx
|
||||
│ ├── user-avatar/
|
||||
│ │ ├── user-avatar.tsx
|
||||
│ │ ├── styles/
|
||||
│ │ │ └── user-avatar.module.css
|
||||
│ │ ├── types/
|
||||
│ │ │ └── user-avatar-props.type.ts
|
||||
│ │ └── index.ts
|
||||
│ └── user-status/
|
||||
│ ├── user-status.tsx
|
||||
│ └── index.ts
|
||||
├── types/
|
||||
├── hooks/
|
||||
├── user.tsx
|
||||
└── index.ts
|
||||
```
|
||||
|
||||
Если компоненту нужны собственные сегменты — это уже не `ui/`, а `parts/`.
|
||||
Если UI-сущности нужна внутренняя декомпозиция, сценарная логика, получение данных или собственные архитектурные зависимости — это уже не компонент в `ui/`, а модуль в `parts/`.
|
||||
|
||||
## Сегмент parts/
|
||||
|
||||
@@ -68,7 +90,7 @@ home/
|
||||
└── index.ts
|
||||
```
|
||||
|
||||
Отличие от `ui/`: элемент `parts/` — модульная папка со своими сегментами. Элемент `ui/` — вспомогательный компонент, один `.tsx` файл.
|
||||
Отличие от `ui/`: элемент `parts/` — модульная папка со своими сегментами. Элемент `ui/` — компонент родительского модуля без собственной архитектурной ответственности.
|
||||
|
||||
Вложенность `parts/` инкапсулирует область разработки горизонтально: каждый разработчик работает в своём `parts/`-модуле, не затрагивая чужие. Это снижает конфликты при параллельной разработке.
|
||||
|
||||
Reference in New Issue
Block a user