Domain driven design 什么属于聚合根
这是一个实用的领域驱动设计问题: 从概念上讲,我认为我得到了聚合根,直到我定义了一个 我有一个雇员实体,它以聚合根的形式出现。在企业中,一些员工可能会记录与工作相关的违规行为: 员工------*违规行为 由于并非所有员工都受此影响,我认为违规行为不会成为员工总数的一部分,对吗 所以,当我想与员工及其相关违规行为打交道时,这是由某个服务进行的两个独立的存储库交互吗 最后,当我添加一个冲突时,该方法是否在Employee实体上?Domain driven design 什么属于聚合根,domain-driven-design,aggregate,root,entities,Domain Driven Design,Aggregate,Root,Entities,这是一个实用的领域驱动设计问题: 从概念上讲,我认为我得到了聚合根,直到我定义了一个 我有一个雇员实体,它以聚合根的形式出现。在企业中,一些员工可能会记录与工作相关的违规行为: 员工------*违规行为 由于并非所有员工都受此影响,我认为违规行为不会成为员工总数的一部分,对吗 所以,当我想与员工及其相关违规行为打交道时,这是由某个服务进行的两个独立的存储库交互吗 最后,当我添加一个冲突时,该方法是否在Employee实体上? 谢谢你的帮助 在做了更多的研究之后,我想我找到了问题的答案 保罗·斯
谢谢你的帮助 在做了更多的研究之后,我想我找到了问题的答案 保罗·斯托维尔(Paul Stovell)在网上对一个类似问题的回答略作修改。用“客户”代替“员工”,用“订单”代替“违规”,你就明白了 只是因为客户参考了订单 不一定意味着订单会下降 在客户聚合根目录中。 客户的地址可能是,但是 订单可以是独立的(例如 例如,您可能有一个服务 处理所有新订单,无论是谁 客户是,我得走了 客户->订单在中没有意义 这种情况下) 从域的角度来看,您可以 甚至质疑这些数据的有效性 参考资料(客户已参考 订单清单)。你多久去一次 实际上需要所有的订单 顾客在某些系统中,它使 有道理,但在其他情况下,只有一个客户 可能会下很多订单。机会是 您希望在两个月之间为客户下订单 日期范围,或客户的订单 尚未处理的,或订单 没有支付的,等等。 您将需要所有 其中大多数可能比较少见。 然而,更有可能的是 在处理订单时,您将 需要客户信息。所以在 代码,
Order.Customer.Name
很有用,
但是Customer.Orders[0].LineItem.SKU
-
可能没那么有用。当然
那完全取决于你的生意
域名
换句话说,更新客户与更新订单无关。在我的案例中,订单或违规行为可以独立于客户/员工处理
如果违规有详细信息行,则违规和违规行将成为同一聚合的一部分,因为更改违规行可能会影响违规
编辑**
在我的领域里,问题在于违规行为没有任何行为。它们基本上是所发生事件的记录。我还不确定这会有什么影响。我想知道结论会是什么 “违规”将成为根实体。“违规”将由“员工”根实体引用。ie违规存储库员工存储库 但是,您对将违规行为作为根实体感到困惑,因为它没有行为
但“行为”是否是根实体资格的标准?我不这么认为。埃里克·埃文在他的书中说 聚合是一组相关对象,我们将其视为一个单元,用于数据更改 这里有两个要点:
var list = repository.FindAllViolationsByEmployee(someEmployee);
在这一点上,我大体上同意莫斯的看法。但是,请记住业务角度中的交易概念。因此,我实际上把“为了数据更改的目的”理解为“为了事务的目的” 存储库是域模型的视图。在域环境中,这些“视图”实际上支持或表示业务功能或功能—事务。例如,员工可能有一个或多个违规行为,如果是,则是某个时间点内交易的各个方面。考虑你的用例。 场景:“员工做出违反工作场所的行为。”这是发生的一种业务事件(即事务,或更大的、可能是分布式事务的一部分)。受根影响的域对象实际上可以从多个角度看到,这就是为什么它令人困惑的原因。但是要记住的是行为,因为它与业务事务有关,因为您希望您的业务流程尽可能准确地模拟现实世界。就关系而言,就像在关系数据库中一样,您的概念域模型实际上应该已经指出了这一点(即关联性),这通常可以从任意方向读取:
Customer { /*...*/ }
Employee { /*...*/ }
Repository<T> : IRepository<T>
, IEnumerable<T>
//, IQueryable<T>, IQueryProvider //optional
{ /**/ }
BusinessController {
Repository<Customer> Customers { get{ /*...*/ }} //aggregate root
Repository<Order> Orders { get{ /*...*/ }} // aggregate root
}