Saturday, 2 November 2013

Where does the Application Layer end and the Domain start?


After finishing the previous post it occurred to me that there is a couple of other stuff I'd planned to say about the topic. For one I didn't give any example for how the implementation of an app service might look like. So here it goes...
You have a good old Ordering application. The Product Owner figures out he needs a new function, namely displaying the user information (name, address, ...) and her last 10 orders in one page. That's a Use Case. The client could do two calls getting the user info then the orders, but you decide to mingle it into one. Then the app service will get the User from the User Subdomain, the Orders from the Order Subdomain and build a transfer object from them. The app service's responsibility is the delegation and the assembling of the transfer object (which belongs to the app layer, not the domain!).
class UnlikelyOrderHistoryViewService {
  public UnlikelyOrderHistoryView getUnlikelyOrderHistoryView(CustomerId customerId) {
        authenticationCheck(); 
        Customer customer = getCustomerRepository().find(customerId);
        List lastXOrders = getOrderRepository().findLast(customerId, 10);
        return getUnlikelyOrderHistoryViewAssembler().assemble(customer, lastXOrders);
  }
}

Of course distinction between the domain and the application layer still needs consideration in concrete situations. For example you start with a small domain. You can create, update and search for users. The domain might consist of only a User entity and a UserRepository. Your app service only delegates to the repository and do the boilerplate stuff. Then the Product Owner starts coming up with new and new types of queries. Search by name, age, profession. All users with first name Amanda, under 26 and not an accountant, or Martha who has a dog. At first you put extra methods and new parameters in the app service(s) but as the query criteria become more and more complex, the logic starts to form a new layer with its own vocabulary (that's the breaking point) and earns the right to be called domain. By its weight it sinks down to the Domain leaving the app service lean again. Evolution. The point is, it's always a matter of balance and the demarcation lines are susceptible to shift in time. And to say something practical at the end, I've found a simple rule of thumb that often helps me decide whether the logic in the app layer has grown too fat.

Thou shalt not suffer a decision in the app layer!

Nor in the infrastructure anyway. If you see a control structure there, a foreach or especially an if { ... } else { ... }, treat it with suspicion! Always ask yourself, why does this Yes-No decision need to be here instead of the Domain? Of course they have the right to be there sometimes, but rarely.

No comments :

Post a Comment