В DDD, как вы работаете с несколькими репозиториями для списков только для чтения

Что вы делаете, если вам нужно создать список данных только для чтения на странице, и эти данные, естественно, будут поступать из нескольких, потенциально 5 или более разных репозиториев?

Мы используем DDD и форсируем доступ к нашей базе данных через репозитории, но есть сценарий, который не подходит для DDD, и мы пытаемся выбрать лучший шаблон для использования.

Например, предположим, что у вас есть веб-сайт сообщества с видео, форумами, блогами и т. д. У вас есть страница форума со списком комментариев. Это грубо, но я надеюсь, что это имеет смысл.

<table>
<tr><td>User Name (with possible link)</td><td>User's community score.</td><td>User Avatar</td><td>User's E-mail</td><td>User's blog</td><td>User's videos</td></tr>
</table>
<table>
<tr><td>This is a comment.</td></tr>
</table>

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

Проблема в том, что эффективность. Репозитории можно развернуть, но только вокруг того агрегата, для которого они созданы. Использование репозиториев становится неэффективным для доступа на чтение в тот момент, когда вам нужен доступ к данным, которые находятся более чем в одном репозитории.

Мое решение состоит в том, чтобы создать DTO UserInformation с соответствующей информацией и поместить метод в UserForumsRepository с подписью

ILIst<UserInformation> GetUserForumsUserInformationByForumPostID(int forumPostID).

Один из моих коллег предполагает, что использование DTO таким образом нарушает шаблон проектирования, который мы использовали, и предполагает, что лучшим способом было бы получить список идентификаторов комментариев форума, а затем передать эти идентификаторы в различные репозитории, чтобы вернуть Результаты.

Я считаю, что основной целью репозиториев является инкапсуляция бизнес-логики, которая важна для частей CUD CRUD, но списки только для чтения должны генерироваться так, как это имеет смысл. Если это уместно, я думаю, что даже имеет смысл полностью удалить методы списка только для чтения из репозитория (например, в общем виджете, который используется на нескольких страницах разных типов).

Как вы справляетесь с этой ситуацией?


person John    schedule 23.03.2010    source источник


Ответы (2)


Я ненавижу отвечать на свой вопрос, но у меня не было комментариев, и, кажется, я нашел ответ от обычного подозреваемого: Фаулера.

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

Согласно Фауэру (PoEAA 401), вы «... обычно не можете передавать объекты из модели предметной области... потому что объекты обычно связаны в сложную сеть, которую трудно, если вообще возможно, сериализовать». Фаулер продолжает: «Вместо этого вы должны передавать упрощенную форму данных из объектов предметной области».

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

Должен признаться, меня несколько огорчило это заявление Фаулера. Мне очень нравится удобство использования модели предметной области в ASP.Net MVC. Это делает его особенно удобным при создании основных и подробных представлений шаблонов проектирования пользовательского интерфейса. Когда строго типизированное представление связано с клиентом, требуется всего одна строка кода для включения частичного представления CustomerOrders.ascx (с типом IList) и передачи customer.Orders в частичное представление. Может быть, можно продолжать делать это, пока объект домена не ведет себя, но это вопрос будущего.

person John    schedule 23.03.2010
comment
Модель предметной области без поведения — это антипаттерн, называемый анемичной моделью предметной области. Мы используем dto для решения вашей проблемы. Один или несколько репозиториев объединяются для сопоставления нескольких сущностей с одним сглаженным dto, который затем отправляется клиенту. Если вы отправляете свои объекты клиенту, вы рискуете тем, что ваша модель предметной области изменит свое состояние непоследовательным образом. - person Sean Chambers; 02.05.2010
comment
Вы делаете это на уровне сервиса или на уровне репозитория? - person John; 03.05.2010

Ответ 2

Здесь необходим дополнительный сервисный уровень между конкретным репозиторием и клиентом. Иногда то, что нужно клиенту, отличается от того, что предоставляет уровень репозитория, особенно в случае, когда репозитории могут быть распределенными. Сервисный уровень позволяет вам определять грубые методы и скрывать мелкие детали от клиента. На уровне сервисов вы затем передаете клиенту облегченные DTO вместо полноценных бизнес-объектов.

Для сопоставления бизнес-объектов с DTO и обратно довольно популярным становится инструмент Automapper.

person John    schedule 24.03.2010