Reasons to wrap a primitive type as a value object

One of common code smells is Primitive Obsession:

using primitive objects to represent domain ideas
(c2 wiki)

We refactor this smell by introducing Value Objects.

A Value Object represents a domain concept whose identity is made up of all its parts. For example, an instance FullName("Marcin", "Gryszko") of FullName(first, last) cannot be distinguished from another instance FullName("Marcin", "Gryszko"). On the hand, a (DDD) Entity has an identity composed of a single or multiple attributes. Entities are created and its existence continues as time passes. Person(SomePersonalNumberGivenAtBirth("ABC123456"), FullName("Marcin", "Gryszko") refers to the same human being, even if I change my first or last name.

Value Objects can wrap single or multiple attributes. Usually, nobody is sniffy about a Value Object with at least two attributes. It’s common sense to encapsulate cohesive attributes into a new type. But what with a single attribute? Why is it worth to invest some time to write additional code? These are my arguments I bring forward to my fellow developers.

Documentation

The same concept is repeated across many domain classes. It’s also quite important in your domain. So you lift it to a type. You give it a well understandable name. Now it’s clear that AccountId means something special in the system.

Validation

You don’t allow to sneak invalid values into your domain. Everything can be a String. But if you have an EmailAddress, you can roughly verify if the address is syntactically correct1 . Or if the HourOfDay describes a day fraction used on the planet Earth.

Format and unit of measure independence

Is this id a string or a number? Who cares! Let’s hide this information in an Id type. Is long distance in meters or in kilometres? long distanceInKm is much better. However, when we want suddenly make some calculation in inches? Wouldn’t be better that a Distance instance could hide the storage unit and have a couple of creation and conversion method (with distances in various units)?

[1] Instead to try to come up with a perfect, RFC 2822 compliant regular expression, just send a verification email. You already know that if you solve a problem with a regex, you already have two problems.

Advertisements