5.2 KiB
Зависимости SLM
Пояснение нормативной модели зависимостей SLM.
Матрица слоёв задаёт допустимые зависимости между модулями.
Что считается зависимостью
- Обычный импорт, импорт типа и реэкспорт одинаково создают архитектурную зависимость.
- Импорт между файлами одного модуля не пересекает модульную границу.
- Импорт любого внутреннего файла, сегмента или компонента считается зависимостью ближайшего модуля-владельца.
- Вложенный модуль имеет собственную границу зависимостей.
- Группы, сегменты и компоненты не имеют самостоятельных границ зависимостей.
Точка входа фреймворка не является модулем. Её импорты участвуют в проверке направления слоёв.
Ресурс shared также не является модулем. Его прямой импорт участвует в проверке направления слоёв, но не нарушает требование о публичном API модуля.
Допустимые связи
- Модуль может импортировать модули своего слоя и слоёв, разрешённых нормативной матрицей.
- Модули одного слоя могут импортировать друг друга.
- Промежуточный слой не является обязательным посредником.
infraможет импортироватьuiдля визуального представления технической возможности;uiне импортируетinfra.
Модуль слоя domains может импортировать публичный API другого разрешённого модуля. Runtime- и type-only импорты одинаково создают архитектурную зависимость, а циклические зависимости запрещены.
// domains/orders
import type { Product } from '@/domains/catalog'
SLM не требует отдельного механизма инъекции между модулями слоя domains.
Матрица слоёв определена в Слоях.
Связанные правила
SLM-LAYER-A002SLM-MODULE-A004SLM-DEPENDENCY-A005SLM-NESTED_MODULE-A010SLM-ENVIRONMENT-R016SLM-ENVIRONMENT-R017SLM-ENVIRONMENT-R018SLM-ENVIRONMENT-R019
Публичный API
// Допустимо
import { Button } from '@/ui/button'
// Недопустимо
import { Button } from '@/ui/button/button'
Если модуль объявляет специализированный фасет, его путь также является публичным:
import type { Session } from '@/domains/auth'
import { AuthProvider } from '@/domains/auth/client'
import { getServerSession } from '@/domains/auth/server'
Фасеты сред выполнения
Ограничения фасета распространяются на все его runtime-импорты и реэкспорты, включая транзитивные. Type-only import остаётся архитектурной зависимостью, но не добавляет исполняемый код в среду фасета.
index не импортирует и не реэкспортирует client, browser или server. client может использовать универсальную внутреннюю реализацию модуля, но не импортирует browser или server. browser и server могут использовать универсальную внутреннюю реализацию, но не импортируют друг друга.
// Browser-only фасет подключается только за границей без SSR.
const BrowserEditor = dynamic(
() => import('@/domains/editor/browser').then(({ BrowserEditor }) => BrowserEditor),
{ ssr: false },
)
Обычный статический импорт @/domains/editor/browser запрещён даже внутри Client Component. Tree shaking, проверка typeof window и обещание не вызывать экспорт при SSR не заменяют динамическую границу с отключённым SSR.
Циклы
ui/modal → ui/button → ui/icon
ui/icon -/→ ui/modal