Что такое совокупный корень?
-
21-09-2019 - |
Вопрос
Я пытаюсь понять, как правильно использовать шаблон репозитория.Центральная концепция совокупного корня продолжает возникать.При поиске информации о том, что такое совокупный корень, в Интернете и при переполнении стека я постоянно нахожу дискуссии о них и мертвые ссылки на страницы, которые должны содержать базовые определения.
В контексте шаблона репозитория что такое совокупный корень?
Решение
В контексте шаблона репозитория совокупные корни — это единственные объекты, которые ваш клиентский код загружает из репозитория.
Репозиторий инкапсулирует доступ к дочерним объектам — с точки зрения вызывающего объекта он автоматически загружает их либо одновременно с загрузкой корня, либо когда они действительно необходимы (как в случае с отложенной загрузкой).
Например, у вас может быть Order
объект, который инкапсулирует операции над несколькими LineItem
объекты.Ваш клиентский код никогда не загрузит LineItem
объекты напрямую, только Order
который их содержит и который будет совокупным корнем для этой части вашего домена.
Другие советы
От Эванса DDD:
AGGREGATE — это кластер связанных объектов, которые мы рассматриваем как единое целое с целью изменения данных.Каждый АГРЕГАТ имеет корень и границу.Граница определяет, что находится внутри AGGREGATE.Корень — это отдельная СУЩНОСТЬ, содержащаяся в AGGREGATE.
И:
Корень — единственный член AGGREGATE, на который внешним объектам разрешено хранить ссылки на[.]
Это означает, что совокупные корни — единственные объекты, которые можно загрузить из репозитория.
Примером может служить модель, содержащая Customer
сущность и Address
сущность.Мы никогда не получим доступ к Address
объект непосредственно из модели, поскольку он не имеет смысла без контекста связанного Customer
.Итак, мы могли бы сказать, что Customer
и Address
вместе образуют совокупность, и это Customer
является совокупным корнем.
Совокупный корень — это сложное название простой идеи.
Главная идея
Хорошо спроектированная диаграмма классов инкапсулирует его внутреннюю структуру.Точка, через которую вы получаете доступ к этой структуре, называется aggregate root
.
Внутреннее устройство вашего решения может быть очень сложным, но пользователь этой иерархии будет просто использовать root.doSomethingWhichHasBusinessMeaning()
.
Пример
Проверьте эту простую иерархию классов
Как вы хотите ездить на своей машине?Выберите лучший API
Вариант А (он просто как-то работает):
car.ride();
Вариант Б (пользователь имеет доступ к внутренним функциям класса):
if(car.getTires().getUsageLevel()< Car.ACCEPTABLE_TIRE_USAGE)
for (Wheel w: car:getWheels()){
w.spin();
}
}
Если вы считаете, что вариант А лучше, поздравляю.Вы получаете основную причину aggregate root
.
Агрегатный корень инкапсулирует несколько классов.вы можете манипулировать всей иерархией только через главный объект.
Представьте, что у вас есть сущность «Компьютер», эта сущность также не может существовать без сущности «Программное обеспечение» и сущности «Оборудование».Они образуют Computer
совокупность, мини-экосистема компьютерной части домена.
Aggregate Root — это материнская сущность внутри агрегата (в нашем случае Computer
), обычно ваш репозиторий работает только с объектами, которые являются совокупными корнями, и этот объект отвечает за инициализацию других объектов.
Рассматривайте корневой элемент агрегата как точку входа в агрегат.
В коде С#:
public class Computer : IEntity, IAggregateRoot
{
public Hardware Hardware { get; set; }
public Software Software { get; set; }
}
public class Hardware : IEntity { }
public class Software : IValueObject { }
public class Repository<T> : IRepository<T> where T : IAggregateRoot {}
Имейте в виду, что Hardware, скорее всего, тоже будет ValueObject (не будет иметь собственной идентификации), рассматривайте это только как пример.
Если вы следуете подходу «сначала база данных», корневой агрегацией обычно является таблица на стороне 1 отношения «1-многие».
Самый распространенный пример — Человек.У каждого человека есть множество адресов, одна или несколько платежных квитанций, счетов-фактур, записей CRM и т. д.Это не всегда так, но в 9/10 случаях это так.
В настоящее время мы работаем над платформой электронной коммерции, и у нас в основном есть два совокупных корня:
- Клиенты
- Продавцы
Клиенты предоставляют контактную информацию, мы назначаем им транзакции, транзакции получают отдельные позиции и т. д.
Продавцы продают товары, имеют контактных лиц, страницы о нас, специальные предложения и т. д.
Об этом заботятся репозиторий Клиента и Продавца соответственно.
Внутри агрегата есть корень агрегата.Корень агрегата является родительской сущностью для всех других объектов и объектов-значений в агрегате.
Репозиторий работает на основе совокупного корня.
Более подробную информацию также можно найти здесь.
Совокупный означает сбор чего-либо.
корень это как верхний узел дерева, откуда мы можем получить доступ ко всему, например <html>
узел в документе веб-страницы.
Аналогия с блогом. Пользователь может иметь много сообщений, и каждое сообщение может иметь много комментариев.поэтому, если мы выберем любого пользователя, он может действовать как корень чтобы получить доступ ко всем связанным сообщениям и дополнительным комментариям к этим сообщениям.Все это вместе называется коллекцией или Агрегированный
Агрегат — это место, где вы защищаете свои инварианты и обеспечиваете согласованность, ограничивая доступ к корню агрегата.Не забывайте, что агрегат должен разрабатываться на основе бизнес-правил и инвариантов вашего проекта, а не отношений с базой данных.вам не следует внедрять какой-либо репозиторий, и никакие запросы не допускаются.
В Erlang нет необходимости различать агрегаты, поскольку агрегат состоит из структур данных внутри состояния, а не из объектно-ориентированной композиции.См. пример: https://github.com/bryanhunter/cqrs-with-erlang/tree/ndc-london