Anemic vs rich domain objects
Like many of you googling this or reading this topic, I did not anticipate there will be a debate in the team on how domain objects should be created and goes in them, until recently. But either side you are from, I hope I can give you a more holistic view, and really help you make better decisions.
Anemic Domain Object
To start with the anemic domain object wasn't something new, it exists since the first programming languages were created, and is a common pattern in procedural programming, where you have a clean separation of business logic and domain model, in which the domain objects are created as "dumb" and "simple" objects representing the business domain, whereas the business functionalities will be handled by "services".
The use of anemic domain object is not just unique to procedural programming, but also in object-oriented languages as well. You can easily find traces of it in POJO (Plain Old Java Object), which basically defines an entity, in early 2000. A typical example is the creation of an "employee" object in various programming language training materials or CS101. And there is a good reason for that, because it's really simple to model and use POJO to access database. So does the usage in Java Beans, which basically follows the same trait, but with some differences in comparison to POJO.
Furthermore, if you have used any MVC or MVVM framework since early 2000, it shouldn't be hard to empathise with the use of anemic domain object. As a matter of fact, by promoting the use of DTO (data transfer object), it really keeps the boundary clear and makes application easy to read and understand.
The advantages of using anemic domain object are:
- It encapsulates and represents the business domain
- It does not lead to the leaking of information or over-subscription of dependencies
- It is easy to reason about
And finally, this pattern is programming paradigm agnostic and is achieved by good programming discipline.
Rich Domain Object
For that last reason, it gives a stark difference to rich domain objects.
Some would argue rich domain object will naturally occur when doing object-oriented programming, because an object does not only contain the domain model, but also, it's capable of performing more heavy lifting, which is exactly what object-oriented programming languages were designed to do.
That view is reinforced by DDD (domain-driven design), which actively promotes the use of thin service layer that is responsible for the orchestration and delegation of work to rich domain objects, which completes the actual business logic, and is stateful.
There are advantages to this approach too:
- It makes full use of object-oriented language feature, and amplify the benefit of DDD
- The system centres around rich stateful domain objects rather than procedures
Compromises
So both paradigms sound good, why the big fuss talking about it?
First off, there is a reason why the anemic domain object was given such a biased name, and indeed for the reasons given for pro-rich domain objects, the anemic approach seems really inadequate in using object-oriented language features, especially in the context of DDD.
But simplicity is the key to better readability and maintainability, and not everyone is a fan of DDD or stateful objects, that's not to mention the pain reasoning with stateful objects and testing them. As soon as the dependencies being brought into the rich domain object to perform various dubious tasks, such as invoking other services or persisting, a small leap of faith could soon become outrageous.
So when do we draw the boundaries and really make the most of both worlds?
- For responsibilities, such as validation, calculation, and business logic or rules, they can happily reside in a domain object, as long as it does not contradict SOLID principle.
- When requiring external integrations, like accessing a database, calling external services, or presentation, a single-responsibility service layer should be created for that purpose, rather than being a responsibility of the domain object.
Comments
Post a Comment