DDD для аналитика без культа терминов

Зачем аналитику DDD, как bounded context и ubiquitous language помогают проектированию и почему доменная модель важнее терминов

DDD легко испортить двумя способами. Первый — превратить его в технический культ, где все обсуждают aggregates, entities и bounded contexts, но почти не связывают это с реальной системой. Второй — решить, что это вообще “история для архитекторов и разработчиков”, а аналитике достаточно бизнес-требований, процессов и glossary.

На практике обе крайности одинаково вредны. Если DDD превращается в набор терминов, он перестаёт помогать проектированию. Если аналитика игнорирует доменную модель, архитектура получает слишком позднюю и слишком техническую картину предметной области. В результате границы контекстов определяются не смыслом системы, а удобством текущей реализации или историей оргструктуры.

Поэтому полезно смотреть на DDD спокойно: не как на религию и не как на специфическую технику проектирования “только для сложного enterprise”, а как на способ точнее видеть домен и раньше замечать, где предметная область сама начинает подсказывать архитектурные границы.

В прошлой статье мы отбирали архитектурные драйверы. Теперь следующий вопрос: какая доменная модель выдержит эти ограничения? Продолжим серию на примере лунной базы и разберём, чем DDD действительно полезен аналитику, если убрать лишний пафос и сосредоточиться на вопросе: как сделать так, чтобы доменная модель помогала архитектуре, разработке и эксплуатации говорить на одном языке.

Карта лунной базы, разделённая на смысловые контексты

В статье

Зачем аналитику вообще нужен DDD

Аналитику DDD нужен не для того, чтобы уверенно произносить aggregate, entity или anti-corruption layer. Эти термины пригодятся позже, но не с них начинается польза DDD. Он нужен, чтобы раньше видеть:

  • где разные участники системы говорят об одном и том же разными словами;
  • где одно слово скрывает несколько разных смыслов;
  • где “единая модель” на самом деле натягивает друг на друга несовместимые процессы;
  • где границы ответственности в домене не совпадают с тем, как система сейчас организована технически.

Хорошая доменная модель нужна не только разработке. Она нужна всей системе принятия решений:

  • аналитике — чтобы не писать требования к “средней температуре по больнице”;
  • архитектуре — чтобы не строить границы сервисов поверх терминологической каши;
  • разработке — чтобы не компенсировать неясность домена техническими костылями;
  • инженерам домена и эксплуатации — чтобы не обнаружить позже, что система красиво автоматизирует неправильную картину реальности.

Почему доменная модель важнее терминов

DDD очень легко начать воспринимать как словарь правильных понятий. Но проблема почти никогда не в том, знает ли команда термин bounded context. Проблема в том, различает ли команда:

  • запас как “общее количество”;
  • резерв как “недоступное к обычному распределению количество”;
  • критичный резерв как ресурс, который нельзя тратить теми же правилами, что остальные;
  • телеметрию как поток сигналов;
  • операционное состояние как данные для принятия решения;
  • команду как намерение;
  • действие как факт исполнения.

Если эти различия не проговорены, язык проекта начинает врать. А когда язык проекта врёт, архитектура рано или поздно начинает закреплять эту ошибку в схемах, API и данных.

Поэтому доменная модель полезна не как набор сущностей для ER-диаграммы, а как способ удержать различия, которые для системы реально важны.

Вернёмся к сквозному сценарию серии: связь с Землёй пропала на 40 минут, а энергобюджет просел. Именно в такой момент дороже всего обходится, если одно слово в разных контурах значит разное. Посмотрите, как расходится смысл одних и тех же терминов:

Термин Жизнеобеспечение Логистика Энергетика Наземное планирование
«резерв» неприкосновенный запас воздуха/воды на аварию складской буфер под будущий расход зарезервированная мощность под пик страховой объём, заложенный в прогноз поставок
«состояние базы» параметры в пределах порогов остатки и движение запасов баланс генерации и потребления сводный прогноз по всей базе
«критично» угроза жизни прямо сейчас риск исчерпать запас к сроку риск отключения нагрузок срыв долгосрочного плана миссии

Если в сценарии просадки энергии наземный контур под «резервом» понимает страховой объём поставок, а жизнеобеспечение — неприкосновенный аварийный запас, то одно и то же решение «израсходовать резерв» будет означать диаметрально разное. Доменная модель нужна ровно затем, чтобы такие расхождения были видны до того, как они закрепятся в API и данных.

Ubiquitous language: где он рождается и почему без него всё расползается

Ubiquitous language часто описывают слишком академично. На практике это просто рабочий общий язык, на котором:

  • аналитика пишет требования;
  • архитекторы обсуждают границы;
  • разработка проектирует API и модели;
  • инженеры домена подтверждают, что система отражает реальность, а не только внутреннюю логику команды.

Проблема в том, что без такого языка каждая роль быстро начинает использовать свои локальные слова.

В кейсе лунной базы это может выглядеть так:

  • аналитика говорит “ресурс”;
  • логистика говорит “запас”;
  • инженеры жизнеобеспечения говорят “резерв”;
  • архитектура рисует inventory service;
  • разработка делает resources table;
  • эксплуатация называет всё это “критическими материалами”.

Формально все как будто говорят об одном. Практически — уже нет.

Ubiquitous language полезен именно тем, что заставляет сделать эти различия явными достаточно рано.

Минимальный рабочий метод для аналитика, как его собирать:

  1. Выписать термины из интервью и документов — буквально как их произносят люди.
  2. Отметить спорные — те, вокруг которых возникает «подождите, вы о чём».
  3. Найти слова с несколькими смыслами — один термин, за которым стоят разные понятия.
  4. Привязать термины к сценариям — где именно слово используется и что от него зависит.
  5. Согласовать glossary не глобально, а по контекстам — не «один словарь на всё», а свой согласованный язык внутри каждого контекста.

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

Bounded context: не про коробки, а про границы смысла

Одно из самых полезных последствий DDD — понимание, что одна и та же сущность в разных частях системы может значить разное.

Не потому, что команда ошиблась, а потому, что система действительно состоит из разных смысловых областей.

Важный момент: bounded context — это не “будущий сервис” и не “ещё одна коробка на диаграмме”. Это прежде всего граница, внутри которой язык и модель остаются согласованными.

Когда команда начинает рисовать контексты как будущие сервисы слишком рано, DDD быстро вырождается в другой способ делать преждевременную декомпозицию. Гораздо полезнее сначала понять:

  • где начинается разный смысл;
  • где одинаковые термины начинают вести себя по-разному;
  • где разные команды и процессы реально смотрят на домен под разными углами.

Только потом уже можно обсуждать, станут ли эти границы сервисами, модулями или просто отдельными частями общей модели.

Лунная база: какие контексты там естественны

В кейсе лунной базы довольно быстро можно увидеть несколько естественных контекстов. Это именно bounded contexts, а не просто разделы системы, по трём признакам: внутри каждого свой язык (одни и те же слова значат разное), свои правила (что допустимо и что критично) и свой владелец решений (кто отвечает за домен). Где меняется хотя бы одно из трёх — там и проходит граница смысла.

Жизнеобеспечение

Здесь важны:

  • состояние воздуха, воды, давления, температуры;
  • критичные пороги;
  • деградационные режимы;
  • приоритет безопасности над экономией.

Почему граница смысла: свой язык порогов и аварий, правило «безопасность важнее экономии», владелец — инженеры жизнеобеспечения.

Энергетика

Здесь другой язык:

  • генерация;
  • накопление;
  • распределение;
  • приоритеты потребителей;
  • резервные режимы.

Почему граница смысла: язык баланса и приоритетов потребления, правила распределения мощности, владелец — энергетики; «резерв» здесь — мощность, а не запас.

Логистика и ресурсы

Здесь начинают жить:

  • запасы;
  • расход;
  • пополнение;
  • резервирование;
  • критичность ресурса;
  • планирование поставок и перераспределения.

Почему граница смысла: язык запасов и движения ресурсов, правила резервирования и пополнения, владелец — логистика; «резерв» здесь — складской буфер.

Робототехника и внешние операции

Тут уже важны:

  • задания;
  • маршруты;
  • подтверждения;
  • связь;
  • локальная автономность;
  • ограничения окружающей среды.

Почему граница смысла: язык заданий и маршрутов, правила подтверждения и автономного исполнения, владелец — операторы внешних операций.

Наземный контур планирования

А здесь появляется другой смысл:

  • прогноз;
  • долгий горизонт планирования;
  • координация поставок;
  • аналитика по всей базе;
  • компромиссы между локальной автономией и глобальной оптимизацией.

Почему граница смысла: язык прогноза и долгого горизонта, правила глобальной оптимизации, владелец — наземное планирование; «состояние базы» здесь — сводный прогноз, а не текущие пороги.

Важно, что слово “состояние базы” внутри этих контекстов может означать разные вещи. И именно здесь bounded context начинает помогать, а не просто украшать разговор.

flowchart TD A["Лунная база"] --> B["Жизнеобеспечение"] A --> C["Энергетика"] A --> D["Логистика ресурсов"] A --> E["Робототехника"] A --> F["Наземное планирование"] B --> G["Безопасность и пороги"] C --> H["Баланс и приоритеты"] D --> I["Запасы, резервы, пополнение"] E --> J["Задания, маршруты, подтверждения"] F --> K["Прогноз, координация, аналитика"]

flowchart TD
  A["Лунная база"] --> B["Жизнеобеспечение"]
  A --> C["Энергетика"]
  A --> D["Логистика ресурсов"]
  A --> E["Робототехника"]
  A --> F["Наземное планирование"]

  B --> G["Безопасность и пороги"]
  C --> H["Баланс и приоритеты"]
  D --> I["Запасы, резервы, пополнение"]
  E --> J["Задания, маршруты, подтверждения"]
  F --> K["Прогноз, координация, аналитика"]
Лунная база: разные контексты, разные смыслы

Контекстная карта: контексты обмениваются смыслом

Контексты не существуют изолированно — они отдают друг другу не «таблицы», а согласованные понятия. Даже без формальных DDD-паттернов полезно увидеть, что именно один контекст передаёт другому:

  • логистика отдаёт «план поставок и пополнения»;
  • жизнеобеспечение отдаёт «критичные резервы и пороги»;
  • энергетика отдаёт «лимиты потребления»;
  • наземное планирование собирает это в «прогноз и координацию по всей базе».
flowchart LR L["Логистика"] -->|план поставок| P["Наземное планирование"] J["Жизнеобеспечение"] -->|критичные резервы и пороги| P E["Энергетика"] -->|лимиты потребления| P P -->|прогноз и приоритеты| L

flowchart LR
  L["Логистика"] -->|план поставок| P["Наземное планирование"]
  J["Жизнеобеспечение"] -->|критичные резервы и пороги| P
  E["Энергетика"] -->|лимиты потребления| P
  P -->|прогноз и приоритеты| L
Контекстная карта: что контексты передают друг другу

Важная деталь: на границе контекстов один и тот же объект переводится, а не просто копируется. «Резерв» логистики, попадая в наземное планирование, превращается во вход (показатель) прогноза, а не остаётся складским буфером. Где этот перевод не сделан явно — там и рождаются самые дорогие рассогласования.

Где аналитика помогает DDD, а где может его испортить

Аналитика очень полезна для DDD, когда:

  • рано фиксирует различия в языке;
  • помогает отделять похожие, но не тождественные понятия;
  • не пытается свести разные контексты к “единому универсальному словарю”;
  • удерживает связь между процессами, требованиями и моделью;
  • приносит в обсуждение реальный эксплуатационный смысл терминов.

Но аналитика же легко может DDD и испортить, если:

  • стремится слишком быстро сделать “единую нормализованную модель на всё”;
  • считает разницу в терминах чисто редакционной проблемой;
  • выравнивает язык так, что из него исчезают реальные смысловые различия;
  • смешивает пожелание к удобству документации с реальной структурой домена.

Хорошая аналитика здесь не упрощает домен искусственно, а делает его различия видимыми и управляемыми.

Короткий checklist перед разметкой доменной модели

Перед тем как рисовать bounded contexts или спорить о модели, полезно проверить:

  1. Какие термины команда использует одинаково, но подразумевает под ними разное?
  2. Где один и тот же объект живёт в разных процессах с разным смыслом?
  3. Какие различия в языке реально влияют на требования и архитектуру?
  4. Где команда пытается создать “единый словарь” ценой потери важных доменных различий?
  5. Какие контексты действительно естественны для системы, а какие пока появились только из удобства текущей оргструктуры?
  6. Какие части модели особенно важны для автономности, безопасности и деградации?
  7. Какие понятия пересекают границы контекстов и требуют явного перевода?
  8. Что в доменной модели уже сейчас должен подтвердить инженер домена, а не только аналитик или разработчик?

Если эти вопросы не пройдены, то дальше очень легко получить красивую схему с неверной картиной реальности.

Что дальше

Мы разобрали, как доменная модель удерживает важные различия. Дальше посмотрим, что происходит, когда модель выбрана неверно: как доменная модель ломает и спасает архитектуру — про то, как ошибка в модели расходится по API, данным и границам системы, и как правильная модель, наоборот, спасает архитектуру.

Обсуждение в Telegram

Присоединиться →

Комментарии