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

У меня есть система, в которой пользователь отвечает на вопрос в форме. У меня есть объекты, представляющие эту модель, но я не совсем уверен, как организовать эти объекты с точки зрения DDD.

  1. Форма (имеет свой список) Разделы;
  2. Раздел -> (имеет свой список) Группы;
  3. Группа -> (есть свой список) Вопросы;
  4. Вопрос -> (может иметь собственный список подвопросов) Вопросы;
  5. Вопрос -> (есть свой список) Ответы;
  6. Ответ -> (есть свой список) Answer_Details;
  7. Answer_Detail -> (потенциально имеет свой собственный список дополнительных деталей) Sub_Answer_Details.

Каждый объект имеет более 15 свойств, и каждое из них не имеет смысла без своего родителя. Согласно DDD, я считаю, что сущность формы должна быть агрегатным корнем, а все другие объекты должны быть объектами значений. Это означает, что мне нужен репозиторий только для сущности формы. В этом случае FormRepository будет загроможден всевозможными CRUD-методами для дочерних объектов. Верны ли мои рассуждения с точки зрения DDD? Это нормально, что я получаю очень обширную совокупность? Я считаю, что такое представление может легко привести к проблемам с производительностью.


person ddv    schedule 30.11.2012    source источник


Ответы (2)


Да, в DDD можно использовать глубокую иерархию.

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

Да, Form должен быть совокупным корнем.

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

В этом случае FormRepository будет загроможден всеми видами CRUD-методов для дочерних объектов - нет, репозиторий должен содержать только методы, относящиеся к совокупному корню, т.е. Get<T> , Save<T> where T : IAggregateRoot, как только вы получите экземпляр совокупного корня, вы можно перемещаться с помощью атрибутов и методов, чтобы получить то, что вам нужно. Пример:

var formId = 23;
var form = _formRepository.Get(formId);
var firstGroup = form.Sections.First().Group().First();

или лучше

var groupIndex = 1;
var firstGroup = form.GetGroupAt(groupIndex);

куда

public Group GetGroupAt(int groupIndex)
{
    Sections.First().Group().ElementAt(groupIndex);
}

Я считаю, что такое представление может легко привести к проблемам с производительностью - если вы используете CQRS, вы будете вызывать какой-то Form метод домена из обработчика команд, и если вы используете NHibernate для сохранения сущностей, он по умолчанию будет использовать ленивую загрузку и будет загружать только Form из БД, а затем будет загружать только те сущности, которых вы действительно касаетесь, так, например, Sections.First() загрузит все разделы из БД, но не группы и все остальное. Для запроса вы должны создать FormDto (объект передачи данных) и другие, возможно, сглаженные dtos, чтобы получить данные в нужной вам форме (которая может отличаться от структуры ваших сущностей, а пользовательский интерфейс может управлять структурой dto). Взгляните на мою blog для получения информации о DDD / CQRS / NHibernate / Repository

person xhafan    schedule 30.11.2012
comment
Совсем недавно прочитал Эффективный совокупный дизайн, где рекомендуются небольшие агрегаты. Могут возникнуть проблемы с производительностью с огромным агрегатом, который содержит коллекцию дочерних сущностей с тысячами элементов, потому что добавление элемента в коллекцию извлекает всю коллекцию (например, nhibernate работает так) - person xhafan; 26.07.2013
comment
Исправлена ​​ссылка на Эффективный агрегированный дизайн - person xhafan; 15.07.2015
comment
Это зависит от многих факторов. Будут ли одновременно происходить модификации одной и той же формы? Если ответ положительный, вам не следует создавать кластер большего размера. Кроме того, ваш вариант использования очень CRUD, поэтому с точки зрения пользовательского интерфейса, я думаю, вы просто представляете все редактируемые поля для всей формы и сохраняете их как целый документ. Однако, если ваш пользовательский интерфейс был немного более сегрегированным (например, позволял редактировать одну группу за раз или один раздел и т. Д., Тогда вам было бы полезно иметь несколько AR). - person plalx; 17.08.2015
comment
@xhafan Что вы думаете о хранении такого большого AR со всеми дочерними объектами, если эти методы должны быть помещены в один и тот же репозиторий? Только представьте, что у автора темы есть СУБД для каждого объекта, у которого есть собственная таблица, ясно, что никто, кроме репозитория AR, не может их хранить, но в этом случае репозиторий будет выглядеть как ад :-) - person user1016265; 09.03.2016
comment
@ user1016265 Я не совсем понимаю, о чем вы спрашиваете. На мой взгляд, репозиторий должен быть простым и иметь только методы Get, Save и Delete, ничего больше. - person xhafan; 21.03.2016
comment
Репозиторий @xhafan должен хранить совокупный корень. Если AR будет довольно сложным, тогда собственный репозиторий должен сохранять все эти сущности (иногда) в разных таблицах. Даже с Order / OrderLine. С РСУБД это могут быть как минимум две разные таблицы, поместите ли вы все это в один save метод, или у вас будет частный метод saveOrderLine ?? - person user1016265; 22.03.2016
comment
ААА ОК. Я использую nhibernate для сохранения, поэтому для сохранения AR вы вызываете session.Save (aggregateRoot); и все, все дерево будет сохранено в их таблицах. Посмотрите здесь: github.com/jagregory/fluent-nhibernate/wiki/Auto -mapping, а здесь: github.com/ jagregory / fluent-nhibernate / tree / master / src / как его использовать - person xhafan; 23.03.2016

Несмотря на то, что ответ был принят, я подумал, что могу добавить свои 2 цента:

Глубокие иерархии (вероятно) прекрасны, но помните, что идея агрегата состоит в том, чтобы фактически предотвратить это. Я склонен думать о сущностях в совокупности по следующим направлениям:

"Имеет ли этот объект какое-либо значение без AR?"

Поскольку у меня нет контекста w.r.t. вашу модель буду использовать _1 _ / _ 2_. Имеет ли OrderLine какое-либо значение без Order? Могу ли я сделать что-нибудь (поведение) с самой строкой заказа? Очевидный ответ - «нет».

К каждой модели нужно будет относиться в зависимости от контекста. Но владение не обязательно означает сдерживание.

Это может быть легче увидеть, когда вы работаете с отдельными ограниченными контекстами при условии правильного определения BC :)

В вашем случае Answer может не иметь значения без Question. Но, возможно, Question может жить в QuestionBank BC, и конкретный вопрос может использоваться как в вашем Examination BC, так и в вашем Enrollment BC. Все это полностью придумано, поэтому это будет зависеть от вашего контекста.

Поэтому, если Question может быть AR, тогда вопросы, принадлежащие вашему Form AR, могут быть просто объектом значения или даже простым идентификатором вопроса.

person Eben Roux    schedule 04.12.2012
comment
Спасибо за ваши 2 цента. Я не совсем понимаю, что вы имеете в виду под: Итак, если вопрос может быть AR, то вопросы, принадлежащие вашей форме AR, могут быть просто объектом значения. - person ddv; 05.12.2012
comment
Как Question быть AR может быть объектом-ценностью. Все AR должны быть Entities. На самом деле в моем случае все объекты не имеют смысла без хозяина. К ним нельзя получить доступ без контекста формы. Разделы и группы в моем случае не имеют другого значения, кроме вопросов группировки. Пожалуйста, дайте мне знать, будет ли ваш подход отличаться от подхода @xhafan. Как вы думаете, какие объекты могут быть голосовыми - person ddv; 05.12.2012
comment
Ах, я понимаю, почему ответ может не иметь смысла :) --- извините за это. Я имею в виду, что если AR в BC-A используется в BC-B, то в BC-B вы можете использовать либо только соответствующий AR Id , либо моделировать его как объект значения. Модель будет на 100% зависеть от вашего контекста / понимания модели. Поэтому я не могу с уверенностью сказать, что то, что у вас есть, неверно. Однако в прошлом я моделировал AR подобным образом, и, оглядываясь назад, я знаю, что это было не на 100% правильно. Если это работает, то все в порядке; если вы столкнетесь с проблемами / дублированием, вы захотите снова взглянуть на модель. - person Eben Roux; 05.12.2012