16 KiB
Терминология SLM
Этот документ задаёт нормативный смысл терминов. Определения используются при толковании архитектуры и правил, но сами по себе не являются отдельными правилами.
Владение
SLM root
Граница структурной архитектуры одного приложения. Внутри неё определяются владельцы ответственностей, слои, модули и их зависимости.
Ответственность
Результат или поведение приложения, за которое отвечает один модуль-владелец. Ответственность является самостоятельной, когда ей нужны собственный публичный контракт, зависимости, состояние или область жизни, а не только внутренняя роль в работе другого модуля. Наличие у framework-сущности props, импортов, локального состояния или lifecycle-кода само по себе не создаёт самостоятельную ответственность.
Доменный сценарий
Продуктово значимое поведение, сформулированное в предметных терминах и приводящее к предметному результату. Его владелец определяет модели, правила, переходы, продуктовое состояние, смысл операций с продуктовыми данными, допустимые исходы и доменный UI. Количество потребителей, текущая страница и технический механизм выполнения не меняют принадлежность сценария.
Техническая возможность, которую сценарий получает через публичный API другого модуля, сохраняет собственного владельца. Например, infra может владеть HTTP-транспортом или доставкой телеметрии, но смысл продуктовой операции и доменного события остаётся у доменного сценария.
Доменный UI
UI-код, чьи данные, действия, состояния или исходы выражены в терминах одного домена и представляют либо запускают его сценарий. Доменный UI является частью реализации доменной ответственности даже тогда, когда используется только одной страницей. Универсальные визуальные элементы принадлежат ui, а размещение и связывание готовых доменных API в страницу или экран принадлежит compositions.
Владелец
Модуль, который определяет публичный API ответственности, её зависимости, состояние, область жизни и внутреннюю реализацию. Каждый файл принадлежит ближайшей модульной границе и реализует ответственность этого модуля. Место выполнения кода или вид framework-сущности не переносит владение.
Структурные сущности
Слой
Архитектурная роль кода внутри SLM root. Слой классифицирует владельцев по назначению и ограничивает допустимые направления зависимостей. Нормативные роли и матрица определены в разделе Слои.
Группа
Необязательный навигационный классификатор модулей внутри одного слоя или другой группы. Группа не является владельцем, публичным API или границей зависимостей.
Модуль
Минимальная самостоятельная архитектурная единица SLM. Модуль владеет одной связной ответственностью, имеет публичный API и физически размещается в отдельной папке.
Домен
Специализированный модуль слоя domains, владеющий одной связной предметной ответственностью и её сценариями. Домен самостоятельно определяет публичный доменный контракт, ожидаемые неуспешные исходы, продуктовое состояние, доменный UI и адаптацию внешних данных и ошибок. Он остаётся обычным узлом модульного графа, подчиняется всем правилам модулей и не создаёт дополнительный контейнерный уровень.
Сегмент
Необязательная внутренняя часть одного модуля, группирующая его содержимое по назначению. Сегмент не является владельцем, публичным API или границей зависимостей.
Вложенный модуль
Обычный модуль, физически размещённый внутри родительского модуля. Он владеет отдельно сформулированной связной частью ответственности родителя, имеет публичный API и собственную границу зависимостей. Родитель владеет общим результатом, а вложенный модуль — выделенной подответственностью; одна и та же ответственность не получает двух владельцев.
Для кода за пределами родительской границы вложенный модуль остаётся внутренней реализацией родителя. Внутри вложенного модуля снова действуют все правила обычного модуля, поэтому рекурсивная структурная вложенность создаётся только модульными границами.
Публичная граница
Публичный API
Единый логический контракт внешнего доступа к модулю. Он скрывает внутреннюю реализацию и физически представлен обязательным фасетом index и только необходимыми фасетами client, browser и server.
Доменный контракт
Принадлежащая домену предметная форма его публичного API: принимаемые значения, возвращаемые модели и результаты, события, доступные потребителям состояния и ожидаемые неуспешные исходы. Доменный контракт определяется смыслом сценариев и не выводится из DTO, схемы, SDK или типов источника данных.
Фасет
Объявленная публичная точка входа модуля, открывающая часть его единого API для определённой среды выполнения. Импорт фасета не является глубоким импортом; любой другой внешний путь внутрь модуля остаётся внутренним.
Глубокий импорт
Импорт или реэкспорт внутреннего пути чужого модуля, который не объявлен его публичным фасетом.
Граница источника данных
Контракт источника
Техническая форма обмена с внешним сервисом, SDK, storage или другим источником данных. К ней относятся request и response DTO, source-specific enum, nullable semantics, статусы, payload и типы ошибок. Контракт источника не является доменным контрактом даже при полном структурном совпадении.
DTO
Значение или тип контракта источника, предназначенный для передачи данных через техническую границу. DTO допускается во внутреннем интеграционном коде домена, но не используется как публичная модель, продуктовое состояние или значение доменного UI.
Mapper
Один из возможных внутренних механизмов адаптации источника: функция или связный набор функций, преобразующий контракт источника в доменный контракт либо доменное значение в контракт запроса. Адаптация принадлежит доменному владельцу, но SLM не требует использовать mapper как конкретный паттерн, имя или файловую единицу.
Доменные ошибки
Доменная ошибка
Ожидаемый неуспешный исход доменного сценария, смысл и публичный контракт которого определены текущим доменом. Способ представления и передачи такого исхода, включая exception, Result, union или другую форму, SLM не устанавливает.
Доменная ошибка не является технической ошибкой источника. Чужой тип ошибки, source code, message, transport status, raw payload, cause и диагностические данные не входят в доменный контракт в исходной форме.
Реализация домена создаёт только исходы, объявленные доменным контрактом. Интеграционный или framework-код использует эту декларацию и не становится отдельным владельцем ошибок.
Runtime-идентификация доменной ошибки
Публичная capability, позволяющая реальному потребителю отличить доменную ошибку от другого runtime-значения. Она может быть реализована constructor-ом, marker-ом, guard-ом, parser-ом, schema или иным способом, подходящим среде потребителя. SLM не требует такую capability для каждого домена и не устанавливает её форму.
Неожиданный дефект
Неуспешное выполнение, которое не объявлено ожидаемым исходом доменного сценария и обрабатывается согласно общей политике приложения. Способ доставки и диагностики дефекта SLM не устанавливает, но техническая ошибка чужого источника не становится частью публичного API домена в исходной форме.
Зависимости
Зависимость
Направленная статическая связь между архитектурными границами внутри одного SLM root. Обычный импорт, импорт типа (import type) и реэкспорт одинаково создают архитектурную зависимость.
Зависимость внутреннего файла или сегмента относится к ближайшему модулю-владельцу. Вложенный модуль начинает собственную границу зависимостей.
Нормативная матрица слоёв
Отношение допустимой зависимости между слоями одного SLM root. Матрица определяет доступные целевые роли, но не требует проходить через каждый промежуточный слой.
Жизненный цикл
Область жизни
Период, в течение которого принадлежащие модулю состояние или долгоживущий ресурс должны оставаться активными.
Ресурс жизненного цикла
Ресурс, работа которого продолжается после первоначального вызова и требует остановки, отмены, отписки или освобождения. Например, подписка, обработчик событий, таймер, наблюдатель, запрос или соединение.
Очистка
Гарантированное прекращение работы ресурса не позже завершения его области жизни. Автоматическая очистка фреймворка считается очисткой владельца, если модуль устанавливает и контролирует соответствующую границу.
Немодульные единицы
Точка входа фреймворка
Специальная немодульная единица слоя app, которая запускает приложение, объявляет точку маршрута, преобразует внешние входные данные или подключает готовые публичные API.
Ресурс shared
Небольшая детерминированная единица слоя shared, не зависящая от продукта и не скрывающая отдельного внутреннего устройства. У неё нет изменяемого состояния, ввода-вывода, области жизни или собственного публичного API.
Путь и имя сами по себе не определяют ни одну из перечисленных сущностей. Физическое сопоставление задаётся стайлгайдом или конфигурацией проверки после определения ответственности и владельца.