Команда описывает процесс разными глаголами, но не может согласовать результат каждого шага. Как применить ...

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

Проходите собеседования с ИИ помощником Hintsage

Краткий ответ

Проведите сессию Event Storming: фиксируйте не действия исполнителей, а проверяемые факты, уже произошедшие в предметной области, например «Заявка одобрена» или «Платёж отклонён». Затем свяжите каждый факт с командой или правилом, которое его вызывает, и определите, кто владеет изменяемыми данными и бизнес-решением. Так границы ответственности выводятся из потока изменений и событий, а не из названий подразделений или экранов.

Исторический контекст

Event Storming появился как фасилитируемый способ быстро исследовать предметную область совместно с экспертами и технической командой. Подход решает проблему, при которой традиционные интервью дают разрозненные описания действий, но скрывают бизнес-факты, исключения и зависимости между участниками.

Его связь с Domain-Driven Design делает события удобной точкой согласования языка предметной области. Однако Event Storming не является готовой архитектурой: результаты сессии требуют последующей проверки и уточнения.

Постановка проблемы

Фраза «оператор обрабатывает заявку» не показывает, что именно изменилось, кто отвечает за решение и что должны увидеть другие участники. Разные подразделения могут использовать одно слово для разных состояний, а разные слова — для одного бизнес-факта.

Если границы ответственности определить по оргструктуре или интерфейсам, появятся дублирование правил, неясный владелец данных и постоянные согласования между командами. Ошибка особенно опасна там, где один процесс пересекает продажи, проверку риска и расчёты: формальная последовательность шагов ещё не означает корректного распределения ответственности.

Подробное решение

Сначала участники формулируют события в прошедшем времени: «Документ проверен», «Лимит превышен», «Договор подписан». Событие должно описывать значимый факт, который уже произошёл, а не намерение («проверить документ») и не техническую операцию («вызван метод»).

Далее для каждого события выясняют:

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

Граница ответственности обычно проходит там, где один согласованный контекст принимает решение и изменяет принадлежащие ему данные. Если событие «Риск одобрен» создаётся только модулем оценки риска, бизнес-правило одобрения относится к его ответственности. Сервис заявок может инициировать проверку и получить результат, но не должен незаметно дублировать правило оценки.

После первичной раскладки нужно сгруппировать события по устойчивым терминам, правилам и моделям данных. Эти группы могут подсказать bounded contexts, владельцев бизнес-возможностей или границы команд, но не должны автоматически превращаться в микросервисы: организационные, транзакционные и эксплуатационные ограничения проверяются отдельно.

Важно различать событие и состояние. «Заявка одобрена» — факт перехода, а «заявка находится в статусе одобрена» — текущее представление состояния. Событие может быть неизменяемым историческим фактом, тогда как состояние допускает обновление и требует ясного владельца.

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

Ситуация из практики

В компании процесс возврата товара описывали так: магазин «принимает возврат», склад «проверяет товар», финансовый отдел «возвращает деньги». На практике возникал спор: деньги иногда возвращались до решения склада, а повреждённый товар требовал отдельной проверки.

Рассматривались три варианта. Можно было распределить ответственность по подразделениям, но это закрепило бы текущую оргструктуру и не устранило спорные состояния. Можно было начать с экранов системы, однако это смешало бы пользовательский интерфейс с бизнес-правилами. Выбрали Event Storming с фиксацией событий: «Возврат зарегистрирован», «Товар принят на проверку», «Возврат одобрен», «Товар признан повреждённым», «Возврат денег инициирован».

После добавления исключений стало видно, что решение об одобрении возврата принадлежит контексту возвратов, а финансовый контекст отвечает за исполнение денежной операции после получения события «Возврат одобрен». Склад владеет результатом физической проверки, но не решает финансовый вопрос напрямую. Это устранило дублирование правил и позволило отдельно согласовать задержку между одобрением и фактическим возвратом денег.

Что кандидаты часто упускают

  1. Вопрос: Можно ли считать каждую найденную группу событий отдельным bounded context?

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

  1. Вопрос: Что делать, если одно событие хотят публиковать несколько подразделений?

Ответ: Сначала нужно проверить, действительно ли это один и тот же бизнес-факт. Возможно, совпадает название, но различаются условия, момент возникновения или значение для потребителей. Если факт един, следует определить одного владельца его порождения, а остальные подразделения должны реагировать на событие или предоставлять входные данные; если факты различны, их нужно переименовать и разделить.

  1. Вопрос: Почему нельзя строить границу ответственности только по месту хранения сущности?

Ответ: Хранение объекта не всегда означает владение бизнес-правилами его изменения. Например, карточка клиента может быть доступна нескольким контекстам, но каждый из них отвечает за разные аспекты: идентификацию, кредитный лимит или маркетинговое согласие. Границу следует определять по решениям и инвариантам, которые должен защищать владелец, а не только по таблице или документу.