Issues with service layers and domain models

design-patterns, domain-driven-design, java

Solution

First, the problem of a client calling Employee.Transfer() which you don't actually want: I like to return only DTO's from my Service Layer. These DTO's contain data and no methods. This solves the problem of a Client calling Employee.Transfer().

Next, the problem of having all code in EmploymentService.transferEmployee(). You say it doesn't feel right because it looks like procedural programming. The solution is to find a good mix between the logic you put into the Service and the logic you put into the Domain object. For example:

Domain object does:

- Check to see if it's not deleted

- Check to see if it's not already in that location

- etcetera

Service layers does:

- Load Employee

- Call Employee.Transfer

- Send email to employee

- Send email to location manager

- etcetera

I would probably use a Location Domain object in this code:

public class Location
{
   public void AddEmployee(Employee emp)
   {
      if(!IsFull)
         Employees.Add(emp);
   }

   public void RemoveEmployee(Employee emp)
   {
      Employees.Remove(emp);
      If(Employees.Count < 100)
         IsFull = false;
   }
}

Problem

I'm developing an application with a service layer that operates on a domain model. In the current design I'm passing domain objects up through the service layer (e.g. returning an `Employee` domain object when calling `EmploymentService.getEmployee()` , but require that operations performed on the objects go though the service (e.g. `EmploymentService.transferEmployee( int employeeId, int newLocationId)`. (Examples are contrived, by the way). This feels a little wrong to me. One, it seems like procedural programming. Two, the domain objects have setters like `Employee.setLocationId` that a client could invoke that of course wouldn't transfer the employee to a new location, as all of the complicated operations to coordinate different systems needed to hypothetically transfer the employee are in the service layer. I'd feel better about this if I could hide the setters from the client, but both the ServiceLayer and DAOs in different packages need to be able to access the setters of domain objects. Is this sort of thing ok, or is there a better way? (Also, any real-world examples of service layers with underlying domain models would be welcome!) Also, I've read the Anemic Domain Model anti-pattern and I don't think I'm falling into that trap, but I'm not completely sure!

Original source