Как бороться с внешними серверами с сохранением состояния в DDD? - PullRequest
0 голосов
/ 28 января 2019

Сценарий # 1

  • Ситуация: мне нужно выполнить бизнес-операцию с некоторыми данными, которые находятся в веб-сервисе.
  • Решение: репозиторий использует веб-сервис в качестве репозитория, создаваяагрегат с данными веб-сервиса и сохранение изменений позже.
  • Сомнение: все в порядке?

Сценарий # 2

  • Ситуация: Iнеобходимо выполнить бизнес-операцию с некоторыми данными, которые находятся в моей базе данных, и такая операция включает в себя веб-сервис для вычисления значения.
  • Решение: веб-сервис абстрагируется как служба домена, поэтому он передается в совокупностьв качестве параметра для выполнения операции.
  • Сомнение: имеет ли это смысл?Я бы сказал, что веб-сервис должен быть частью репозитория, поэтому данные сохраняются вместе.

Сценарий # 3

  • Ситуация: запрос бизнес-операции / сохраняет данные из/ к двум различным базам данных, доступ к одной напрямую осуществляется через веб-сервис.
  • Решение: оба, соединение с базой данных и веб-сервис, находятся в репозитории и сохраняются вместе.Агрегат не знает об этом разделении.

Сценарий # 4 (проблемы начинаются ...)

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

Сценарий #n [много разных вариантов # 4] ...

Так что я не могу обдуматьчеткие критерии того, как использовать веб-сервисы в DDD, когда они вносят изменения в свое состояние.

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

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

Какой твердый критерий выбрать?

Ответы [ 2 ]

0 голосов
/ 28 января 2019

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

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

Saga запускается, а затем прослушивает изменения в домене, обычно подписываясь на события домена.Он реагирует на них, посылая команды в соответствующую конечную точку.Обратите внимание, что я использую термин «конечная точка» для обозначения любого получателя, который обрабатывает команды идемпотентным способом.Агрегаты, будучи чистыми, являются такими конечными точками.Но конечной точкой Saga может быть также внешняя система, такая как платежный шлюз.Такой шлюз не должен инициировать новый платеж с существующим PaymentID (непрозрачным полем, которое отправляет ваша система).

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

Вы можете прочитать больше о Sagas здесь и здесь и здесь .

0 голосов
/ 28 января 2019

Ответ заключается в следующем: Life Beyond Distributed Transactions .

Краткая форма состоит в том, что попытка надежно координировать записи в разных местах является дорогостоящей.В большинстве случаев лучше признать в своем дизайне, что вы не можете быть во всех местах одновременно, и инвестировать в устранение последствий этого факта.

...