我正在设法弄清楚如何正确使用存储库模式。聚合根的中心概念不断出现。在网络和Stack Overflow上搜索有关总根的帮助时,我一直在寻找有关它们的讨论以及指向应该包含基本定义的页面的无效链接。
在存储库模式的上下文中,什么是聚合根?
我正在设法弄清楚如何正确使用存储库模式。聚合根的中心概念不断出现。在网络和Stack Overflow上搜索有关总根的帮助时,我一直在寻找有关它们的讨论以及指向应该包含基本定义的页面的无效链接。
在存储库模式的上下文中,什么是聚合根?
Answers:
在存储库模式的上下文中,聚合根是客户端代码从存储库加载的唯一对象。
存储库封装了对子对象的访问权限-从调用者的角度来看,它会在加载根的同时或实际需要它们时(与延迟加载一样)自动加载它们。
例如,您可能有一个Order
对象,该对象封装了对多个LineItem
对象的操作。您的客户端代码永远不会LineItem
直接加载包含对象的对象Order
,这将是域中该部分的总根。
从Evans DDD:
AGGREGATE是一组关联的对象,出于数据更改的目的,我们将其视为一个单元。每个AGGREGATE都有一个根和一个边界。边界定义了AGGREGATE内部的内容。根是包含在AGGREGATE中的单个特定ENTITY。
和:
根是AGGREGATE的唯一成员,允许外部对象保存对[。]的引用
这意味着聚合根是可以从存储库加载的唯一对象。
一个示例是包含Customer
实体和Address
实体的模型。我们永远不会Address
直接从模型访问实体,因为没有关联的上下文就没有意义Customer
。所以我们可以说Customer
和Address
一起形成一个聚合,这Customer
就是一个聚合根。
Each AGGREGATE has a root
和The root is the only *member* of the AGGREGATE
-这verbage意味着根是在聚集属性。但是在所有示例中,都是相反的:根包含聚合的属性。你能澄清一下吗?
Customer
该类是否被视为聚合根或Customer
实例?
聚合根是简单概念的复杂名称。
设计良好的类图封装了其内部。您访问此结构所经过的点称为aggregate root
。
解决方案的内部结构可能非常复杂,但是该层次结构的用户将只使用root.doSomethingWhichHasBusinessMeaning()
。
您想如何开车?选择更好的API
选项A(以某种方式起作用):
car.ride();
选项B(用户可以访问班级内部信息):
if(car.getTires().getUsageLevel()< Car.ACCEPTABLE_TIRE_USAGE)
for (Wheel w: car:getWheels()){
w.spin();
}
}
如果您认为选项A更好,那么恭喜您。你得到背后的主要原因aggregate root
。
聚合根封装了多个类。您只能通过主对象来操纵整个层次结构。
car
聚合根。您也可以允许类似图纸上的情况。正确的解决方案取决于应用程序的业务模型。每种情况下可能有所不同。
假设您有一个计算机实体,没有该软件实体和硬件实体,该实体也无法生存。这些构成Computer
域的计算机部分的总体,小型生态系统。
聚合根是聚合内的母公司实体(在我们的示例中Computer
),通常的做法是让您的存储库仅与作为聚合根的实体一起使用,并且该实体负责初始化其他实体。
将聚合根视为聚合的入口点。
在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(本身没有标识),仅将其视为示例。
where T : IAggregateRoot
-这个让我很快乐
如果遵循数据库优先方法,则聚合根通常是一对多关系的1侧的表。
最常见的例子是人。每个人都有许多地址,一张或多张工资单,发票,CRM条目等。情况并非总是如此,而是9/10倍。
我们目前正在电子商务平台上工作,基本上有两个聚合根:
客户提供联系信息,我们为他们分配交易,交易获得订单项,等等。
卖家出售产品,与他人联系,关于我们的页面,特价优惠等。
这些分别由客户和卖方存储库处理。
聚合是您保护不变量并通过限制对聚合根的访问来强制一致性的地方。不要忘记,聚合应该根据您的项目业务规则和不变量而不是数据库关系进行设计。您不应注入任何存储库,并且不允许进行任何查询。
在Erlang中,一旦聚集是由状态内部的数据结构组成的,而不是由OO组成的,则无需区分聚集。查看示例:https://github.com/bryanhunter/cqrs-with-erlang/tree/ndc-london