Где реализовать доступ к данным для метода доступа агрегированного корневого объекта

У меня есть совокупный корень с именем Account и объект с именем Contact, к которому можно получить доступ с помощью метода в корне: Account.GetContactById(string id). Доступ к совокупному корню осуществляется через репозиторий, поэтому логика доступа к данным для получения учетных записей из хранилища находится там.

Где должна находиться логика доступа к данным для доступа к сущности Contact? Большинство примеров, которые я вижу, демонстрируют метод Account.GetContactById, выполняющий поиск в коллекции в памяти. В моем случае Account может ссылаться на тысячи Contacts, которые я не хотел бы предварительно загружать в память. Итак, учитывая, что при вызове метода потребуется доступ к хранилищу данных, могу ли я реализовать этот доступ в:

  1. Метод Account.GetContactById? Это расширит прямой доступ к хранилищу за пределами репозиториев и внесет некоторую жесткую связь.
  2. AccountRepository, может быть вызван агрегатом Account? Казалось бы, это открывает Contact сущностей напрямую для любого другого пользователя репозитория, что нарушает правила Эванса.
  3. Другой репозиторий, например ContactRepository? В этом случае у меня есть репозиторий для объекта, который не является совокупным корнем.
  4. Другой?

person BitMask777    schedule 14.05.2015    source источник
comment
Почему Contact не является собственным корневым каталогом? Почему вы решили использовать большой кластер Account aggregate?   -  person plalx    schedule 15.05.2015
comment
@plalx Отличная точка. Моя дилемма могла быть просто артефактом плохого решения в моделировании. Я подумаю над этим еще немного.   -  person BitMask777    schedule 15.05.2015
comment
Обычно, если нет обязательных инвариантов, таких как максимальное количество контактов и т. Д., То Contact, вероятно, будет AR, поскольку вы ничего не получите, если их кластеризовать в Account.   -  person plalx    schedule 15.05.2015
comment
@plalx Ваш совет привел меня к правильному пути решения. Я хотел бы поблагодарить вас за это, поэтому, если вы хотите опубликовать его в качестве ответа, я приму его и добавлю к нему комментарии с особенностями моего решения.   -  person BitMask777    schedule 18.05.2015


Ответы (1)


Комментарии от @plalx указали мне правильное направление. Я публикую здесь свое решение как ответ, чтобы помочь другим, у кого могут возникнуть вопросы того же типа.

Прочитав пару действительно хороших статей Вернона о моделировании агрегатов (вы можете найти статьи здесь и здесь) вывод, что я позволил композиционной структуре привести меня к плохой модели. Просто потому, что Contact относится к Account, недостаточно, чтобы объединить их в одну совокупность. От Вернона:

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

Он объясняет, как это не масштабируется, отчасти из-за той самой проблемы, с которой я столкнулся, используя в качестве примера систему отслеживания спринтов:

Принимая во внимание производительность и масштабируемость, что произойдет, когда один пользователь одного клиента захочет добавить в продукт один элемент невыполненной работы, которому уже несколько лет и который уже имеет тысячи элементов невыполненной работы? Предположим, что механизм сохраняемости может выполнять отложенную загрузку (Hibernate). Мы почти никогда не загружаем сразу все элементы бэклога, релизы и спринты. Тем не менее, тысячи элементов невыполненной работы будут загружены в память только для того, чтобы добавить один новый элемент в и без того большую коллекцию.

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

Итак, в конце я разделил Contact и Account на разные агрегаты с помощью службы приложений для разрешения ассоциации.

person BitMask777    schedule 20.05.2015