On the DDD user group, there has been endless discussions about whether a service or repository can be directly called by classes that are part of the domain model. There is a group of people that believe that this is just fine and then there are a group of people who believe that this violates encapsulation and the very nature of a centralized domain model.
I’m definitely in the second group of people. I believe that domain models can be seen like the kernel of an operating system. It is completely and utterly decoupled from the rest of the application. There are only afferent couplings, no efferent couplings in my DDD book ;-).
However, I do recognize that there are some scenarios where there is a need for calling a service or a repository from the domain model. In fact, I came across this urge in our previous sprint. During the execution of some business logic, its possible that something needs to be resolved by an infrastructure service. How did I keep the domain model decoupled from this infrastructure concern. Domain events!
Udi has written about How to create fully encapsulated Domain Models in the past (make sure to read the comments) and has further refined this approach in one of his latest articles.
I must admit that the solution I applied for achieving multi-threading and dealing with memory leaks is less elegant, but certainly equivalent. But hey, that’s what refactoring is for :-).
1 for the second group. Aside from domain events, I have also seen some nice approaches using a domain service interface, and then having the domain service call out to the infrastructure.
public class DomainWidget
{
public void Do(IDomainService domainService)
{
domainService.ThisMayHitAnInfrastructureService(this.SomeGoodData);
}
}
I guess I would still call this decoupled?
Its the eternal discussion and blurred line between when to choose between interfaces and events. Both are indeed decoupled. I like events because then I don’t have to pass a reference to an interface. Its a matter of taste I guess.