У меня есть вопрос относительно DDD и шаблона репозитория.
Скажите, что у меня есть Клиентский репозиторий для Клиентского корня агрегата. Получение и Находит, что методы возвращают полностью заполненный агрегат, который включает объекты как Адрес, и т.д. Вся польза. Но когда пользователь ищет клиента в UI, я просто требую 'сводки' агрегата - просто плоский объект с обобщенной информацией.
Одним путем я мог иметь дело с этим, должен назвать метод находки на репозитории как нормальный, и затем на прикладном уровне, отобразить каждый клиентский агрегат на CustomerSearchResult / CustomerInfo DTO и передать их обратно клиенту.
Но моей проблемой с этим является производительность; каждый Клиентский агрегат может потребовать, чтобы несколько запросов заполнили все ассоциации. Таким образом, если мои критерии поиска соответствовали 50 клиентам, это - настоящий хит на DB для того, чтобы потенциально получить данные, в которых я даже не испытываю необходимость.
Другая проблема - то, что я могу хотеть включать сводные данные о клиенте, который является за пределами совокупной корневой границы Клиента, такой как дата последнего порядка, сделанного, например. Порядок имеет свой собственный агрегат и поэтому получить информацию для заказа клиента, которую я должен был бы назвать OrderRepository, также ухудшающаяся производительность.
Таким образом, теперь я думаю, что меня оставляют с двумя опциями:
Добавьте дополнительный метод Находки к CustomerRepository, который возвращает список этих сводных объектов путем выполнения одного эффективного запроса.
Создайте цель, созданную CustomerInfoRepository только для чтения, который просто имеет метод находки, описанный в 1.
Но оба из них чувствуют, что я иду вразрез с принципами DDD. Мои репозитории наследовались универсальной основе: Репозиторий, где T: IAggregateRoot. Они сводный информационный объект не является агрегатами и имеет другой тип к T, поэтому действительно № 1 идет вразрез с дизайном.
Возможно, для № 2 я создал бы абстрактный SearchRepository без ограничения IAggregateRoot?
В моем домене существует много подобных сценариев.
Как Вы реализовали бы этот сценарий?
Спасибо, Dave
Обновление
После чтения ответа Theo я думаю, что пойду с опцией № 2 и создам специализированный SearchRepository в своей инфраструктуре, приспособленной к этим сценариям. Прикладной уровень (сервисы WCF) может затем назвать эти репозитории, которые просто заполняют сводный DTOs непосредственно, а не объекты области значений отображения к DTOs.
**** Обновите 2 ****
Хотя я спросил это более чем год назад, я думал, что просто добавлю, что я с тех пор обнаружил CQRS, который нацелен на решение этой точной проблемы. Udi Dahan (http://www.udidahan.com/) и Greg Young (http://codebetter.com/gregyoung/) записали много об этом. При создании распределенного приложения с DDD CQRS для Вас!
Его начало, он может перечислить:
models = Dir.new("#{RAILS_ROOT}/app/models").entries
Глядя еще...
-121--2012847-При создании собственных потоков (не потоков BackgroundWorker или ThreadPool) можно передать метод обратного вызова из основного потока, вызываемого из рабочего потока. Это также позволяет передавать аргументы в обратный вызов и даже возвращать значение (например, флаг перехода/отказа). При обратном вызове вы обновляете пользовательский интерфейс через диспетчер целевого элемента управления:
public void UpdateUI(object arg)
{
controlToUpdate.Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Normal
, new System.Windows.Threading.DispatcherOperationCallback(delegate
{
controToUpdate.property = arg;
return null;
}), null);
}
}
-121--4213547- Я думаю, что вы хотите отобразить только сводную информацию. Эти биты обобщенной информации не являются сущностями или ценностными объектами модели домена. Это только информация, не более того.
Это что-то вроде отображения отчетной информации. Если бы я занимался такими вещами, я бы не придерживался чистого подхода DDD. Предлагаемые варианты в порядке, потому что ваша работа завершается. DDD не следует рассматривать как догму. Думай вне коробки. Ослабьте немного DDD.
Но имейте в виду, что вы просто создаете информационные значения вне модели для целей отображения. Таким образом, если пользователь выбирает один бит информации для выполнения какой-либо операции с ней (которая определена в модели домена), необходимо извлечь идентификатор из информационных значений и извлечь объект сущности/значения/агрегат из репозитория.
Я настоятельно рекомендую это видео: Эрик Эванс: Что я узнал о DDD со времени книги . Если вы читаете его книгу, вы действительно должны увидеть все видео. Обратите очень пристальное внимание примерно в 30:00, где Эрик Эванс сам говорит об агрегатах и ссылается на проблему, которая у вас в настоящее время есть.
Я бы:
Если T в вашем универсальном базовом репозитории является клиентом, то я думаю, что вы неправильно применяете концепцию совокупных корней, хотя я не строго EvansangeList . Я бы разработал репозиторий для клиента, который вернул любые данные, которые логически или комфортно группируют с клиентом, включая объекты источников данных или только для чтения, которые являются представлениями данных о клиентах.