Treating Software Anemia

DDD pundits argue that any model does not have to be anemic. Software anemia is typically assessed by the (small) amount of behavior present in classes. In a model that is merely inferred from a database, there is usually very little behavior, making the model anemic.

Is software anemia a serious disease?

Technical Threat

In humans, anemia leads to weariness and is caused by a deficiency of red blood cells, which are responsible for delivering oxygen to the body tissues and providing vitality and energy. In a software context, anemia signifies a lack of energy to cope with changes, but it is not considered a disease. An anemic model can still function effectively if the development team is capable of managing the complexity of the domain and its evolution.

Ultimately, an anemic model is not a mistake per se but just poses a threat to your code, much like Damocles’ sword. According to the historical anecdote, Damocles sat on a throne with a massive sword hanging over him, supported only by a single hair. This serves as a fitting metaphor: everything remains fine as long as the sword remains suspended.

It’s not a certified technical debt; but a sort of technical threat that could one day (in a near time) become technical debt.

Methods over Properties

The emphasis on behavior serves two main purposes: first, creating objects with a public interface that closely resembles entities observable in the real world, and secondly, facilitating easier modeling that aligns with the names and rules of the ubiquitous language.

When modeling, a kind of back thinking drives us to focus on attributes first. Perhaps, because of our learning path often driven by the relational data model. We then mark attributes with properties with public getters and setters. At that point, having methods to alter the state of properties seems a useless extra effort.

This is precisely where the change has to happen.

A quick example is better than many, inevitably repeating words. Suppose you have a UserAccount class that models the concept of a signed-up user to some software system. The user forgets its password and the system manages to reset it. The state of the persisted user should change to host a password-reset token and the time it was requested. The user is sent an email with a link that incorporates the token. When she follows the link, the system uses the token to track back the identity, checks the expiration of the link and sets the new password. How would you code the change of state due to the initial request? Probably you would use code like this.

user.PasswordResetToken = Guid.NewGuid();
user.PasswordResetRequested = DateTime.UtcNow;

What about this, instead?

user.RequestPasswordReset();

Internally, the method includes just the two lines above that set properties. What’s the difference? You simply shifted from a data-centric vision to a behavior-centric perspective.

Where is readability? In the name of the action.

Where is maintainability? You can possibly change the way password reset is implemented by just rewriting the method and acting in one place only.

Excerpt from upcoming book Clean Architecture in .NET, Microsoft Press 2024

Published by D. Esposito

Software person since 1992

Leave a comment