How to Build a Good One Value Object (Domain-Driven Design)
By: Carlos Bueno
Tags: Ddd, Aspnetcore, Value Objects, Net Core 3, Domain Driven Design

I’m gonna write some posts on the topic of Domain Driven Design. Over the years, I’ve come to some conclusions on how to apply DDD practices in general that I hope you will find helpful. I’ll try to distill my background with it to several points which I’ll illustrate with examples. Let’s start it.

I was wondering why is so painful to many developers build a Value Object, I have seen a lot of application built using DDD approach, but in almost all cases Primitive obsession is in everywhere.

If you don’t know what is a Primitive obsession I recommend that you read the article Functional C#: Primitive obsession written by Vladimir Khorikov.

In this article, we’ll focus on Domain and learn How to build a good one Entity avoiding Primitive obsession using Value Object. Also, We’ll use DomainDrivenDesing.Core, it’s my Framework with some basics pieces of stuff of DDD that will help us in this journey.

This is how a Payment entity would be made in an ordinary way using primitives:

The problem in this sample is that when you use primitives is necessary to apply all validations rules for your domain, so it becomes painful to do because you need to put a lot of validations logic in your source that does not belong to the model.

So, instead of you pass CardNumber, CVV, and ExpirationDate as a primitive, You would create a Value Object called Card, CardNumber, CVV and ExpiryDate instead.

Let’s start with CardNumber, in this one you should inherit the class ValueObject from DomainDrivenDesign.Core, then you can use the method CheckRule. This method expects a class that had implemented the interface IValidationRule.

As you can see, you can move almost all of the validations from Entity to Card, CardNumber, CVV, and ExpirationDate Value Object classes.

Whenever you create a class that implements the interface IValidationRule you must write just a business rule there, If your Value Object has more Rules you must create more classes that implemented this interface to do it, therefore you can extend rules just adding a new Rule File, thus respecting the SOLID Open Close principle.

You need to do it for all Rules that you identify.

You need to build CVV and ExpirationDate Value Object with validations and using this Value Objects to build the Card Value Object.

For the CVV Value Object you need to create CCVShouldBeFourOrThreeDigit to validate this rule, so it looks like this one.

Now you will create ExpirationDate and Card Value Objets like those.

The other Value Object classes: Money and Beneficiary, you can see in the link provided at the end of the article, but I’ll talk about them in the next article.

So, Now you can change your Payment class using Value Objects.

Your payment class should be like this, cleaner and just doing what is its responsibility.

Summary

With non-primitive types, we are getting closer to designing applications in C# clean and easy to extend. Next time, I’ll show how to create Money Value Object and I’ll explain what is a Domain Services and show you how it works with Money Value Object.

Related video

Source code

Other articles in the series