0

我正在研究一个涉及Workspace's 的项目的持久层,其中每个可能包含零个、一个或多个Document's。(我正在尝试遵循领域驱动设计原则,但我的问题可能与此没有直接关系。)

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

  • 在内存中创建实体和值,就像没有持久性一样(可能使用工厂方法Workspaces.newWorkspace(...)),并且
  • 调用一个单独的persist()方法(可能在存储库中)来处理持久性?

或者我的工厂方法应该Workspaces.newWorkspace()创建一个持久化实体(一旦事务关闭,它将被持久化)?

如果这个问题的答案是“分离,伙计!” 然后我想知道如何以优雅的方式完成此任务。我的第一种方法是(在Scala伪代码中):

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

但是,如果一个工作区可以有很多文档,那就不好了(受 RAM 限制)。我遵循“如何不将服务注入实体”的下一个方法是:

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:这是这样做的方法吗?!嗯,这是很多代码,有很多样板!

4

1 回答 1

2

我应该把持久性分开吗?

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

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

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

但是,如果一个工作区可以有很多文档,那就不好了(受 RAM 限制)。

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

还可以查看Vaughn Vernon 的 Effective Aggregate Design以深入处理这些问题。

于 2012-12-12T19:54:26.527 回答