I would like to know what the pros and cons are for using an Anemic Domain Model (see link below).
Fowler Article
Why is Anemic Domain Model harmful? One could say that the Anemic Domain Model is not going along with Object-Oriented Design. The separation of logic into other class is just not correct in OOD approach. But it is not the primary reason why Anemic Domain Model is harmful.
The Anemic domain model is a programming Anti-pattern where the domain objects contain little or no business logic like validations, calculations, rules, and so forth. The business logic is thus baked into the architecture of the program itself, making refactoring and maintenance more difficult and time-consuming.
In object-oriented programming, and especially in Domain-Driven Design, objects are said to be anemic if they have state but lack behavior. Some kinds of objects, such as Data Transfer Objects (DTOs), are expected to simply be a collection of data.
Anemic domain model is nothing more but entities represented by classes containing only data and connections to other entities. These classes lack of the business logic, which usually is placed in services, utils, helpers etc.
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.
The pros:
The cons:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With