7.7 KiB
SLM Level 2
Статус: рабочий черновик. Документы в этой папке не являются спецификацией.
Level 2 предназначен для отдельных предметных областей с устойчивыми API, несколькими способами сборки или самостоятельными framework-модулями. Он сохраняет структурную базу Level 1, но заменяет выбранный доменный модуль доменным пакетом с явными владельцами ролей.
Наследование Level 1
Доменный пакет Level 2 соблюдает определения и правила Level 1, кроме явно заменённых положений:
| Положение Level 1 | Статус в Level 2 |
|---|---|
Матрица app → compositions → domains → { infra, ui } → shared |
Сохраняется |
| Модуль, Group, сегмент, компонент, публичный API и граф зависимостей | Сохраняют смысл |
Доменный модуль и SLM-L1-DOMAIN-R015 |
Заменяются только для предметной области в пакетной форме |
Единый публичный API модуля business |
Представлен обязательными type-only и factory-фасетами и необязательным runtime-фасетом |
Навигационная Group слоя domains |
Может одновременно содержать доменные модули и пакеты |
| Group внутри доменного пакета | Содержит обычные SLM-модули и Groups |
Канонический набор требований образуют правила Level 1 и правила Level 2.
Когда выбирать Level 2
Level 2 оправдан, когда одной предметной области нужны несколько независимо собираемых Domain API, разные browser/server assemblies, несколько технических интеграций или самостоятельные domain-specific модули React, Vue либо другого фреймворка.
Level 2 выбирается для конкретной предметной области. Один SLM root может корректно содержать простые доменные модули Level 1 и доменные пакеты Level 2. Размер каталога сам по себе не требует перехода.
Цена Level 2
Пакетная форма намеренно дороже простого доменного модуля. Она добавляет отдельные business-фасеты, минимум одну assembly, явную runtime-инъекцию cross-domain API и adapter-модули для production capabilities. Concrete state/query runtime, SDK и недетерминизм не импортируются напрямую в business.
Эта цена оправдана независимой сборкой API, несколькими средами, строгой environment boundary или самостоятельными framework bindings. Если домену не нужны такие свойства, он остаётся модулем Level 1.
Базовая форма
src/domains/
├── catalog/ # Доменный модуль Level 1
└── auth/ # Доменный пакет Level 2
├── README.md # Необязательная metadata
├── business/ # Обязательный SLM-модуль
│ ├── index.ts # Только public types
│ ├── factory.ts # Public factories entry
│ └── runtime.ts # Необязательный deterministic runtime
├── assemblies/ # Обязательная непустая Group
│ ├── browser/ # SLM-модуль
│ └── request/ # SLM-модуль
├── adapters/ # При наличии technical dependencies
│ └── identity-provider/ # SLM-модуль
└── react/ # Необязательная framework Group
├── session/ # SLM-модуль
└── login-form/ # SLM-модуль
Корень пакета не является модулем и не имеет index.ts. Каждый исполняемый владелец внутри пакета остаётся обычным SLM-модулем со своим публичным API.
Публичные границы
business может объявить несколько API и соответствующих фабрик. Assembly создаёт только нужный для своего контекста именованный граф:
import type {
AuthAdministrationApi,
AuthSessionApi,
} from '@/domains/auth/business'
import {
authAdministrationFactory,
authSessionFactory,
} from '@/domains/auth/business/factory'
import {
AUTH_ERROR_CODES,
isAuthError,
} from '@/domains/auth/business/runtime'
import { createBrowserAuth } from '@/domains/auth/assemblies/browser'
import { AuthSessionProvider } from '@/domains/auth/react/session'
business/runtime существует только при наличии реальных внешних потребителей детерминированных runtime-экспортов. Общие импорты @/domains/auth и @/domains/auth/react запрещены: пакет и Groups не имеют агрегирующих API.
Совместное применение форм
Простой доменный модуль и доменный пакет могут постоянно сосуществовать в одном SLM root, но одна предметная область имеет только одну форму. При связи, пересекающей границу пакета Level 2, доменный код использует type-only публичный контракт либо детерминированный business/runtime; готовые API передаются runtime-аргументами в месте сборки графа.
Если доменному модулю Level 1 нужна runtime-инъекция, которой его текущий публичный API не поддерживает, этот потребитель рефакторится или сам переводится в пакетную форму. Level 2 не создаёт скрытый механизм внедрения в старый модуль.