Что такое совокупный корень?


447

Я пытаюсь понять, как правильно использовать шаблон репозитория. Центральная концепция Aggregate Root продолжает появляться. При поиске в Интернете и в Stack Overflow справки о том, что такое совокупный корень, я постоянно нахожу дискуссии о них и мертвые ссылки на страницы, которые должны содержать базовые определения.

Что такое совокупный корень в контексте шаблона хранилища ?


16
Рассмотрите обзор следующих тематических исследований. Эффективное Совокупные дизайн Часть I: Моделирование одного агрегата dddcommunity.org/wp-content/uploads/files/pdf_articles/... Часть II: Изготовление агрегатов работают вместе dddcommunity.org/wp-content/uploads/files/pdf_articles/... Часть III: Получение понимания
Бен Витале

Ответы:


310

В контексте шаблона репозитория агрегатные корни являются единственными объектами, которые клиентский код загружает из репозитория.

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

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


21
Гипотетически, если клиентскому коду нужен LineItem для каких-то других целей, будет ли это формировать отдельный агрегат (при условии, что будут задействованы другие объекты, не связанные с объектом Order)?
Ахмад

20
@ Ахмад, другие агрегаты могут ссылаться на LineItems как данные только для чтения, они просто не могут их изменить . Если другие агрегаты могут изменить их, вы не сможете защитить инварианты заказа (или позиции).
Джефф Стернал

4
Взгляните на это, например, lostechies.com/blogs/jimmy_bogard/archive/2010/02/23/… . В этом примере Customer является инвариантом Order, верно? Тем не менее, Клиент также может быть другой совокупный корень? Или мне здесь не хватает фундаментального понимания?
Ахмад

3
@ Джефф Вы сказали, что «они просто не могут их изменить» - это принудительно или условно?
Нил Барнвелл

4
@Neil: я бы применил его, используя любые доступные языковые механизмы - например, создав неизменный класс для представления данных.
Джефф Стерн

206

От Эванса ДДД:

AGGREGATE - это кластер связанных объектов, которые мы рассматриваем как единое целое с целью изменения данных. Каждый AGGREGATE имеет корень и границу. Граница определяет, что находится внутри АГРЕГАТА. Корень - это отдельная особая сущность, содержащаяся в АГРЕГАТЕ.

А также:

Корень - единственный член AGGREGATE, которому внешние объекты могут содержать ссылки на [.]

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

Примером является модель, содержащая Customerсущность и Addressсущность. Мы никогда не получим доступ к Addressобъекту напрямую из модели, так как это не имеет смысла без контекста связанного Customer. Таким образом , мы могли бы сказать , что Customerи Addressвместе образуют совокупность и Customerпредставляет собой совокупность корень.


57
Обновление от Эрика Эванса : подчеркните, что агрегатные корни являются границами согласованности для транзакций / параллелизма, и подчеркните, что внешние сущности не могут содержать ссылки на дочерние сущности других агрегатов.
Брайан Лоу,

3
Так что словоблудие меня всегда смущает. Each AGGREGATE has a rootи The root is the only *member* of the AGGREGATE- этот глагол подразумевает, что корень является собственностью Агрегата. Но во всех примерах все наоборот: корень содержит свойства, которые являются агрегатами. Вы можете уточнить?
Синастетик

1
Просто чтобы понять мой язык правильно, Customerкласс считается совокупным корнем или Customer экземплярами ?
Джо

1
Вообще говоря, в парадигме "позиция-заказ-позиция-клиент" клиентом будет совокупный корень. Экземпляр клиента будет экземпляром этого совокупного корня. Говоря об объединенном корне, называемом клиентом, вы обсуждаете логическую конструкцию клиента, который составляет экземпляр клиента. Коллекция клиентов - это просто коллекция.
Ибрагим Маллуф

111

Совокупный корень - это сложное имя для простой идеи.


Главная идея

Хорошо разработанная диаграмма классов инкапсулирует ее внутренности. Точка, через которую вы получаете доступ к этой структуре, называется aggregate root.

введите описание изображения здесь

Внутренние элементы вашего решения могут быть очень сложными, но пользователь этой иерархии будет просто использовать root.doSomethingWhichHasBusinessMeaning().


пример

Проверьте эту простую иерархию классов введите описание изображения здесь

Как вы хотите ездить на своей машине? Выбрал лучший API

Вариант А (просто как-то работает):

car.ride();

Вариант B (пользователь имеет доступ к инерналам класса):

if(car.getTires().getUsageLevel()< Car.ACCEPTABLE_TIRE_USAGE)
    for (Wheel w: car:getWheels()){
        w.spin();
    }
}

Если вы считаете, что вариант А лучше, то поздравляю. Вы получаете основную причину позади aggregate root.


Совокупный корень инкапсулирует несколько классов. Вы можете управлять всей иерархией только через главный объект.


17
Мне нравится пример, но я изо всех сил пытаюсь найти сценарий, в котором Клиент должен ссылаться на Engine. Кажется, что Двигатель должен быть заключен в капсулу позади Автомобиля. Можете ли вы остановиться на этом немного?
Emragins

По моему мнению, сам двигатель должен быть внутри конкретной модели автомобиля, например, BMW серии 5 с двигателем 3000 куб. При таком моделировании двигатель является компонентом для автомобиля.
Парама Дхармика

1
@ParamaDharmika конечно, вы можете смоделировать это таким образом. Это зависит от того, насколько «продвинутыми» с автомобилями являются ваши клиенты. В базовой модели он должен иметь доступ к carсовокупному корню. Вы также можете разрешить ситуацию, как на рисунке. Правильное решение зависит от бизнес-модели приложения. Это может быть различным в каждом случае.
Марчин Шимчак,

1
@MarcinSzymczak правильно, не могу не согласиться с тем, что решение зависит от самой доменной модели
Parama Dharmika

На самом деле, Колесо - это совокупность, которая содержит Шину (и другие части). Если ваши правила требуют, чтобы к колесному агрегату можно было получить доступ только через агрегат корня автомобиля, то двигатель также содержится в агрегате корня автомобиля и не должен быть доступен вне автомобиля. Это в сфере автомобилей. Владелец автомобиля (Заказчик) не будет ссылаться на двигатель, кроме как в контексте его / ее автомобиля.
Ибрагим Маллуф

35

Представьте, что у вас есть объект «Компьютер», этот объект также не может существовать без объекта «Программное обеспечение» и «Оборудование». Они образуютComputer совокупность, мини-экосистему для компьютерной части домена.

Aggregate Root - это сущность материнства внутри совокупности (в нашем случае Computer), это обычная практика, когда ваш репозиторий работает только с сущностями, которые являются Aggregate Roots, и эта сущность отвечает за инициализацию других сущностей.

Рассматривайте совокупный корень как точку входа в совокупность.

В коде C #:

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 {}

Имейте в виду, что аппаратное обеспечение, скорее всего, тоже будет ValueObject (не имеет собственной идентичности), рассмотрите его только в качестве примера.


6
where T : IAggregateRoot- Этот сделал мой день
Кристиан Э.

Я думаю, что формулировка немного противоречива, и это то, что смущает меня, когда я пытаюсь выучить это. Вы говорите, что Компьютер - это совокупность, но затем вы говорите, что корнем будет сущность материнства ВНУТРИ совокупности. Итак, какой из них является сущностью "материнства" в совокупности в этом примере?
Синаэстетик

Привет из будущего! Парень имеет в виду, что компьютер сам по себе является совокупным корнем, а компьютер и все, что внутри него, является совокупностью. Или, если быть более ясным: случай сам по себе является совокупным корнем, а весь компьютер - совокупным (совокупность всего, что составляет «компьютер», например, освещение RGB, оборудование, источники питания, ОС и т. Д.)
капитан Кенпачи

Техника IAggregateRoot обнаруживается в документации Microsoft: docs.microsoft.com/en-us/dotnet/architecture/microservices/…
Сэмюэль Дэниелсон

16

Если вы следуете подходу, основанному на базе данных, то вы обычно объединяете корень как таблицу со стороны 1 отношения 1-много.

Самый распространенный пример - Человек. У каждого человека есть много адресов, один или несколько платежных ведомостей, счета, записи CRM и т. Д. Это не всегда так, но в 9/10 раз больше.

В настоящее время мы работаем над платформой электронной коммерции, и у нас есть два основных корня:

  1. Клиенты
  2. Продавцы

Клиенты предоставляют контактную информацию, мы присваиваем им транзакции, транзакции получают позиции и т. Д.

Продавцы продают товары, имеют контактных лиц, страницы о нас, специальные предложения и т. Д.

Об этом заботятся Клиент и Хранилище Продавца соответственно.


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

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

12

Дин:

В контексте репозитория Совокупный корень является сущностью без родительской сущности. Он содержит ноль, одну или несколько дочерних сущностей, чье существование зависит от Родителя в отношении его идентичности. Это отношение «один ко многим» в репозитории. Эти Дочерние Сущности - простые Совокупности.

введите описание изображения здесь


1
Итак, если вы продавец автомобилей, то Car будет самостоятельным корнем? Потому что у вас может быть много автомобилей, у которых еще нет покупателя
JorgeeFG

2
@JorgeeFG реальный ответ - никто не имеет никакой подсказки. Вокруг столько противоречивой информации.
Mardoxx

3
Дочерние сущности - это не агрегаты, а просто сущности, которые оказываются членами агрегата, в котором контролируется корневой агрегат. «Агрегат» - это логическая группировка объектов.
Sinaesthetic

@JorgeeFG это действительно зависит от ограниченного контекста, который вы разрабатываете. Если вы продавец автомобилей, то что-то вроде автомагазина становится совокупным корнем, а под ним - автомобили ...
jokab

8

Из неработающей ссылки :

Внутри Агрегата есть Совокупный Корень. Агрегированный корень является родительской сущностью для всех других сущностей и объектов значений в совокупности.

Репозиторий работает на основе совокупного корня.

Более подробную информацию также можно найти здесь .


4
Спасибо. Это определенно самая распространенная и расстраивающая сломанная ссылка, с которой я постоянно сталкивался.
Дина

Кроме того, формулировка кажется задом наперед. Как корень может находиться в пределах совокупности и быть одновременно его родителем?
Синаэстетик

1
Совокупный корень является корневым классом. Простой Агрегат всегда содержится в Агрегатном Корне. Используя диаграмму, приведенную выше ... Заказчик - Совокупный Корень. Заказчик может владеть одним или несколькими автомобилями. Автомобили являются агрегатами по отношению к Заказчику. Автомобили имеют двигатель. Двигатель - это агрегат, содержащийся в агрегате автомобиля. Что делает Клиента Агрегированным Корнем, так это предположение модели о том, что доступ к автомобилю или его компонентам всегда осуществляется через клиента, которому принадлежит автомобиль.
Ибрагим Маллуф

8

Агрегат означает сбор чего-то.
Корень похож на верхний узел дерева, откуда мы можем получить доступ ко всему, как <html>узел в документе веб-страницы.
Блог аналогия, пользователь может иметь много сообщений, и каждый пост может иметь много комментариев. поэтому, если мы получим какого-либо пользователя, он может выступать в роли пользователя root для доступа ко всем связанным постам и дальнейшим комментариям этих постов. Все это вместе называется коллекцией или совокупностью


1

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


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.