Files
docs/projects/slm-design/canons/architecture/layers.md
S.Gromov 89cc873c19
All checks were successful
CI/CD Pipeline / build (push) Successful in 44s
CI/CD Pipeline / docker (push) Successful in 1m17s
CI/CD Pipeline / deploy (push) Successful in 8s
docs: обновить архитектуру SLM compositions
- обновлена модель слоёв на app → compositions → business → infra → ui → shared
- добавлены правила composition modules и providers-сегмента
- обновлены правила монорепозитория для слоя compositions
- переписаны React-примеры под page-level композицию
- добавлен пример вариантов структуры compositions
2026-05-26 23:46:11 +03:00

12 KiB
Raw Blame History

title, description
title description
Слои Иерархия слоёв от app до shared, правила зависимостей и зона ответственности каждого слоя

Слои

Раздел описывает слои SLM: что такое слой, какие бывают, как между ними направлены зависимости и какие правила действуют на каждом.

Определение

Слой — уровень организации кода внутри src/. Каждый слой отвечает за свою область и задаёт правила для кода внутри: направление импортов, именование, допустимые связи между модулями.

Группы слоёв

Слои делятся на три группы:

Группа Слои Описание
Композиция app, compositions Подключают приложение к фреймворку и собирают страницы, маршруты и крупные продуктовые части интерфейса
Ядро business, infra, ui Реализация продукта: бизнес-домены, техсервисы, UI-кит
Фундамент shared Общие ресурсы: утилиты, хелперы, стили, конфиги

Направление зависимостей

Любой импорт между модулями — только через публичный API.

app → compositions → business → infra → ui → shared
  • app подключает приложение к фреймворку и импортирует готовые модули из нижних слоёв
  • compositions импортирует business, infra, ui, shared
  • business импортирует infra, ui, shared
  • infra импортирует infra, ui, shared
  • ui импортирует ui и shared
  • shared не импортирует другие SLM-слои
  • business, infra, ui, shared не импортируют compositions
  • Внутри compositions направление импортов между composition modules не фиксируется, но импорты разрешены только через публичный API
  • Модули business используют runtime-зависимости на другие домены только через фабрику, import type — напрямую
  • Импорт типов (import type) в «Ядре» разрешён в обоих направлениях

Слой App

Точка входа приложения. Отвечает за запуск, роутинг и подключение composition modules к фреймворку.

В отличие от остальных слоёв, app/ не содержит модулей SLM. Здесь живут только инфраструктурные файлы, которые не могут быть никаким другим слоем: файлы фреймворка роутинга, точка запуска и код инициализации.

Требования

  • Не содержит модулей SLM — только файлы фреймворка, роутинг, инициализация
  • Содержит: файлы маршрутов, bootstrap, обработку ошибок верхнего уровня (404, error boundary), подключение глобальных стилей и ассетов
  • Провайдеры, guards, layouts, screens и страницы — только подключает готовые из compositions или нижних слоёв, не реализует
  • Не содержит бизнес-логику, UI-компоненты, хуки, сторы, сервисы
  • Никем не импортируется

Слой Compositions

compositions/ — слой сборки страниц, маршрутов и крупных продуктовых частей интерфейса.

На этом слое собираются page, layout, screen, widget и другие composition modules. Они связываются между собой и с нижними слоями: business, infra, ui, shared.

SLM не фиксирует жёсткую структуру внутри compositions. Команда выбирает организацию под фреймворк, роутинг, CMS и продуктовую задачу.

Базовая рекомендация:

src/compositions/
├── pages/
├── layouts/
├── screens/
└── widgets/

pages, layouts, screens и widgets внутри compositions не являются отдельными SLM-слоями. Это типы композиционных модулей.

Composition module может содержать обычные сегменты SLM: ui/, parts/, hooks/, stores/, services/, mappers/, types/, styles/, lib/, config/, providers/.

Page-level store, provider, guard или business composition размещаются внутри page composition module, если они нужны всей странице.

compositions/pages/profile/
├── profile.page.tsx
├── profile-business-composition.ts
├── providers/
├── hooks/
├── stores/
├── types/
└── index.ts

Layout, screen и widget могут получать данные page composition через публичный API соответствующего composition module.

import { useProfilePageStore } from '@/compositions/pages/profile'

Внутри compositions направление импортов между composition modules не фиксируется. Допустим граф, но все импорты идут только через public API.

// Хорошо
import { useProfilePageStore } from '@/compositions/pages/profile'

// Плохо
import { useProfilePageStore } from '@/compositions/pages/profile/hooks/use-profile-page-store.hook'

Требования

  • compositions содержит composition modules страниц, маршрутов и крупных продуктовых частей интерфейса
  • Структура внутри compositions выбирается командой
  • Базовая рекомендация: pages/, layouts/, screens/, widgets/
  • pages, layouts, screens, widgets внутри compositions не являются отдельными SLM-слоями
  • Providers, stores, guards и business composition размещаются внутри того composition module, которому они принадлежат
  • Внутри compositions импорты между composition modules разрешены в любую сторону, но только через public API
  • Deep imports внутрь composition modules запрещены
  • business, infra, ui и shared не импортируют compositions

Слой Business

Бизнес-домены приложения: auth, catalog, orders, checkout, chat. Каждый домен — отдельный модуль со своими типами, логикой, UI и сервисами.

Слой входит в группу «Ядро». Импортирует infra/, ui/, shared/. Каждый бизнес-модуль создаёт публичный API фабрики в корне. Cross-domain зависимости: runtime — через аргументы фабрики, типы — напрямую через import type.

Business объединяет то, что в FSD разделено на features и entities: пользовательские сценарии и бизнес-сущности живут вместе, внутри одного домена. Внутри домена сегменты разделяют ответственность: types/ — доменная модель, hooks/ и services/ — сценарии и логика, mappers/ — трансформация данных, parts/ — составные блоки.

src/business/
├── auth/
├── catalog/
├── orders/
├── checkout/
└── chat/

Когда количество доменов затрудняет навигацию — вводится группировка по субдоменам. Группа — папка для организации, не модуль (без index.ts).

src/business/
├── commerce/
│   ├── catalog/
│   ├── cart/
│   ├── orders/
│   └── checkout/
└── communication/
    ├── chat/
    └── notifications/

Требования

  • Один модуль = один бизнес-домен
  • Циклические зависимости между доменами запрещены
  • Публичный API фабрики — через фабрику в корне модуля ({name}.factory.ts). index.ts экспортирует только фабрику и type-only экспорты
  • Импорт runtime-кода между доменами — через фабрику. import type — напрямую
  • Доменные типы (User, Product) живут здесь, не в shared/

Слой infra

Техсервисы приложения: theme, i18n, API-адаптеры, logger, realtime. Каждый сервис — отдельный модуль.

Слой входит в группу «Ядро». Импортирует infra/, ui/, shared/.

Отличие от shared/: infra — инфраструктура приложения (сервисы, темы, адаптеры к API), shared/ — общие ресурсы (утилиты, хелперы, стили, конфиги).

src/infra/
├── theme/
├── i18n/
├── backend-api/
├── maps-api/
├── logger/
├── feature-flags/
└── realtime/

Требования

  • Один модуль = один техсервис
  • Импортирует infra/, ui/, shared/
  • Не содержит продуктовые composition modules конкретных страниц или маршрутов

Слой UI

UI-кит без бизнес-логики: button, carousel, toast, modal.

Слой входит в группу «Ядро». Импортирует ui/ и shared/.

Компоненты строятся друг на друге: button использует icon, carousel использует button.

src/ui/
├── button/
├── input/
├── icon/
├── carousel/
├── modal/
├── toast/
├── dropdown/
├── tabs/
└── tooltip/

Когда количество компонентов затрудняет навигацию — вводится группировка на примитивы и композиции. Примитивы (button, icon, input) не импортируют композиции. Композиции (carousel, modal, dropdown) строятся на примитивах.

src/ui/
├── primitives/
│   ├── button/
│   ├── input/
│   ├── icon/
│   └── badge/
└── composites/
    ├── carousel/
    ├── modal/
    ├── dropdown/
    ├── tabs/
    └── tooltip/

Требования

  • Не содержит бизнес-логику
  • Импортирует только ui/ и shared/

Слой Shared

Общие ресурсы: утилиты, хелперы, стили, конфиги. Не знает о бизнес-домене.

Слой входит в группу «Фундамент» — ни о ком не знает, никого не импортирует.

Отличие от infra/: infra — инфраструктура приложения (сервисы, темы, адаптеры к API), shared/ — общие ресурсы (утилиты, хелперы, стили, конфиги).

Отличие от ui/: UI-компоненты (button, carousel, modal) живут в слое ui/, а не здесь.

src/shared/
├── lib/
├── types/
├── styles/
└── sprites/

Требования

  • Не имеет runtime-состояния
  • Не знает о продуктовых composition modules