Domain driven design 公开类似于存储库的方法的域实体
就拿这个例子来说。主管域类公开了一个方法 获取下属(DateTime from,DateTime to)将返回给定时间段内由给定主管监督的所有人员 出于令人愉快的语义原因,该方法应该放在这里。但是为了DDD纯度应该去别的地方。这是因为我假设要实现需要使用存储库的方法,而将存储库嵌入域实体中似乎是错误的。在这种情况下,该方法应该进行响应或服务-GetUnderlines(主管-主管,DateTime-from,DateTime-to) 其他人如何处理这种情况 编辑:我认为这些力量可以这样描述:根据OO原则,我希望我的实体的公共接口能够公开一组丰富的面向业务的功能。但根据DDD实现原则,这些方法的实现最好在别处。例如,在服务中 如何解决这一明显的冲突?我可以看到的是:Domain driven design 公开类似于存储库的方法的域实体,domain-driven-design,Domain Driven Design,就拿这个例子来说。主管域类公开了一个方法 获取下属(DateTime from,DateTime to)将返回给定时间段内由给定主管监督的所有人员 出于令人愉快的语义原因,该方法应该放在这里。但是为了DDD纯度应该去别的地方。这是因为我假设要实现需要使用存储库的方法,而将存储库嵌入域实体中似乎是错误的。在这种情况下,该方法应该进行响应或服务-GetUnderlines(主管-主管,DateTime-from,DateTime-to) 其他人如何处理这种情况 编辑:我认为这些力量可以这样描述:根据
如果
Supervisor
是一个Aggregate Root
,则可以从Supervisor
返回下属
列表,但只需只读集合即可,因为下属
应该由Supervisor
修改,以将域规则和不变量应用于修改操作。(基本规则不仅适用于DDD,也适用于OOP设计)
下属
看起来像一个历史实体
。在大多数情况下(我没有足够的上下文信息来证实您的情况),历史实体
不是聚合根
,只有聚合根
有存储库
请记住,如果
取消绑定的检索是针对UI
(不应用带有规则和不变量的操作),那么您不需要关心聚合根
,实体
,等等,因为您应该应用CQR并使用view services来检索普通数据(第一个标准形式,不是聚合根
)向用户显示。当用户UI
触发操作时,您需要检查规则(即应用DDD);您从存储库
检索主管
,检查下划线
(请记住,只读集合)要做出决定,请应用操作并保存更改。一种常见的方法是将所有主管的下属作为只读集合公开。如果需要实现一种按日期范围过滤的方法,只需将此方法添加到类主管作为获取下属即可(DateTime from,DateTime to)
一切正常
如果通用方法不起作用,因为您的主管
有大量的下属
,或者检索所有这些下属
,非常耗时,或者……Martin Fowler提出了一种变通方法-“(PoEAA)模式
您可以定义一个组件接口,该接口在域模型的特定日期范围内返回下划线
,但在另一层(例如数据访问层)中实现
在这种情况下,您的域实体没有对服务的引用,并且不会公开任何“下属”。所有需要获取“下属”的客户端都会调用服务,并将“主管”的实例传递到方法和日期范围中
如果基础数据属于管理者集合,则管理者应拥有这些数据的集合
像
班主任{
私人藏品;
}
然后getUnderlines(DateTime from,DateTime to)过滤未解析项。这很好
但是,如果有太多属于主管的底层,则此解决方案对性能不友好。在这种情况下,我希望使用使底层成为聚合根并使用其存储库检索结果,如:
interface UnderlyingRepository {
Collection<Underlying> GetUnderlings(Guid supervisorId, DateTime from, DateTime to);
}
接口基础存储库{
集合getUnderlines(Guid supervisorId、DateTime from、DateTime to);
}
客户机(可能是MVC控制器)直接调用存储库,然后问题是如何保护以前由Supervisor聚合保护的AddUnderground的不变量。
您可以使用DomainService或DomainEvents
上面的解决方案基于传统的DDD架构模型。正如@jlvaquero所说,您可以使用CQRS。在这种情况下,我也会使用Service.getUnderlines(…)
。让我们等待有人写一个更深入的回复。但这仍然意味着域实体有一个对“服务”的引用接口。这实际上是我问题的关键。实体是否应该引用这样的服务(即使只是一个接口)我已经编辑了我的帖子,并指定它只能在“通用方法不起作用”时使用。首先,你应该尝试实现更简单、更可取的通用方法,然后寻找解决方法。谢谢。事实上,据我所知,你的观点并不完全正确。聚合实体中的项只能通过聚合根访问(不是通过任何其他机制)。这与一个实体不应引用不在同一聚合中的其他实体完全不同。实体可以相互关联,但不在同一聚合中。
interface UnderlyingRepository {
Collection<Underlying> GetUnderlings(Guid supervisorId, DateTime from, DateTime to);
}