Domain Driven Design
What is Anemic Domain Model and why it can be harmful?
Anemic Domain Model is a common approach in software development that many folks don’t even know they are using it including myself. If you are using Entity Framework, there is a chance you know this approach. But do you?
What is the Anemic Domain Model?
It is a Model which separates data and operation working with them from each other. In most of the time, your domain consists of two separated classes. One is the entity, which is holding data, the other is the stateless service, which operates with an entity.
Entity is usually represented with public properties. Setters and getters. Typical example of Entity Framework entity in the .NET application can look like this:
Stateless service, as the name suggests, is represented with stateless class, which means that it contains methods only and such methods should operate only with a related entity. Its Stateless Service can look like this:
You may use more than one service class to operates with an entity. This example serves to demonstrate the idea behind the Anemic Domain Model.
Why is Anemic Domain Model harmful?
One could say that the Anemic Domain Model is not going along with Object-Oriented Design. The separation of logic into other class is just not correct in OOD approach. But it is not the primary reason why Anemic Domain Model is harmful. Having a pure OOD is not the goal in and of itself. We need to consider more fundamental reasons. There are three of them.
First is discoverability, meaning easy finding out what we could do with the object just by using IntelliSense. Lack of discoverability may lead to duplicate already existing code.
Which flows us to the second reason and that is duplication. When you don’t keep methods near to data, it is hard to say where exactly they are located. The developer forfeits the idea to write their own implementation of those methods, which results in duplicating some or all already existing logic.
The third is the lack of encapsulation and this one is worst. The first two are more easily avoid by applying codebase standards. This one, however, always has a harmful effect on your project. It is precisely the lack of encapsulation that ruins most code bases employing Anemic Domain Models.
What is encapsulation?
There are a few definitions of what encapsulation is. Some believe that encapsulation is information hiding. That is when you make some of the class members private and therefore hide them from the client code. While this is one of the means of achieving encapsulation, the information hiding is not the encapsulation per se.
Another definition you can counter is, that encapsulation means to bundle data and operations together. While this is also a way to achieve an encapsulation in object-oriented programming languages, it is not the same as encapsulation either.
Encapsulation is an act of protecting the data integrity
This is usually done by preventing clients of a class from setting the internal data into an invalid or inconsistent state. And that is where tools such as information hiding, and bundling data and operations together come helpful.
Information hiding helps you removes the internals from the eyes of its clients, so there is less risk of corrupting it.
Bundling of data and operations provides you the one entry point for all actions you do upon this class. This way you can perform all required validations and integrity checks before modifying the internal state.
As you can see, these two techniques are related to encapsulation in the sense to achieve it, but they themselves are not the end goal.
You can also think of encapsulation in terms of invariants. Each class has its own set of invariants, conditions that you can always rely upon to be true. It is your responsibility as a software developer to make sure that those invariants are valid during the execution of the program.
Why is so important to maintain the encapsulation?
It is all about complexity. The more complex the codebase becomes, the harder is to work with it, which ultimately results in the decreasing speed of development, increasing the number of bugs and damaging the ability to respond to business needs.
Just imagine that your code doesn’t guide you through what is and what is not allowed to do with it, and you must double-check repeatedly. It brings a lot of mental burden in the process of programming. You cannot trust yourself to do always the right thing and the best way to do so is by maintaining proper encapsulation so that your codebase doesn’t even provide an option for you to do anything incorrectly.
How to maintain the encapsulation with Anemic Domain Model?
An Anemic Domain Model always means a lack of encapsulation. You must expose invariants to external worlds. There doesn’t exist a proper way to make a former set of classes to avoid it. The classes of data end up to have no restrictions of how you can change them and therefore the responsibility to maintain the invariants shifts to the classes of operations, which is a very dangerous situation because you have to remember to keep all invariants intact each time you modify a class with data.
Why we are even using it?
Because it is intuitive for developers, especially the one who comes from a data background. Therefore, it is easy to implement, which can be beneficial sometimes.
But what if I want to maintain the encapsulation?
Then you should go tame a beast named Domain-Driven Design. DDD guides you on how to design your entities differently than you are used to. But this doesn’t mean that Anemic Domain Model is always the wrong approach. Look at this image below.
Graph narrates about development progress measured by spent work hours. As you can see, Anemic Domain Model projects always take off quickly, leads to an increase in maintenance costs in the future. In cases where you know that project is not going large or the project will not be developed more often, Anemic Domain Model is just fine to pick and could also be the best choice.
However, if you find yourself at the beginning of the development of enterprise application, a rich Domain Model by DDD is preferable and more recommended choice.
Is it always per project decision?
The decision of whether to deploy the Anemic Domain Model is local to a particular bounded context in your system. In some bounded context, you might want to implement an Anemic Domain Model, in others go with the rich one. Bounded context is separate from each other and you can deploy them by different strategies in each of them.
Article is heavily inspired by, in my humble opinion, one of the best Domain-Driven Design evangelist, .NET Architects and Pluralsight authors, Vladimir Khorikov and one of his courses “Refactoring from Anemic Domain Model Towards a Rich One”. If you are hungry for more information, you can easily pick up where article left off, and that is in the fourth module of the already mentioned course.
Note: You can reach me out on twitter or send me an email. I am part of the company Itixo, located in beautiful country Czechia. We are hosting the biggest .NET conference in central Europe in Prague every year named Update Conference Prague.