Domain Driven Design: Domain Service, Application Service
Can someone explain the difference between domain and application services by providing some examples? And, if a service is a domain service, would I put the actual implementation of this service within the domain assembly and if so, would I also inject repositories into that domain service? Some info would be really helpful.
Services come in 3 flavours: Domain Services, Application Services, and Infrastructure Services.
- Domain Services : Encapsulates business logic that doesn't naturally fit within a domain object, and are NOT typical CRUD operations – those would belong to a Repository.
- Application Services : Used by external consumers to talk to your system (think Web Services). If consumers need access to CRUD operations, they would be exposed here.
- Infrastructure Services : Used to abstract technical concerns (e.g. MSMQ, email provider, etc).
Keeping Domain Services along with your Domain Objects is sensible – they are all focused on domain logic. And yes, you can inject Repositories into your Services.
Application Services will typically use both Domain Services and Repositories to deal with external requests.
Hope that helps!
(If you don't feel like reading, there's a summary at the bottom :-)
I too have struggled with the precise definition of application services. Although Vijay's answer was very helpful to my thinking process a month ago, I have come to disagree with part of it.
Other resources
There's very little information about application services. Subjects like aggregate roots, repositories and domain services are discussed extensively, but application services are only mentioned briefly or left out altogether.
The MSDN Magazine article An Introduction To Domain-Driven Design describes application services as a way to transform and/or expose your domain model to external clients, e.g. as a WCF service. This is how Vijay describes application services too. From this point of view, application services are an interface to your domain.
Jeffrey Palermo's articles on the Onion Architecture (part one, two and three) are a good read. He treats application services as application-level concepts, such as a user's session. Although this is closer to my understanding of application services, it's still not in line with my thoughts on the subject.
My thoughts
I have come to think of application services as dependencies provided by the application. In this case the application could be a desktop application or a WCF service.
Domain
Time for an example. You start out with your domain. All entities and any domain services that don't depend on external resources are implemented here. Any domain concepts that depend on external resources are defined by an interface. Here is a possible solution layout (project name in bold):
My Solution - My.Product.Core (My.Product.dll) - DomainServices IExchangeRateService Product ProductFactory IProductRepository
The Product
and ProductFactory
classes have been implemented in the core assembly. The IProductRepository
is something that is probably backed by a database. The implementation of this is not the domain's concern and is therefore defined by an interface.
For now, we'll focus on the IExchangeRateService
. The business logic for this service is implemented by an external web service. However, its concept is still part of the domain and is represented by this interface.
Infrastructure
The implementation of the external dependencies are part of the application's infrastructure:
My Solution + My.Product.Core (My.Product.dll) - My.Product.Infrastructure (My.Product.Infrastructure.dll) - DomainServices XEExchangeRateService SqlServerProductRepository
XEExchangeRateService
implements the IExchangeRateService
domain service by communicating with xe.com. This implementation can be used by your applications that utilize your domain model, by including the infrastructure assembly.
Application
Note that I haven't mentioned application services yet. We'll look at those now. Let's say we want to provide an IExchangeRateService
implementation that uses a cache for speedy lookups. The outline of this decorator class could look like this.
public class CachingExchangeRateService : IExchangeRateService
{
private IExchangeRateService service;
private ICache cache;
public CachingExchangeRateService(IExchangeRateService service, ICache cache)
{
this.service = service;
this.cache = cache;
}
// Implementation that utilizes the provided service and cache.
}
Notice the ICache
parameter? This concept is not part of our domain, so it's not a domain service. It's an application service. It's a dependency of our infrastructure that may be provided by the application. Let's introduce an application that demonstrates this:
My Solution - My.Product.Core (My.Product.dll) - DomainServices IExchangeRateService Product ProductFactory IProductRepository - My.Product.Infrastructure (My.Product.Infrastructure.dll) - ApplicationServices ICache - DomainServices CachingExchangeRateService XEExchangeRateService SqlServerProductRepository - My.Product.WcfService (My.Product.WcfService.dll) - ApplicationServices MemcachedCache IMyWcfService.cs + MyWcfService.svc + Web.config
This all comes together in the application like this:
// Set up all the dependencies and register them in the IoC container.
var service = new XEExchangeRateService();
var cache = new MemcachedCache();
var cachingService = new CachingExchangeRateService(service, cache);
ServiceLocator.For<IExchangeRateService>().Use(cachingService);
Summary
A complete application consists of three major layers:
- domain
- infrastructure
- application
The domain layer contains the domain entities and stand-alone domain services. Any domain concepts (this includes domain services, but also repositories) that depend on external resources, are defined by interfaces.
The infrastructure layer contains the implementation of the interfaces from the domain layer. These implementations may introduce new non-domain dependencies that have to be provided the application. These are the application services and are represented by interfaces.
The application layer contains the implementation of the application services. The application layer may also contain additional implementations of domain interfaces, if the implementations provided by the infrastructure layer are not sufficient.
Although this perspective may not match with the general DDD definition of services, it does separate the domain from the application and allows you to share the domain (and infrastructure) assembly between several applications.
The best resource that helped me understand the difference between an Application Service and a Domain Service was the java implementation of Eric Evans' cargo example, found here. If you donwload it, you can check out the internals of RoutingService (a Domain Service) and the BookingService, CargoInspectionService (which are Application Services).
My 'aha' moment was triggered by two things:
-
Reading the description of the Services in the link above, more precisely this sentence:
Domain services are expressed in terms of the ubiquitous language and the domain types, i.e. the method arguments and the return values are proper domain classes.
-
Reading this blog post, especially this part:
What I find a big help in separating the apples from the oranges is thinking in terms of application workflow. All logic concerning the application workflow typically end up being Application Services factored into the Application Layer, whereas concepts from the domain that don’t seem to fit as model objects end up forming one or more Domain Services.
From the Red Book (Implementing Domain Driven Design, by Vaughn Vernon), this is how I understand the concepts:
Domain objects (entities and value objects) encapsulate behavior required by the (sub)domain, making it natural, expressive, and understandable.
Domain services encapsulate such behaviors that do not fit in a single domain object. For example, a book library lending a Book
to a Client
(with corresponding Inventory
changes) might do so from a domain service.
Application services handle the flow of use cases, including any additional concerns needed on top of the domain's. It often exposes such methods through its API, for consumption by external clients. To build on our previous example, our application service might expose a method LendBookToClient(Guid bookGuid, Guid clientGuid)
that:
- Retrieves the
Client
. - Confirms its permissions. (Note how we have kept our domain model free of security / user management concerns. Such pollution could lead to many problems. Instead, we fulfill this technical requirement here, in our application service.)
- Retrieves the
Book
. - Calls the domain service (passing the
Client
andBook
) to handle the actual domain logic of lending the book to the client. For instance, I imagine that confirming the book's availability is definitely part of the domain logic.
An application service should generally have a very simple flow. Complex application service flows often indicate that domain logic has leaked out of the domain.
As you can hopefully see, the domain model stays very clean this way, and is easy to understand and discuss with the domain experts, because it only contains its own, actual business concerns. The application flow, on the other hand, is also much easier to manage, since it is relieved of domain concerns, and becomes concise, and straightforward.
Domain service is the extension of the domain. It should be seen only in the context of the domain. This is not some user action like for instance close account or something. The domain service fits where there is no state. Otherwise it would be a domain object. Domain service does something which makes sense only when being done with other collaborators (domain objects or other services). And that making sense is the responsibility of another layer.
Application service is that layer which initializes and oversees interaction between the domain objects and services. The flow is generally like this: get domain object (or objects) from repository, execute an action and put it (them) back there (or not). It can do more - for instance it can check whether a domain object exists or not and throw exceptions accordingly. So it lets the user interact with the application (and this is probably where its name originates from) - by manipulating domain objects and services. Application services should generally represent all possible use cases. Probably the best thing you can do before thinking about the domain is to create application service interfaces what will give you a much better insight in what you're really trying to do. Having such knowledge enables you to focus on the domain.
Repositories can generally speaking be injected into domain services but this is rather rare scenario. It is the application layer who does it most of the time though.