Peter Veentjer published his second post on Domain-Driven Design in which he questions the need for a Service Layer. First, the Service Layer is what Eric Evans calls the Application Layer. Let’s see what Eric has to say about this particular layer in his excellent book Domain-Driven Design.
Application Layer [his name for Service Layer]: Defines the jobs the software is supposed to do and directs the expressive domain objects to work out problems. The tasks this layer is responsible for are meaningful to the business or necessary for interaction with the application layers of other systems. This layer is kept thin. It does not contain business rules or knowledge, but only coordinates tasks and delegates work to collaborations of domain objects in the next layer down. It does not have state reflecting the business situation, but it can have state that reflects the progress of a task for the user or the program.
According to Peter the Application Layer is still very useful for security, transactions, decoupling and as a facility to store application logic. I’m not sure about the security and transactions in the service layer since it leads to the problem of not isolating the domain. The all seeing eye Frans Bouma responded with:
How can the Application Layer coordinate tasks and delegate work if it doesn’t contain business rules?
Let’s concentrate on DDD and the patterns that play a role in this discussion: Application Layer, Domain Layer, Infrastructure Layer, Application Service, Domain Service, and Infrastructure Service. With these patterns in mind I tend to agree with Eric that it is straightforward to identity Infrastructure Services, but significantly harder to distinguish Application from Domain services. 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. Otherwise you’ll be definitely messing up a real model object which, in my opinion, has been done in Peter’s example. Human Resource Management fires people, since they are the ones that know the details about the “firing policy”, that is, assuming I am the domain expert in this case. To capture this important domain concept I would introduce the HrmService, Domain Service in the Domain Layer. This way the Application Layer does not contain any domain/business related logic and focuses on the application logic only.
The Application Layer isn’t mandatory; it is only there if it really adds value. Since my Domain Layer is so much richer than before, it’s often not interesting with the Application Layer.
Right on the spot! So, the question remains: when do we need an Application Layer and Application Services? Imagine we need to build an application on top of our Domain Model using the HrmService, Domain Service to accept an employee-firing request from this big SAP system. It requires the HrmService to determine whether it’s possible to fire the given employee by interacting with the necessary Employee, EmployeeFile, ContractFile and FirePolicy objects. We also need to communicate the advice by sending e-mails, letters and other communications for which we use the Infrastructure Layer. We now have captured a small part of the application workflow which fits nicely inside the Application Layer. Now part of the Application Layer’s responsibility is to digest the employee-firing request and send a message to the HrmService, Domain Service for fulfillment. It then decides to send notifications to the Infrastructure Service.
It’s important to note that the domain layer isn’t being distracted from representing the important concepts of the business, a healthy heart I'd say!