Domain driven design 在DDD中具有深层层次结构的聚合根是否合适?
我有一个系统,用户以一种形式回答问题。我有表示这个模型的对象,但我不太确定如何根据DDD组织这些对象Domain driven design 在DDD中具有深层层次结构的聚合根是否合适?,domain-driven-design,aggregateroot,Domain Driven Design,Aggregateroot,我有一个系统,用户以一种形式回答问题。我有表示这个模型的对象,但我不太确定如何根据DDD组织这些对象 表格(有自己的)章节列表 第->(有自己的)组列表 组->(有自己的问题列表) 问题->(可以有自己的子问题列表)问题 问题->(有自己的答案列表) 答案->(有自己的答案详细信息列表) 答案详细信息->(可能有自己的子详细信息列表)子答案详细信息 每个对象都有15个以上的属性,没有父对象,每个属性都没有意义。根据DDD,我认为表单实体应该是聚合根,所有其他对象都应该是值对象。这意味着我只需要表
每个对象都有15个以上的属性,没有父对象,每个属性都没有意义。根据DDD,我认为表单实体应该是聚合根,所有其他对象都应该是值对象。这意味着我只需要表单实体的存储库。在这种情况下,FormRepository将充斥着子对象的各种CRUD方法。就DDD而言,我的推理正确吗?我最终得到的是一个非常广泛的聚合,这样可以吗?我相信这样的表示很容易导致性能问题。是的,DDD中的深层层次结构很好 我最终得到一个非常广泛的集合,这样可以吗如果实际情况如此复杂,并且您的域模型是您所能想到的最好的,那么您最终将得到一个复杂的聚合根 是的,
表单
应该是聚合根
所有其他对象都应该是值对象-错误,所有其他对象都应该是非聚合根实体(具有Id),而没有存储库来获取它们。值对象没有Id,值对象的相等性仅由其属性值决定,而不是由Id的相等性决定(更多信息)
在这种情况下,FormRepository将充斥着子对象的各种CRUD方法-不,存储库应该只包含有关聚合根的方法,即Get,Save 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);
}
我相信这样的表示很容易导致性能问题-如果使用,您将从命令处理程序调用一些
Form
domain方法,如果您使用NHibernate进行实体持久化,默认情况下它将使用延迟加载,并且只从DB加载Form
,然后它将只加载您真正接触的实体,例如Sections.First()
将从DB加载所有部分,但不加载组和其他部分。对于查询,您将创建一个表单dto
(数据传输对象)和其他可能扁平化的dto,以获取所需表单中的数据(这可能不同于您的实体结构,UI可能驱动dto结构)。查看我的关于DDD/CQRS/NHibernate/Repository的信息即使答案已被接受,我想我还是可以加上我的2美分:
深层层次结构(可能)很好,但请记住,聚合背后的想法实际上是为了防止这种情况。我倾向于将实体视为一个整体,大致如下:
“如果没有AR,该实体是否具有任何含义?”
由于我没有任何上下文w.r.t.您的模型,我将使用订单
/订单行
。如果没有订单
,订单行是否有任何意义?我可以自己处理订单行吗?显而易见的答案是“不”
每个模型都需要根据上下文进行处理。但所有权并不一定意味着遏制
使用单独的有界上下文时,如果BCs正确,则更容易看到这些内容:)
在您的情况下,答案如果没有它的问题
,可能没有任何意义。但是一个问题
可能存在于问题库
BC中,并且一个特定的问题可以在你的考试
BC和你的注册
BC中使用。所有这些都是完全虚构的,所以这取决于你的背景
因此,如果问题
可以是AR,那么表单
AR所拥有的问题可能只是一个值对象,甚至是一个简单的问题ID。谢谢你的2美分。我不太明白你的意思:如果问题可以是AR,那么你表格AR中的问题可能只是一个值对象。如何问题成为AR可以是一个值对象。所有应收账款均应为实体。实际上,在我的例子中,没有所有者,所有对象都没有意义。如果没有表单上下文,就无法访问它们。在我的例子中,节和组除了分组问题没有其他意义。请告诉我您的方法是否与@xhafan的方法不同。你们认为什么东西可以是伏萨,我明白为什么答案可能是没有意义的:)---很抱歉。我的意思是,如果BC-A中的AR在BC-B中使用,那么在BC-B中,您可以只使用相关的AR Id,或者将其建模为值对象。模型将100%取决于您对模型的上下文/理解。所以我不能肯定地说,你所拥有的是不正确的。然而,我过去曾以类似的方式对ARs进行建模,事后看来,我知道这不是100%正确的。如果它起作用,那就好了;如果您遇到问题/重复,您需要再次查看模型。最近阅读了推荐使用小聚合的地方。如果一个巨大的聚合包含数千个项目的子实体集合,则可能会出现性能问题,因为向集合中添加一个项目会获取整个集合(例如,nhibernate是这样工作的)。固定到该集合的链接取决于许多因素。是否会同时修改同一表格?如果答案是肯定的,那么您不应该创建更大的集群聚合。还有,你的使用