![]() |
1
25
在做了更多的研究之后,我想我对我的问题有了答案。 保罗·斯托维尔对一个类似问题的回答做了一点小小的修改。 DDD messageboard . 用“客户”代替“员工”,用“订单”代替“违规”,你就明白了。
换句话说,更新客户与更新订单无关。在我看来,可以独立于客户/员工处理订单或违规行为。 如果违规行为有细线,那么违规行为和违规行为将是同一集合的一部分,因为更改违规行为可能会影响违规行为。 编辑** 在我的领域,这里的问题是违规行为没有任何行为。它们基本上是发生事件的记录。还不确定它的含义。 |
![]() |
2
21
埃里克·埃文在他的书中说, Domain-Driven Design: Tackling the Complexity in the Heart of Software ,
这里有两个要点:
我相信在您的场景中,员工和违规不一定是一个单元,而在订单和订单项的例子中,它们是单个单元的一部分。 建模aggregate边界时,另一件重要的事情是在聚合中是否有任何不变量。不变量是应该在“整体”聚合中有效的业务规则。例如,对于order和orderitem示例,您可能有一个不变量,该不变量表示订单的总成本应小于预定义的金额。在这种情况下,只要您想向订单添加orderitem,就应该强制执行这个不变量,以确保您的订单是有效的。然而,在您的问题中,我看不到您的实体之间的任何不变量:雇员和违规。 这么简单的回答: 我认为员工和违规行为分别属于两个单独的集合。这些实体中的每一个都是它们自己的聚合根。因此,您需要两个存储库:EmployeeRepository和ViolationRepository。 我也相信你应该有一个从违反到员工的单向联系。这样,每个违规对象都知道它属于谁。但是,如果要获取特定员工的所有违规列表,则可以向违规存储库询问:
|
![]() |
3
2
你说你有员工实体和违规行为,而每一个违规行为本身都没有任何行为。从我上面所读到的,在我看来,你可能有两个总的根源:
EmployeeViolations由同一个员工ID标识,它包含一组冲突对象。这样就可以将员工行为和违规行为分开,而没有行为就不会得到违规实体。 违反是实体还是值对象,您应该根据其属性来决定。 |
![]() |
4
1
在这一点上,我一般同意莫什的观点。但是,请记住业务观点中的事务概念。所以我实际上把“数据变更的目的”理解为“交易的目的”。 存储库是域模型的视图。在域环境中,这些“视图”实际上支持或表示业务功能或功能——事务。在这种情况下,员工可能有一个或多个违规行为,如果是,则是某个时间点中事务的各个方面。考虑您的用例。 场景:“员工的行为违反了工作场所。”这是发生的一种业务事件(即事务,或更大的、可能是分布式事务的一部分)。受根影响的域对象实际上可以从多个角度看到,这就是为什么它令人困惑的原因。但是要记住的是行为,因为它与业务事务相关,因为您希望您的业务流程尽可能精确地模拟真实世界。在关系方面,就像在关系数据库中一样,概念域模型实际上应该已经指出了这一点(即关联性),通常可以从以下两个方向读取: 员工----犯------由---->违反 因此,对于这个用例,公平地说,它是一个处理违规的事务,而根或“主要”实体是违规的。那么,这将是您将为特定业务活动或业务流程引用的聚合根。但这并不是说,对于不同的活动或流程,您不能拥有员工聚合根,例如“新员工流程”。如果要小心,就不应该存在循环引用的负面影响,或者能够以多种方式遍历域模型。不过,我会警告您,这方面的管理应该由您的业务域中的控制器部分,或者您拥有的任何等效部分来考虑和处理。 旁白:从模式(即MVC)的角度考虑,存储库是一个视图,域对象是模型,因此应该使用某种形式的控制器模式。通常,控制器声明存储库(聚合根的集合)的具体实现和访问。 在数据访问世界中… 以LinqToSQL为例,DataContext将是控制器,它公开客户和订单实体的视图。该视图是一种非声明性的、面向框架的表类型(大致相当于存储库)。请注意,视图保持对其父控制器的引用,并且经常通过控制器来控制如何/何时实现视图。因此,控制器是您的提供者,负责映射、翻译、对象水合等。模型就是您的数据POCO。几乎是典型的MVC模式。 以n/hibernate为例,isession将是控制器,通过session.enumerable(字符串查询)或session.get(对象ID)或session.createReciteria(typeof(customer)).list()公开客户和订单实体的视图。 在商业逻辑世界中…
简而言之,让您的业务流程和事务成为指导,让您的业务基础架构随着流程/活动的实现或重构而自然地发展。此外,与传统的黑盒设计相比,更喜欢可组合性。当你开始面向服务或云计算时,你会很高兴你做到了。:) |
![]() |
5
0
我想知道结论是什么? “冲突”将成为根实体。“员工”根实体将引用“违规”。IE违规存储库<->员工存储库 但是你被认为是违反根实体,因为它没有任何行为。 但是“行为”是一个符合根实体资格的标准吗?我不这么认为。 |
![]() |
6
0
这是一个测试理解的稍微正交的问题,返回到订单……订单项示例,系统中可能有一个分析模块想要直接查看订单项,即获取特定产品的所有订单项,或者所有订单项大于某个给定值等,确实有很多像这样的用例和驱动。”聚合根”到极端,我们是否可以认为orderitem本身是一个不同的聚合根?? |
![]() |
7
0
视情况而定。变更/添加/删除变更是否会改变员工的任何部分-例如,您是否在过去3年内针对员工存储违规计数或违规计数? |
![]() |
Tony Raimo · 域实体是否应该调用存储库? 7 年前 |
![]() |
Seb · DDD只读存储库返回“值对象” 7 年前 |
![]() |
tlt · 使用嵌套对象和大集合进行聚合根优化 7 年前 |
![]() |
PatrickSJ · DDD,状态对象/值对象 7 年前 |
![]() |
msmani · DDD更改聚合根id 7 年前 |
![]() |
DuskMcDusk · 逻辑和性能中的聚合根冲突 7 年前 |