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

StackOverflow https://stackoverflow.com/questions/2098112

Вопрос

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

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

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

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

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

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

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

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

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

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

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

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

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

Обновить

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

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

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

Это было полезно?

Решение

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

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

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

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

Другие советы

Я бы так и сделал:

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top