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

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

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

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

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

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

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

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

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

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

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

В моей сфере много подобных сценариев.

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

Спасибо, Дэйв

Обновить

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

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

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


person David Masters    schedule 19.01.2010    source источник


Ответы (2)


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

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

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

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

person Theo Lenndorff    schedule 20.01.2010
comment
Вы правы, они не являются ни сущностями, ни объектами-ценностями. Думаю, на самом деле я спрашивал, где эти итоговые объекты поместятся в домене? Думаю, ответ таков: нет. Как вы говорите, они предназначены только для информационных целей - аналогично отображению информации в отчете; они не содержат никаких бизнес-правил. Кстати, это было интересное видео - удивлен, что раньше не встречал его :) Спасибо, Дэйв. - person David Masters; 20.01.2010
comment
Отличный ответ. Я столкнулся с той же проблемой, и ваш ответ был очень поучительным. - person Luiz Damim; 14.03.2012
comment
Репозитории никогда не предназначались для запросов: jefclaes.be /2014/01/repositories-where-did-we-go-wrong_26.html - person JefClaes; 28.01.2014
comment
Если ссылка на видео не работает, вот еще одна. - person Martin Klinke; 20.04.2016
comment
Спасибо @MartinKlinke. Обновил ссылку. - person Theo Lenndorff; 03.05.2016

Я мог бы:

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

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

person Jamie Ide    schedule 20.01.2010