Anemic Model vs Rich model

wawrzyniak

Paweł

Posted on February 17, 2024

Anemic Model vs Rich model

Anemic Model

Someday I fall into a trap and use this anemic model where I should not.

I know that hiding implementation is important.
Therefore the anemic model which has all properties available by getters and setters is not a good solution, because any programmer can call any setter and change the state of the object. Such a Class does not have any business logic, all logic is in other classes like Services or Helpers (therefore named "anemic").

Stability

It is effortless and you may ask why this is a problem.

Let's say you need to set variable is available when some condition is true (e.g. stockQuantity > 50)
If you used this setter you need to write code like this

public function changeAvaiblity() {
if (stockQuantity > 50) {
    $product->setAvaible(true);
}
...
// Product class
public function setAvaibility(bool $avaible): void {
   $this->avaible = $avaible;
}
Enter fullscreen mode Exit fullscreen mode

but how do you ensure that this condition will be covered in another part of the system?

Maybe some programmers did not go too deep and hack your solution

...
$product_service->changeAvaiblity();
...
$product->setAvaibility(true);
Enter fullscreen mode Exit fullscreen mode

As you see setters can be run at any time and change state.

Better solution

So I avoid setting via public setter but I use a private method. But there is a catch here.

Imagine I will get new business requirements, there I wrote a new function but forgot to call the function setAvaibility(true) and my state of the object is not correct.

Use the constructor to set an initial state

The best solution is to use a constructor to set the initial state and simply to avoid to situation where the state of the object is not correct.

Rich domain model

This action is a part of the Rich domain model where we create our models to avoid creating objects in incorrect states.

The purpose of the rich domain model is to create consistent classes, all variables and public interfaces of the class are consistent, and present domain logic.

To archive that, we can use e.g. Value Objects which can guard our rules.

We expose business logic methods not states of objects.
So we use


public function isAvailableForSale(): bool {
if (stockQuantity > MINIMUM_STOCK_VALUE) {
    $product->avaible = true;
}

return $this->avaible;

Enter fullscreen mode Exit fullscreen mode

In the Rich domain model, we expose behaviors. For my little example, behavior is 'Is Product available for sale' but this could be any other question

There is one more point for using rich domain models.
Testing the Rich domain model is much easier than testing the Amenic model.

When we use the Anemic model

We use them as DTOs (Data Transfer Objects) because we want only to read data and send it through e.g. in RestApi, or to send data between layers of our application or for Database entities.

Conclusion

If you need simply DTO, you can create The Anemic model.
But if there is more logic and it is not a simple CRUD you should use The Rich domain model to lean your logic on stable behaviors/contracts which are easy to test and help you to avoid introducing your objects in an incorrect state and make logic and application more consistent.

💖 💪 🙅 🚩
wawrzyniak
Paweł

Posted on February 17, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related