I am working on the persistence layer of a project that involves Workspace
's, each of which may contain zero, one, or more Document
's. (I am trying to follow Domain-Driven-Design principles but my questions may not be directly related to this.)
Question 1: Should I separate out persistence? I.e., do you design you entity and value classes in such a way that you can
- Create entities and values in memory, just as you would do without persistence (possibly using a Factory method
Workspaces.newWorkspace(...)
), and - Call a separate
persist()
method (possibly in a Repository) to take care of persistence?
Or should my factory method Workspaces.newWorkspace()
create a persisted entity (which will be persisted once the transaction closes)?
If the answer to this question is "Separation, dude!" then I wonder how to accomplish this in an elegant way. My first approach was (in Scala pseudocode):
class Workspace(title: String, documents: List[Document], id: Option[Long]) {
def add(d: Document) = // ...
def remove(d: Document) = // ...
}
However, if a workspace can have many documents, this is not good (limited by RAM). My next approach, following "How not to inject services into entities", was this:
class Workspace(title: String, docSupplier: DocSupplier, id: Option[Long]) {
def add(d: Document) = docSupplier.add(d)
def remove(d: Document) = docSupplier.remove(d)
}
With this, the workspace factory can create new workspaces like this:
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)
}
Also, my repository can reconstruct workspaces it fetches from the database like this:
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)
}
Question 2: Is this the way to do this?! Puh, it's a lot of code, with a lot of boilerplate!