0

Eric Evan 的 DDD 书,第 页。152:

仅为实际需要直接访问的 AGGREGATE 根提供存储库。

1. 是否应该通过需要直接访问的聚合根的存储库来检索和保存不需要直接访问的聚合根?

例如,如果我们有CustomerOrder聚合根,并且无论出于何种原因我们不需要直接访问AR,那么我假设获得订单Order的唯一方法是通过遍历属性?Customer.Orders

2.什么时候应该ICustomerRepository检索订单?何时Customer检索 AR(通过ICustomerRepository.GetCustomer)或当我们遍历Customer.GetOrders属性时?

3.ICustomerRepository自己应该检索订单还是应该将此责任委托给一个IOrderRepository?如果是后者,那么一种选择是IOrderRepository注入ICustomerRepository. 但是由于外部代码甚至不应该知道它的IOrderRepository存在(如果外部代码知道它的存在,那么它也可以IOrderRepository直接使用),那么应该如何ICustomerRepository获得对IOrderREpository

更新:

1

关于实现,如果使用像 NHibernate 这样的 ORM 完成,则不需要 IOrderRepository。

a) 你是说在使用 ORM 时,我们通常不需要实现存储库,因为 ORM 隐式提供了它们?

b)我确实计划学习一种 ORM 技术(可能是 EF),但是从我读过的关于 ORM 的内容来看,似乎如果你想将域或应用层与持久层完全解耦,那么这两层不应该使用ORM 表达式,这也意味着 ORM 表达式和 POCO 应该只存在于 Repository 实现中?

c)如果存在某种情况,由于某种原因 AR root 没有直接访问权限(并且项目不使用 ORM),那么您对 ​​3. 的回答是什么?

谢谢

4

1 回答 1

3

我很难想到聚合不需要直接访问的示例。但是,我认为在撰写本文时(大约 2003 年),对限制或消除聚合之间的可遍历对象引用的强调并不像今天那样普遍。因此,Customer聚合可能会引用聚合的Order集合。在这种情况下,可能不需要Order直接引用 an,因为Customer可以接受遍历。

关于实现,如果使用像 NHibernate 这样的 ORM 完成,则不需要IOrderRepository. 聚合将Order仅具有映射。此外,映射Customer将指定更改应向下级联到相应的Order聚合。

ICustomerRepository 应该何时检索订单?

这是引起对聚合之间可遍历对象引用的关注的问题。ORM 提供的一个解决方案是延迟加载,但延迟加载可能会出现问题。理想情况下,仅在需要时才检索客户的订单,这取决于上下文。因此,我的建议是避免聚合之间的可遍历引用,而是使用存储库搜索。

更新

a) 您仍然需要实现 ICustomerRepository 的东西,但如果配置了映射,实现将非常简单——您将委托给 ORM 的 API 来实现每个存储库方法。但是,不需要 IOrderRepository。

b) 对于完全封装,存储库接口将不包含任何特定于 ORM 的内容。存储库实现将使存储库合同适应 ORM 细节。

c)很难对我无法想象的场景做出判断,但似乎不需要订单存储库接口,您仍然可以拥有一个订单存储库来更好地分离职责。也不需要注入,只需让客户 repo 实现创建一个 Order repo 实例。

于 2013-05-22T18:33:37.017 回答