Anemic domain model and the DAO antipattern

07/04/2011

I was recently introduced to the anemic domain model antipattern when browsing Play! framework documentation. It's an interesting topic, although there seems to be some missconceptions about it: some people say it's not really an antipattern, while others try to avoid it by falling into the DAO antipattern, where you assing persistence responsabilities to the domain objects themselves. First things first, we should clarify what is the domain model and what Martin Fowler defines as an anemic domain model. The domain model is the layer in the application that reflects the business entities that the application has to deal with. In a CRM system, they would be users, customers, quotes, contacts, etc. In Java, they are tipically contained in POJOS:


class Customer{
 
 private int id;
 private String name;

 public void setId(int id){
   this.id=id;
 }
 public int getId(){
   return id;
 }

 public void setName(String name){
   this.name=name;
 }
 public String getName(){
   return name;
 }
}

But nothing prevents us from storing the domain model in plain old arrays. It's not usually the case in Java, but is more often found in PHP or other dynamic languages:

 

 $customer = array( 'name' => 'Foo');

So, what is the problem, and why is it an antipattern? The problem here is that normally, you'd have a service layer that operates with the domain object model, making operations with it and chaning its state, which leads to poor OOP and to more procedural programming. Imagine we have a ContratcService which creates contracts for a given customer. In an anemic data model, it would look like this:



public class ContractService(){

  public void createContract(Customer customer, Contract contract){
      customer.getContracts().add(contract);
      if(customer.getContracts().size()> 100){
         customer.setVIPCustomer(true);
         customer.setDiscount(Discount.MAX_DISCOUNT);
      }
 }
}

So Customer class just acts as a dumb container of data. It doesn't do anything else, and all the business logic is placed in the service layer. Instead, the logic that sets the VIP property and the discount should live in the customer class. In this way, the customer class should know that if he has more than 100 contracts, he is a VIP, and he also gets some specific discount. That would make it a rich domain model. This doesn't mean all responsability has to be moved to the domain objects, and this is where the DAO antipattern comes in: you might be tempted to move the persistence layer into the domain model (meaning a Customer class that knows how to persist itself, so we could write things like cusomter.save()). This violates the single-responsability principle: The domain model should only take care of its data, and and the logic that affects it. Does all this mean that frameworks like Play! or Ruby on Rails are falling into the DAO antipattern? Well, the way I see it, yes and no. Yes, because they are assigning persistence responsabilities to model instances. But no, because what Rails calls a model is not really a pure conceptual model object: it is the model and the DAO layer glued together. This layer is responsible for persistence, so in this cases we are obviously not falling into the DAO antipattern. This last point arises another one: It's all about what you understand as the domain model. If your understanding of the domain model is the domain pojos themselves and the service layer (which would be responsible for dealing with business logic), then the anemic domain model antipattern is automatically gone. I personally preffer though to put the domain model out of the service layer, the same way I preffer putting the domain model out of the persistence layer. The really important question here is.. are you happy with the way you are implementing separation of concerns?