域实体,公开类似于存储库的方法

时间:2013-10-18 08:30:01

标签: domain-driven-design

举个例子。 主管域类公开了一种方法 GetUnderlings(DateTime from,DateTime to),它将返回指定主管在给定时间段内监督的所有人员。

这个方法应该出于愉快的语义原因。但是应该去其他地方获得DDD纯度。那是因为我假设要实现方法,需要使用一个Repository,这似乎是错误的嵌入域实体。在这种情况下,该方法应该在存储库或服务上 - GetUnderlings(主管主管,DateTime from,DateTime to)

其他人如何处理这种情况?

编辑:我认为这些力量可以这样描述:根据OO负责人的说法,我希望我的实体的公共接口公开一组丰富的面向业务的功能。但是根据DDD实现原理,这些方法的实现可能最好位于其他地方。例如,在服务中。

如何解决这种明显的冲突?我能看到的方式是:

  1. 让实体具有对服务或服务接口的引用
  2. 总是让客户端去服务,而不是直接到实体(结果:失去一致性,从OO的角度来看,完全不冷静)
  3. 使用“域名活动”(?)
  4. 使用一些AOP技巧将方法的实现委托给服务。

3 个答案:

答案 0 :(得分:2)

如果SupervisorAggregate Root,则从Underlings返回Supervisor列表是有效的,但只有 READONLY 集合,因为UnderlingsSupervisor修改shold以将域规则和不变量应用于修改操作。 (不仅在DDD中的基本规则,只是很好的OOP设计)

Underlings似乎是历史entity。在大多数情况下(我没有足够的上下文信息来确认您的情况)历史记录entities不是aggregate roots aggregate roots拥有存储库。

请注意,如果Undelings的检索用于UI(不应用带有规则和不变量的操作),则无需关心aggregate roots,{{1等等,因为您应该应用CQRS并使用视图服务来检索纯数据(第一范式,而不是entities)以向用户显示。当用户aggregate roots触发某个操作时,您需要检查规则(这意味着应用DDD);您从UI检索Supervisor,检查Repository(请记住,只读集合)以接受决定,应用操作并保存更改。

答案 1 :(得分:0)

常用方法是将所有Supervisor的{​​{1}}公开为只读集合。如果您需要实现按日期范围过滤它们的方法,只需将此方法添加到UnderlingsSupervisor,一切正常。

如果常见方法不起作用,因为GetUnderlings(DateTime from, DateTime to)有很多Supervisor,或者检索所有这些Underlings或者是非常耗时的。 ..有一种解决方法 - Martin Fowler的“Separated Interface”(PoEAA)模式。

您可以在域模型中的特定日期范围内定义返回Underlings的组件接口,但在另一层(例如数据访问层)中实现它。

在这种情况下,您的域名实体没有提及服务,也没有公开任何“Underlings”。所有需要获得“Underlings”服务并且将“Supervisor”实例传递到方法和日期范围的客户。

enter image description here

答案 2 :(得分:0)

如果主管属于主管总会,主管应该有一系列基础。

喜欢

class Supervisor {
    private Collection<Underlying> underlyings;
}

然后GetUnderlings(DateTime from,DateTime to)正在过滤联系人。这很好。

但如果属于主管的基础太多,则此解决方案对性能不友好。在这种情况下,我想使用make underlying一个聚合根并使用它的Repository来检索结果,如:

interface UnderlyingRepository {
      Collection<Underlying> GetUnderlings(Guid supervisorId, DateTime from, DateTime to);
}

客户端(可能是MVC控制器)直接调用存储库。那么问题是如何保护addUnderlying的不变量,这些变量曾经受到Supervisor聚合的保护。 您可以使用DomainService或DomainEvents。

上述解决方案基于传统的DDD架构模型。就像@jlvaquero所说,你可以改用CQRS。