DDD: Repositories calling Application Services
This forms part of a series based around me getting my head around DDD :)
Following on from a previous question, but the background knowledge is not needed: System consuming WCF services from another system, when underlying databases have relationships
There is a Document System and an HR System. The HR System needs to save a document and also some HR specific data relating to the document.
My first thought was that the call to Document System should be in the Application Service of HR System (unnessacery code stripped out):
public class HRDocumentService
{
public void SaveDocument(string filename, string employee)
{
long documentLibraryId = _documentLibraryService.SaveDocument(filename);
HRDocument hrDocument = HRDocument.CreateDocument(documentLibraryId, employee);
_hrDocumentRepository.Save(hrDocum开发者_开发技巧ent);
}
}
and the Repository is like this:
public class HRDocumentRepository
{
public long Save(HRDocument hrDocument)
{
_session.Save(hrDocument);
}
}
But Jak Charlton says in this article "What Sits Behind A Repository? Pretty much anything you like. Yep, you heard it right. You could have a database, or you could have many different databases. You could use relational databases, or object databases. You could have an in memory database, or a singleton containing a list of in memory items. You could have a REST layer, or a set of SOA services, or a file system, or an in memory cache…"
So now I'm thinking the service should just be this:
public class HRDocumentService
{
public void SaveDocument(string filename, string employee)
{
HRDocument hrDocument = HRDocument.CreateDocument(documentLibraryId, employee);
_hrDocumentRepository.Save(hrDocument);
}
}
and calls to the Document Library service in the repository like this:
public class HRDocumentRepository
{
public long Save(HRDocument hrDocument)
{
long documentLibraryId = _documentLibraryService.SaveDocument(filename);
hrDocument.DocumentLibraryId = documentLibraryId;
_session.Save(hrDocument);
}
}
This way, arguably, the repsository is still only responsible for persistence.
Am I on the right lines here or way off?
It seems that repositories accessing application services from other systems is quite accepted practice. The Microsoft Application Architecture Guide advocates this in the form of a 'Service Agent', and the Jak Charlton quote above also supports it. If using NHibernate for data access, you can do this by implementing IUserType, As I mention in this post: NHibernate: Lazy loading of IUserType. It's not a universal solution - for example, it has poor performance if you are returning a collection and each entity has to make a WCF call for it's child entity. When asking about integrating systems, people often advocate messaging and CQRS, but even Udi Dahan himself claims this is not suitable for the vast majority of systems.
Domain Services sit in front of repositories and entites, therefore using the DocumentLibraryService inside HRDocumentRepository is not 'DDD conform'.
Your first thought was correct!
But the logic itself (assign some value to the entity before persist) is perfectly valid inside a repoitory, as long as you could get the information not from a service but from a repository.
Hope this helps.
Robert
精彩评论