There are a lot of discussions about rich and anemic domain models. Some developers tend to praise the anemic model, because of it’s simplicity while other blame the anemic model for it’s simplicity and they pray for the rich domain model.

In this blog I want to show both models, the advantages and disadvantages that come with each model to give you a decision and discussion basis.

The anemic model

An anemic model is a domain model that doesn’t contain any logic. That is why the model is called anemic. It is just a container for data that can be changed and interpreted by clients. Therefore all logic is placed outside the domain objects in an anemic model.

Let’s take a look at a simple anemic model.

 

When using anemic domain models the logic to alter and interprete the data must be placed somewhere else. Most times the logic is placed in classes named Service, Util, Helper or Manager. I guess the naming depends on what sounds more freaky and is up to date. Service-oriented architectures are up to date and therefore the classes are often named Service. But these classes often have nothing in common with the services in a service-oriented architecture. Serivces in a service-oriented architecture are usually application services that encapsulate use cases. Take a look at the Service Layer, Martin Fowler for details… ok but let’s get back to the anemic domain models.

From an architectural perspective the “services” that hold the business logic in an anemic domain model are transaction scripts. The only difference to plain transaction scripts is often that they use parameter objects that are named after doamin objects.

An anemic domain service for calculating the total of an order might look like:

You might think that this is a clear, simple design and straight forward. Of course it is straight forward, because it is procedural programming. It’s simplicity is also it’s achilles, because an anemic model can never gurantee it’s correctness at any time. An anemic model has no logic that ensures that it is in a legal state at any time. E.g. the order object does not react to changes of it’s item list and can therefore not update it’s total.
The main problem with anemic models is that they are contradictory with fundamental object-oriented principles like: encapsulation, information hiding.

Objects combine data and logic while anemic models separate them.

The following example shows why an anemic model can never gurantee that it is in a legal state.

 

Another interesting point is that the services that hold the logic are independent from a domain object instance – they are stateless. While some developer think that “stateless” is always a good idea, I want to show you now why it is not “always”.

The interpretation of the data is done by the stateless service. While the service is stateless it can’t know when it is time to execute the logic and when not. In more detail: The stateless service can not cache the values it calculated unlike the rich domain object. A rich domain object handles it’s state changes and therefore knows when it has to recalculate a property’s value.

At least an anemic domain model is not object-oriented programming and like martin fowler says:

At its worst business logic can be very complex. Rules and logic describe many different cases and slants of behavior, and it’s this complexity that objects were designed to work with.
Enterprise Application Architecture, Domain Model, Martin Fowler, http://martinfowler.com/eaaCatalog/domainModel.html

Anemic models are procedural programming

When you look at the anemic models you will recognize that this pattern is very old. Anemic models are procedural programming.
In the early days of programming the order example would have been implemented this way:

If you compare source 4 with source 3 you will recognize that the style is very very similar.

Using anemic domain models means using procedural programming. Procedural programming is straight forward, but hard to understand if you want to understand the state handling of an application. Furthermore the anemic domain model moves the logic of state handling and data interpretation to the clients and this often results in code duplication or in very fine grained services. Ending up with a lot of services and service methods that are interconected in a wide spread and complicated object net. This makes it hard to find out why an object is in a certain state. To find out why an object is in a certain state means that you have to find the method call hierarchy that the object has been passed through and every place that modified the object.

The rich domain model

In contrast to the anemic domain model the rich domain model follows the object-oriented principles. Therefore a rich domain model is really object-oriented programming.
The purpose of a rich domain model or of object-oriented programming is to bring data and logic together. Take a look at the principles of object-oriented programming for details.

Object oriented means that: an object manages it’s state and gurantees that it is in a legal state at any time.

The “Order” class shown in source 1 can be easily transformed to an object oriented version.

The advantage of an object-oriented programming is that an object can garantee that it is in a legal state at any time and that no “Service” class is needed anymore.
A test case will show the difference to source “anemic models can not gurantee that they are in a legal state at any time“.

 

Which model to use?

Developers often argue about the model an application should use.

My opinion is that an application should use the object-oriented approach as much as possible. The advantage of object-oriented programming is that an object can gurantee that it is in a legal state at any time. These gurantees or constraints are needed if you want to gurantee that the whole application is always in a legal (expected) state. This is a good way for an application, a web service, a library or a simple class to gurantee it’s API. API constraints reduce the complexity of a client, because the client must not check all possible states, it can count on what the API declares.
If you go the other way and build up an application on anemic models your application will become unmaintainable sooner or later.
Starting with an anemic model can be easy, but refactor an application towards a rich domain model architecture later can be cumbersome and fail prone. In most cases this is not feasible and therefore will never be done.

That’s why I believe in object-oriented programming and rich domain models.

References

 


Recommended Reading