Подтвердить что ты не робот

DDD - Как реализовать высокопроизводительные репозитории для поиска

У меня есть вопрос относительно DDD и шаблона репозитория.

Скажем, у меня есть репозиторий клиента для корневого агрегата Customer. Методы Get и Find возвращают полностью заполненный агрегат, который включает в себя такие объекты, как Address и т.д. Все хорошо. Но когда пользователь ищет клиента в пользовательском интерфейсе, мне просто требуется "сводка" совокупности - просто плоский объект с суммированной информацией.

Одним из способов решения этой проблемы является вызов метода find в репозитории как обычно, а затем на уровне приложения, сопоставление каждого агрегата клиента с DTO CustomerSearchResult/CustomerInfo и отправка их обратно клиенту.

Но моя проблема с этим - производительность; каждому агрегатору клиента может потребоваться несколько запросов для заполнения всех ассоциаций. Поэтому, если мои критерии поиска совпадают с 50 клиентами, это довольно удачное попадание в БД для потенциального извлечения данных, мне даже не понадобится.

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

Итак, теперь я думаю, что у меня остались два варианта:

  • Добавьте дополнительный метод поиска в CustomerRepository, который возвращает список этих итоговых объектов, выполнив один эффективный запрос.

  • Создайте специально созданный readonly CustomerInfoRepository, который просто имеет метод find, описанный в 1.

Но оба они чувствуют, что я иду против принципов DDD. Мои репозитории наследуются от общей базы: репозиторий, где T: IAggregateRoot. Этот итоговый информационный объект не является агрегатом и имеет тип T, поэтому действительно # 1 идет против дизайна.

Возможно, для # 2 я бы создал абстрактный SearchRepository без ограничения IAggregateRoot?

В моем домене много похожих сценариев.

Как бы вы реализовали этот сценарий?

Спасибо, Dave

Обновление

После прочтения ответа Тео, я думаю, что я поеду с вариантом №2 и создаю специализированный SearchRepository в своей инфраструктуре, ориентированной на эти сценарии. Затем прикладной уровень (службы WCF) может вызывать эти репозитории, которые просто заполняют сводные DTO напрямую, а не отображают сущности домена в DTO.

**** Обновление 2 ****

Хотя я спросил об этом год назад, я подумал, что просто добавлю, что с тех пор я обнаружил CQRS, целью которого является решение этой точной проблемы. Udi Dahan (http://www.udidahan.com/) и Грег Янг (http://codebetter.com/gregyoung/) много писали об этом. Если вы создаете распределенное приложение с DDD, CQRS для вас!

4b9b3361

Ответ 1

Я думаю, что вы хотите отображать только обобщенную информацию. Эти биты обобщенной информации не являются объектами или объектами ценности модели домена. Это только информация, не более того.

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

Но имейте в виду, что вы просто создаете информационные значения вне модели для отображения цели. Поэтому, если пользователь выбирает один бит информации для выполнения какой-либо операции с ним (которая определена в модели домена), вам нужно извлечь идентификатор из информационных значений и вытащить объект/совокупность объектов/значений из репозитория.

Я настоятельно рекомендую это видео: Эрик Эванс: То, что я узнал о DDD, начиная с книги. Если вы прочитаете его книгу, вы действительно должны увидеть все видео. Обратите особое внимание примерно на 30:00, когда сам Эрик Эванс говорит об агрегатах и ​​ссылается на проблему, которую вы в настоящее время имеете.

Ответ 2

Я бы:

  • Возвращает другой объект, представляющий представление моего объекта для отображения, например. CustomerInfo.
  • Возвращает DataTable. Часто общий контейнер является самым простым и лучшим способом.

Если T в вашем общем базовом репозитории является Клиентом, тогда я думаю, что вы неправильно применяете понятие совокупных корней, хотя я не строго Evansangelist. Я бы разработал репозиторий для Клиента, который возвращал любые данные, которые логически или удобно группирует с Клиентом, включая DataTables или объекты только для чтения, которые являются представлениями данных Клиента.