Intro
An anemic domain model happens when your domain model is mostly focused on storing data and has very little business logic or behavior. This can occur when the design of your database heavily influences how you structure your code. Instead of creating a model that reflects the actual business rules and logic, you end up with simple data containers (like classes with only getters and setters) while the business logic is scattered elsewhere, often in services. This makes the code harder to maintain and less aligned with the real-world problems it’s supposed to solve.
The example of anemic domain model is shown below
public class Customer {
private String name;
private String email;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
You may say that this is just a POJO that widely used everywhere. The tricky moment here is how to combine these two concepts?
From one side, you should use POJO in cases of:
- when POJOs are used as DTOs to move data between different layers (e.g., from the database to the application or between services). The primary concern here is that we are focused on transporting data instead of class behaviour
- framework integration (JPA, Hibernate, Spring MVC, etc), like when we use POJOs to as requests / response objects, map database record, etc
From another side, you wan’t to have a rich domain model with its benefits.
Solving problem with Data Access Mappers (transferring data from / to database)
To solve this “problem” we need to implement the additional layer of the code – Data Access Mappers, see explanation below.
In this code, we still use POJOs as “Entity” classes for transferring data from / to database – https://github.com/kostiapl/food-ordering-system/blob/master/payment-service/payment-dataaccess/src/main/java/com/food/ordering/system/payment/service/dataaccess/creditentry/entity/CreditEntryEntity.java
and then in Data Access Mappers, like CreditEntryDataAccessMapper – https://github.com/kostiapl/food-ordering-system/blob/master/payment-service/payment-dataaccess/src/main/java/com/food/ordering/system/payment/service/dataaccess/creditentry/mapper/CreditEntryDataAccessMapper.java, we convert these “anemic models” to domain objects, “rich java objects” that have “rich business logic”, see class
public class CreditEntry extends BaseEntity<CreditEntryId> {
and vice versa.
In this way, we have rich Java classes on one side, which are widely recommended, including in DDD, and still maintain POJO classes for use in JPA. We just need to add an additional layer of logic (data mappers) to accomplish our goals.