Anemic Domain Model: Pros/Cons

With “Anemic Domain Model” being anti-pattern, why are there so many systems that implement this?

I think there are several reasons

1. Complexity of the system

In a simple system (which is almost all the examples and sample code you find on internet) if I want to implement:

Adding product to Order

I put this function on the Order

public void Order.AddOrderLine(Product product)
{
    OrderLines.Add(new OrderLine(product));
}

Nice and super object oriented.

Now let’s say that I need to make sure that I need to validate that the product exists in inventory and throw exception if it doesn’t.

I can’t really put it on Order any longer, since I don’t want my order to be dependent on Inventory, so now it needs to go on the service

public void OrderService.AddOrderLine(Order order, Product product)
{
    if (!InventoryService.Has(product)
       throw new AddProductException

    order.AddOrderLine(product);
}

I could also pass IInventoryService to Order.AddOrderLine, which is another option, but that still makes Order dependent on InventoryService.

There is still some functionality in Order.AddOrderLine, but usually it is limited to Order scope, while in my experience there is a lot more Business Logic out of Order scope.

When the system is more then just basic CRUD, you will end up with most of your logic in OrderService and very little in Order.

2. Developer’s view of OOP

There are a lot of heated discussions on the internet about which logic should go on entities.

Something like

Order.Save

Should Order know how to save itself or not? Let’s say we have repositories for that.

Now can Order add order lines? If I try to make sense of it using simple English, it doesn’t really make sense either. User adds Product to Order, so should we do User.AddOrderLineToOrder()? That seems like overkill.

How about OrderService.AddOrderLine(). Now it kinda makes sense!

My understanding of OOP is that for encapsulation you put functions on classes where the function will need to access class’s internal state. If I need to access Order.OrderLines collection, I put Order.AddOrderLine() on Order. This way class’s internal state doesn’t get exposed.

3. IoC Containers

Systems that use IoC containers are usually fully anemic.

It is because you can test your services/repositories which have interfaces, but can’t test domain objects (easily), unless you put interfaces on all of them.

Since “IoC” is currently lauded as solution for all your programming problems, a lot of people blindly follow it and this way end up with Anemic Domain Models.

4. OOP is hard, procedural is easy

I have a bit of a “Curse of Knowledge” on this one, but I have discovered that
for newer developers having DTOs and Services is a lot easier than Rich Domain.

Possibly it is because with Rich Domain it is more difficult to know on which classes to put the logic. When to create new classes? Which patterns to use? etc..

With stateless services you just slap it in the service with closest name.

Leave a Comment