Команда Event Sourcing или событие из внешней системы?

В большинстве случаев я понимаю разницу между командой и событием в системе CQRS+ES. Однако есть одна ситуация, которую я не могу понять.

Предположим, я создаю систему отслеживания личных финансов, в которой пользователь может вводить дебеты/кредиты. Понятно, что это команды, и после их проверки модель предметной области обновляется и событие публикуется. Однако предположим, что информация о кредите/дебете также поступает непосредственно из внешних систем, т.е. флорист пользователя отправляет сообщение о том, что он снял с кредитной карты пользователя деньги за регулярную доставку ко Дню матери. В этом случае сообщение выглядит как событие (списание уже произошло), но возможно, что сообщение искажено и будет отклонено. Так это действительно команда? Но тогда должен быть способ отправить ACK/NACK, что здесь не так (флорист отправляет сообщение только после того, как узнает, что дебетование состоялось).

РЕДАКТИРОВАТЬ: Просто чтобы уточнить, я не говорю о том, что внешняя система знает что-либо о моих событиях и/или командах. У меня есть компонент, который получает данные из внешней системы, а затем должен опубликовать событие или отправить команду. Вопрос в том, какое событие или команду должен использовать мой компонент?


person Akash    schedule 09.08.2012    source источник


Ответы (2)


Это прекрасный пример ограниченных контекстов.

Событие, произошедшее в другой системе (или ограниченном контексте), представляющей тот же самый или шаг бизнес-процесса, не должно рассматриваться как событие, произошедшее в принимающей системе.

Событие Дебета в системе Флорист может иметь структуру, отличную от события Дебета, которое могло бы произойти в Системе отслеживания финансов.

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

В данном конкретном случае приходит событие из системы Florist с информацией о транзакции, которая произошла в системе Florist (ограниченный контекст). Я бы не стал принимать какие-либо решения в службе домена, а отдал бы команду домену Системы финансового отслеживания, где принимается решение, и могут генерироваться события Системы финансового отслеживания. Если системное событие Флориста отображается в Системе отслеживания финансов неправильно, вы, вероятно, не хотите сообщать об этом системе Флориста в форме Запрос/Ответ или Подтверждение/Отказ. Мероприятие было опубликовано из Флориста, и вы нарушили бы шаблоны обмена сообщениями, если бы реализовали что-то подобное. Ваша инфраструктура обмена сообщениями должна позволять вам повторно отправить сообщение или даже исправить код получения и повторить отправку сообщения с новым кодом.

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

В случае, когда вы описываете, что Система отслеживания финансов — это скорее журнал транзакций, и единственное, что вам нужно сделать, это не рассматривать события Флориста как события Системы отслеживания финансов. Поместите что-то среднее между командами, которые приводят к событиям системы финансового отслеживания.

РЕДАКТИРОВАТЬ:

В ответ на ваше редактирование. Принимающий компонент должен отправлять команды в домен системы отслеживания финансов, который, в свою очередь, будет генерировать события (как обычно).

person Mikael Östberg    schedule 10.08.2012
comment
Спасибо Микаэль, это отличный ответ. Ограниченные контексты — это то, чего мне не хватало. - person Akash; 11.08.2012

Я нашел этот вопрос, задаваясь вопросом о том же.

Мне понравился ответ Микаэля, и я проголосовал за него. Тем не менее, я нашел другой ответ на форуме DDD/CQRS, который использует другой подход, поэтому решил опубликовать его здесь для других, которые тоже ищут.

Цитата Грега Янга по похожему вопросу об отслеживании внешних государство:

В большинстве систем инвентаризации нет команд.

Или перефразируя:

Системы, которые исключительно отслеживают внешнее состояние, не будут иметь команд.

Давайте отмотаем назад и подумаем, как ваша система может развиваться на основе этой идеи (давайте также предположим, что вы строите ее не для себя):

  • Вы решаете создать личный финансовый трекер, который записывает транзакции из внешнего мира, отображает графики, агрегированные итоги и т.д.
  • Поскольку события предназначены для отслеживания изменений состояния, а не команд, вы записываете их. Вы также пишете прогнозы в обработчиках событий для агрегирования событий в итоги и графические точки данных.
  • Тогда вы получите пользователей. Они хвалят приложение, но использование по-прежнему низкое. Копнув глубже, вы обнаружите, что они все еще используют другие приложения для отслеживания финансов, когда, скажем, нет API для локального магазина карт для повторяющихся открыток ко Дню матери, они хотят «разбить» внешнюю транзакцию на несколько, их банк не имеет онлайн-сервиса. доступ, они хотят отслеживать денежные средства и т. д.
  • Таким образом, вы добавляете введенные пользователем транзакции. Вы делаете это, добавляя команды, которые отслеживают транзакции, введенные пользователем. Теперь мы в той же системе, что и ваш вопрос.

Обратите внимание, что этот вариант принимает как команды, так и события. Вы не станете возвращаться назад и преобразовывать все существующие события в команды только потому, что теперь вы позволяете пользователю что-то менять. Вместо этого у вас есть система, которая принимает внешние события транзакций, команды для транзакций, введенных пользователем, и исправления транзакций (которые создают события, изменяющие внутреннее состояние), а также прогнозы для объединения этих внутренних и внешних событий для отображения в приложение.

Хотя мне любопытно. Оглядываясь назад, оказался ли принятый ответ хорошим подходом? Или было бы лучше записывать и обрабатывать события от Флориста напрямую, как предлагает Грег?

person Joe    schedule 24.09.2016