#rest #domain-driven-design
#rest #дизайн, управляемый доменом
Вопрос:
У нас есть (примерно) следующая архитектура:
- Служба приложений выполняет инфраструктурную работу — извлекает данные из репозиториев, которые скрыты за интерфейсами.
- Создается граф объектов и передается соответствующей службе домена.
- Служба домена выполняет это и вызывает соответствующие события.
- События обрабатываются в различных службах приложений, которые выполняют некоторые постоянные операции (изменение репозиториев, отправка электронных писем и т.д.).
Однако. Доменная служба (3) стала настолько сложной, что ей требуются данные из разных внешних API только в том случае, если выполняются определенные условия. Например, если продукт X относится к типу Car, нам нужно узнать цену на эту модель автомобиля из какого-либо внешнего CatalogService (пример изобретен), скрытого за ICatalogService. Эта операция является потенциально дорогостоящей (вызов REST).
Как нам это сделать?
A. Выполняем ли мы предварительную выборку всех данных в службе приложений, перечисленных как (1), даже если они нам могут не понадобиться? Внедряем ли мы интерфейс ICatalogService в данную доменную службу и извлекаем ли данные только при необходимости? Последнее решение может создать проблемы с производительностью, если какой-либо другой клиент доменной службы повторно вызывает эту доменную службу, не зная, что внутри нее скрыт вызов REST.
Или мы просто неправильно определили модель предметной области?
Этот вопрос связан с дизайном, управляемым доменом.
Ответ №1:
Как нам это сделать?
Существует два распространенных шаблона.
Один из них заключается в передаче возможности выполнения запроса в модель предметной области, позволяя модели самой извлекать информацию, когда это необходимо. Обычно это будет выглядеть как определение интерфейса / контракта, который будет использоваться моделью предметной области, но реализован на уровнях приложения / инфраструктуры.
Другой способ заключается в расширении протокола между моделью предметной области и приложением, чтобы мы могли сообщать прикладному уровню, какая информация необходима, а затем код приложения может решить, как ее предоставить. В итоге получается что-то вроде конечного автомата для процессов, при этом код приложения координирует обмен информацией между внешним API и моделью предметной области.
Если вы проявите немного воображения, у вас уже есть конечный автомат примерно такого типа; поскольку код вашего приложения уже координирует перемещение входных данных в репозиторий и модель предметной области. Разница, конечно, в том, что существующий «конечный автомат» достаточно прост и линейен, так что может быть неочевидно, что конечный автомат вообще присутствует.
как именно вы бы сигнализировали о прикладном уровне?
Простые запросы; иными словами, код приложения извлекает необходимую ему информацию из модели предметной области и использует эту информацию для вычисления следующего действия. Когда действие завершено, код приложения отправляет информацию в модель предметной области.
Комментарии:
1. В настоящее время мы используем подход с возможностью. Мне любопытно узнать о 2-м подходе, как именно вы бы сигнализировали о прикладном уровне?
Ответ №2:
Недостаточно информации, чтобы дать вам целевой хороший совет. Я подозреваю, что вам нужно реорганизовать ваши домены на дополнительные поддомены. Похоже, что на вашу доменную службу возложено гораздо больше ответственности, чем на 1. Упростите обслуживание.
Кроме того, если у вас есть длительно выполняющаяся задача, такая как вызов службы, которая занимает много времени, вам нужно ее спроектировать. Самый гибкий дизайн не заставит потребителя ждать. Он немедленно вернется пользователю с каким-либо результатом, даже если это просто периодическое обновление статуса.