19

Anemic domain model was criticized a long time ago by Evans and Fowler, since apparently it goes against object oriented principles, etc. The DDD community is clearly aligned with this statements.

However, in recent years there have been disagreeing voices claiming it's not an antipattern at all and that it is an example of following SOLID principles.

I have been working for so many years using Spring Framework. Every project in every company has always had a service layer containing the business logic, using repositories that operate on anemic models (JPA entities). Furthermore, most of the samples, even the official ones from the Spring guys, showcase this way of working.

My questions are: is anemic domain model still considered an antipattern? Have we all been doing things (regarding DDD) wrong? Don't you think that having Rich Domain models violates the SOLID principles?

3 Answers3

15

ADM is a good pattern for a solution of distributed services such a microservices. It fits many of today's web based business cases.

Consider if we have an Order Domain object. With an OOP approach we would add Order.Purchase() Order.Cancel() etc. It would work well in a desktop app, where we hold orders in memory and do multiple things to the same instance.

But if we have a distributed system, with programs which just to one thing, ie access a list of orders and purchase each one in turn, or get a list of orders and cancel each in turn then having both Methods on the same object makes no sense. We would have to have two Domains or Bounded Contexts:

PurchaseSystemOrder.Purchase()

and

CancelSystemOrder.Cancel();

The only thing these objects would share would be the data structure of properties.

As you add more and more microservices, you end up with dozens of types of Order. It no longer makes sense to talk about an Order as a Domain object, even though its the same conceptual order which is being processed by all these systems.

It makes far more sense to have an Anaemic model, Order, which just encapsulates just the data and to rename your services accordingly:

PurchaseService.Purchase(Order order)

Now we can talk about Order again and we can add whatever new services we think up to process the, without affecting the other currently deployed services.

Fowler and Co come from a monolith system background, in their world an ADM approach would mean a single app with all these separate services instantiated in memory and the OrderDTO being passed around and mutated. This would be far worse than putting the methods on a rich Order model.

But in a distributed system, there are many programs, each only requires a single Order method and runs it on multiple orders, loading each, running the method and then discarding it. It only requires a single Service and a stream of data objects.

Populating a rich model fully, worrying about the requirements and dependencies of all the Methods only to call a single one and then discard the object almost immediately is pointless.

Plus a change to a single one of the methods would require updating all the distributed components as they all depend on the Rich Model for their logic.

I have no room in my code base(s) for stuff they don't need

Ewan
  • 83,178
5

SOLID and DDD are orthogonal to each other, meaning they are really going in different directions from each other. You shouldn’t say that one is used to the exclusion of the other, since they can and should probably exist together in the same codebase.

Anemic domain models only become an anti-pattern once your problem domain has lots of behavior and you have hundreds of service methods with lots of copy-pasted logic or dependencies where service layer methods have to call other service layer methods to get anything done.

DDD is an excellent paradigm for micro-services because of the bounded context concept.

Beware the temptation to see infrastructure code as part of your domain. Infrastructure code is anything that you didn’t write yourself or anything that is coupled to a framework or library that interacts with a third-party system. Database connections, SMTP mailers, ORM libraries, application server run times, all that stuff is infrastructure and you shouldn’t include or depend on it in your domain if you can avoid it.

SOLID principles are a set of general purpose OOP concepts that you can use to make better OOP code. You can write a good DDD codebase using them.

RibaldEddie
  • 3,303
0

A rich domain is nice when done well. A nightmare when not. An anemic domain is always bad. But its a familiar comfortable kind of bad.

If an anemic domain is all you ever want you chose the wrong language when you chose a general purpose language. 4th generation languages specialize around a specific use. If anemic is good enough using them would have made your life easier.

Many frameworks worm their way into the language space until you can't advertise the job as a java job anymore. It's a Java/Spring job. What they're doing, besides making you depend on them, is turn a general purpose language into a bastard form of a 4th generation language.

Is that a best practice or an anti pattern? Well your boss mostly just cares about whether you can hire people to work on the code base. So if we have to pretend we're using a general purpose language to hire people we will.

If your ok with that then fine. You certainly aren't the only one.

But don't tell me that's how it has to be. Don't tell me it's doing anything for me more than it is. I know how to live without it. I know how to push it out so only a few things depend on it. If you're asking me to give in and let it take over everything just because fighting it is to hard then yeah I think that's bad.

I have no room in my code base for stuff it doesn't need.

As for SOLID and the other design principles I can largely follow those even in an anemic domain. Not following them causes a different kind of problem.

candied_orange
  • 119,268