如何在DDD中实现持久性无知?

时间:2012-12-12 09:26:36

标签: java scala domain-driven-design persistence

我正在处理涉及Workspace的项目的持久层,每个项目可能包含零个,一个或多个Document。 (我正在尝试关注Domain-Driven-Design principles,但我的问题可能与此无直接关系。)

问题1:我应该分离出持久性吗?即,您是否以可以

的方式设计实体和价值类
  • 在内存中创建实体和值,就像没有持久性(可能使用Factory方法Workspaces.newWorkspace(...))和
  • 一样
  • 调用单独的persist()方法(可能在存储库中)来处理持久性?

或者我的工厂方法Workspaces.newWorkspace()是否应该创建一个持久实体(一旦事务关闭就会持久化)?

如果这个问题的答案是“Separation,dude!”那么我想知道如何以优雅的方式实现这一目标。我的第一种方法是(在Scala伪代码中):

class Workspace(title: String, documents: List[Document], id: Option[Long]) {
  def add(d: Document) =  // ...
  def remove(d: Document) = // ...
}

但是,如果工作区可以包含许多文档,则这不是很好(受RAM限制)。我在"How not to inject services into entities"之后的下一个方法是:

class Workspace(title: String, docSupplier: DocSupplier, id: Option[Long]) {
  def add(d: Document) = docSupplier.add(d)
  def remove(d: Document) = docSupplier.remove(d)
}

有了这个,工作区工厂可以像这样创建新工作区

class Workspaces {
  def newWorkspace(title: String) = new Workspace(title,
    // A supplier that maintains a simple `List[Document]`
    new DocSupplier() {
      def add(d: Document) = list.add(d)
      def remove(d: Document) = list.remove(d)
    }, id)
}

此外,我的存储库可以重建工作区,它可以从数据库中获取,如下所示:

class WorkspaceRepository {
  def findById(id: Long) = // ... calls `createDoc()`

  def createDoc(...) = new Workspace(title,
    // A supplier that remembers changes so they can be persisted in `persist()`
    new DocSupplier() {
      def add(d: Document) = changes.rememberAdd(d)
      def remove(d: Document) = changes.rememberRemove(d)
    }, id)
}

问题2:这是这样做的方法吗?! Puh,它是很多代码,有很多样板!

1 个答案:

答案 0 :(得分:2)

  

我应该将持久性分开吗?

是的,就像你描述的那样。

  

或者我的工厂方法Workspaces.newWorkspace()应该创建一个   持久化实体(一旦交易将持久化)   闭合)?

不,因为持久化实体应该是一个显式操作,例如添加新工作区时。工厂处理对象实例的创建,存储库处理持久性。正如 pabrantes 所示,工作单元模式可以与存储库结合使用。

  

但是,如果工作区可以包含许多文档,那么这并不好   (受RAM限制)。

这是DDD中的常见情况 - 在达到持久性无知的同时,您必须考虑技术限制。首先要考虑的是Workspace实体是否需要引用Document实例的集合。是否存在Workspace需要执行的不变量?是否存在交易边界?对象引用仅为one of the ways of representing relationships。另一种方法是使用存储库。因此,您不必在Document类上拥有Workspace集合,而是提供一个存储库方法,该方法允许检索与特定工作空间关联的文档。鉴于文档的数量可能很大,存储库也可以支持分页和过滤。

另请参阅Effective Aggregate Design by Vaughn Vernon深入了解这些问题。