我正在处理涉及Workspace
的项目的持久层,每个项目可能包含零个,一个或多个Document
。 (我正在尝试关注Domain-Driven-Design principles,但我的问题可能与此无直接关系。)
问题1:我应该分离出持久性吗?即,您是否以可以
的方式设计实体和价值类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,它是很多代码,有很多样板!
答案 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深入了解这些问题。