DDD - 再生水合根?

时间:2017-07-20 22:15:18

标签: oop domain-driven-design ddd-repositories

我的所有实体都是接口的实现。他们的大部分属性都是只读的 我的存储库包含对库项目的引用,其中我保存所有接口,因此从技术上讲,存储库可以保存聚合根,而不知道任何关于它的事实上的实现(我相信是一个+1)。
这里的问题是:如果大多数属性是只读的,如何在不破坏OOP原则的情况下重新合成聚合根?存储库是否应该保留对域项目的引用并了解接口的具体实现?

2 个答案:

答案 0 :(得分:1)

  

存储库是否应该保留对域项目的引用并了解接口的具体实现?

正如埃文斯在蓝皮书中描述的那样;存储库是实现所扮演的角色,用于防止应用程序直接改变底层数据。类似地,聚合根是一个角色 - 我们不让应用程序触及实际实体,而只是它的一部分。

存储库的实现是模型的一部分,因此它可以更多地了解所表示的特定实体;包括知道如何从中提取可以传递给持久性组件进行存储的状态表示。

要选择特定的上下文,让我们假装我们正在为TradeBook建模,其中一个有趣的用例是客户下订单。 在Java中,Repository接口的实现 - 应用程序知道的位置,可能看起来像

interface API.TradeBookRepository<TradeBook extends API.TradeBook> {
    TradeBook getById(...);
    void save(TradeBook);
}

interface API.TradeBook {
    void placeOrder(...);
}

因此,应用程序知道它可以访问存储库,但是它对实现没有任何了解,但是对它的承诺 将提供支持placeOrder的某些

所以应用程序代码如下:

API.TradeBookRepository<? extends API.TradeBook> repo = ....

API.TradeBook book = repo.getById(...);
book.placeOrder(...)
repo.save(book)

但是给定的存储库实现通常与本书的特定实现相关联;他们配对在一起。

class LIFO.TradeBook implements API.TradeBook {
    ...
}

class LIFO.TradeBookRepository implements API.TradeBookRepository<LIFO.TradeBook> {
    ...
}
  

如何在不违反OOP原则的情况下对聚合根进行补水?

在某种程度上,你不能。好消息是at the boundaries, applications are not object oriented

你放入持久商店的东西不是聚合根;它是一种国家的代表。我倾向于将其视为Memento。你真正拥有的是两个函数 - 一个将特定的聚合根实现(例如:LIFO.TradeBook)转换为Memento,另一个将Memento转换为聚合根。

关键想法:您可能希望更频繁地更改域模型 lot ,而不是希望迁移数据库。因此,Memento需要设计为稳定 - 实际上,Memento是从旧域模型发送到新域的消息,因此许多lessons of message verioning适用。

答案 1 :(得分:0)

简而言之,应用程序中的某些内容必须了解具体实现。如果你真的想要保护存储库实现(而不是合同)不知道具体的实体,那么这个责任只会落在另一个协作者身上(例如,存储库会将补液委托给抽象工厂)。

但是,为聚合创建单独的合同是非常罕见的,因为您通常只有一个这些业务概念的实现,并且通常没有您希望在单元测试中模拟它们的情况。因此,存储库合同和实现大部分时间都是根据具体的聚合来定义的。