DDD: правильно ли для корневого агрегата хранить ссылку на другой корневой агрегат?

16

При следовании модели, управляемой доменом (DDD), правильно ли для корневого агрегата хранить ссылку на внутренний объект, который оказывается корневым объектом в отдельном агрегате?

Я считаю, что это не правильно, в основном из-за этого правила в синей книге :

Ничто за пределами границы AGGREGATE не может содержать ссылку на что-либо внутри, кроме корневого ENTITY. Корневая сущность может передавать ссылки на внутренние сущности другим объектам, но эти объекты могут использовать их только временно, и они могут не удерживать ссылку. Корень может передать копию ЗНАЧЕНИЯ ОБЪЕКТА другому объекту, и не имеет значения, что с ним происходит, потому что это просто ЗНАЧЕНИЕ и больше не будет иметь никакого отношения к AGGREGATE.

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

Коренные субъекты имеют глобальную идентичность. СУЩНОСТИ внутри границы имеют локальную идентичность, уникальную только в пределах АГРЕГАТА.

Я полагаю, что это будет правильный путь, но, поскольку он кажется повторяющимся и избыточным (если его исключить из контекста DDD, с чистым ООП), я прошу некоторую обратную связь.

Lesair Valmont
источник
Что вы подразумеваете под «внутренней сущностью (которая является корневой сущностью в отдельном агрегате)»?
Эрик Эйдт
2
FWIW, что-нибудь может относиться к совокупной корневой сущности, поскольку это вещи, имеющие глобальную идентичность; является ли реферер корневым объектом или нет, не имеет значения.
Эрик Эйдт
Как сказал Эрик. Кроме того, не имеет значения, ссылаетесь ли вы на это с помощью идентификатора или ссылки в вашей модели. Они оба преобразуются в ID на уровне БД, а наличие ссылки дает ORM возможность ленивой загрузки объекта по требованию.
Эйфорическая

Ответы:

21

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

Тем не мение,

  • Общепринятая хорошая практика - ссылаться на AR, сохраняя его идентификатор, а не полную ссылку.
  • Более современные подходы к проектированию агрегатов (см. Красную книгу ) требуют более четкого разделения между агрегатами. Бизнес-операция должна изменять только состояние одного агрегата. В соответствии с этим предположением необходимость хранить ссылку на другой агрегат, как правило, исчезает, поскольку вы не собираетесь изменять 2 агрегата одновременно.

Правильно ли для корневого агрегата хранить ссылку на внутренний объект, который оказывается корневым объектом в отдельном агрегате?

Такого никогда не бывает. Объект-значение может быть частью нескольких агрегатов, но не сущностью. Причина в том, что ничто не помешает вам совместно использовать один и тот же экземпляр сущности между агрегатами. Предположим, что экземпляр сущности E принадлежит обоим агрегатным экземплярам A и B. Так как предпосылка DDD заключается в том, что Aggregate является точкой входа, вы сможете загрузить A, изменить сущность E через нее, все время молча нарушая инварианты из B (что вы не загрузили).

Смотрите ответ Грега Янга здесь: http://domain-driven-design.3010926.n2.nabble.com/Can-an-Entity-be-Shared-across-many-Aggregates-td7579277.html

guillaume31
источник
Спасибо Гийому за четкий, лаконичный и проницательный ответ. Истинный талант знатока DDD. Это то, что я искал. Вводная!
Lesair Valmont
Я знаю, что это может быть глупый вопрос, но могу ли я спросить, что означает holding a referenceв этом контексте? потому что я запутался, когда вы сказали, что: holding a reference to a root is legitпотом после этого вы сказали:This never happens. A Value Object can be part of multiple Aggregates, but not an Entity. The reason is, nothing would then prevent you from sharing the same entity instance between Aggregates.
Anyname Donotcare
1
Держите ссылку = сохраняйте ее внутренне / длительно, как член класса. Дихотомия здесь корень против некорня. Вы можете удерживать корневую ссылку, но не некорневую ссылку.
guillaume31
@ guillaume31 большое спасибо, но могу ли я спросить, можно ли сохранить idвнутреннюю сущность (не root) в другом агрегате или это нарушает (root или нет)?
Anyname Donotcare
Что бы вы сделали с этим удостоверением личности? Даже репозитории дают вам только корни, а не внутренние сущности.
guillaume31
1

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

Если у вас есть объект AR со свойством, которого нет в совокупности, тогда вы сразу же столкнетесь с вопросом. 'Почему нет?'

Вы могли бы добавить идентификатор другого объекта, возможно? Или залить репозиторий?

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

Ewan
источник
Эван, я больше думал о повторном использовании класса между двумя различными агрегатами в смысле ООП, а не о том, чтобы доменная служба выполняла роль бизнес-скрипта, который будет выполнять некоторую работу с двумя различными агрегатами DDD. В заключение, я согласен с вами, мой совокупный корень должен иметь только те свойства, которые являются частью его домена.
Lesair Valmont