JS Value Objects – 1. The Concept

This post is part of a series about the use of Value Objects in JavaScript.

The Value Object (VO) have been around for quite some time (in fact, Dirk Riehle and co wrote an article in 1999 about the use of VOs in Systems), but I did not see a lot of functional implementations in web development. And especially in JavaScript it never crossed my path. In this series of posts I will explore the use of this design pattern in the awesome langue we call JavaScript.

“An object that represents a descriptive aspect of the domain with no conceptual identity is called a VALUE OBJECT. VALUE OBJECTS are instantiated to represent elements of the design that we care about only for what they are, not who or which they are.” – Eric Evans

In this post I will try to explain the use of VOs. Why do we need it? I like to use examples and I will use PHP code in this post, because the language supports an easier implementation than JavaScript (and using JS would spoil the fun for the next posts).

We have a problem…

Our system has users and a user can only exist with an email-address. We model this by creating a class User that requires an argument email in the constructor.

This would work. We will be sure that an user will always have an email-address when it is stored, because it can not be instantiated without one. Creating a new user would look something like this:

But our product owner suddenly decides that a user needs a valid email-addresses (. This means our rule changes: A user can only exist with a valid email-address.

When a new user is created we will validate if it is passed a valid email-address, if not it will throw an exception making sure it can simply not exist without one. This gives us the advantage that whenever we want to interact with a User model in our system, we now for sure that the user is valid.

Note: In my opinion this way (validation during construction) is favored over validation during storage. Some might argue that you would want to create a User (e.g. from a form post) and then validate its properties from the model itself. I agree that you would want the model to describe the “rules of existence” (validation rules), but that also means the model should not be able to exist if they are not met. Because of that I would prefer validation in the constructor and an exception thrown when it fails.

But lets say we want to give the user the ability to change his email-address. This puts us in a difficult position because we need to validate the changed email-address again. But luckily we now DRY:

Going well so far, but our product owner wants a new feature in the system: Users can register their own company. A company has a name and (you guessed it!) an email-address. What to do with validation now? We can not simply copy the method setEmail to the Company class, because that’s bad coding. We could instead create a helper-class or a Validator service that does the job for us, but that would make everything only more complex and harder to read.

Value Object to the rescue!

We can see email-address as an abstraction; a single concept. We said before that a String describes any piece of text. In the same way an EmailAddress would describe a string that contains a valid email-address. We could model it in exact the same way as we did with our first User model:

We now say that an email-address is a value type. It needs a string that represents a valid email-address just as before. The only difference is that we only care about that; higher cohesion than this would be hard to achieve. We can now change the user model like this:

By type-hinting the email argument we make sure that this model can only work with a valid email-address, since invalid ones can not exist.

You probably saw that I added two extra methods to the EmailAddress class. These methods are meant to help us to interact with the object. Since the attribute email in the User class is no longer a string, we can not use it in the same way we did before. This is a slight disadvantage, but PHP gives us a bit of help with the __toString method. Whenever we would echo the email-address PHP will try to cast the object to a string using this method.

Now, when we create a new user we would do it like this:

We now have a bit more preparation work before we can create the user, but what we achieved was that we completely decoupled the email-address from the user. We completely isolated everything that makes an email-address valid; everything concerning this abstraction can now be found in one place. We can even add methods that help us with dealing with the value.

The World of Values

We have seen now how useful this pattern can be, but before we can start implementing this in JavaScript we need to know what a value actually is. How can it be defined?

A value has four key properties (from ‘Values in Object Systems’ – Dirk Riehle) .

  1. It describes a single concept.
  2. It has no life cycle.
  3. It is immutable.
  4. It can not be referenced.

Single concept

Primitive values like string and number are very abstract concepts. A string describes any piece of text and a number any number you might think of. Other examples of value types might be date, currency, age, gender, email, etc.

No Lifecycle

Even though you might think that a value is created, for example through instantiation (new String), a value does not ‘live’.

Let’s say it is Rachel’s birthday and she turned 17. Does this mean a new age of 17 is created? And does it mean that the age 16 is deleted? No, it is best to stop thinking about values as objects. A value is something that lives in a inaccessible “universe of values” and is simply assigned to one or more properties and variables.

Immutable

A value cannot change. This might be a bit hard to grasp, but maybe an example helps you to understand why this is important.

Barry lives in Rotterdam, but he has to move to New York because he got a new job. His family would say that “his address changed” from Coolsingel 3 Rotterdam to Wallstreet 25 New York. But technically that is not true. The address in Rotterdam does not change at all, instead Barry gets a new address located in New York. It means that the property ‘address’ of object ‘Barry’ changed its value.

No Reference

This property distinguishes values from objects. There are no references to values, because they can not be shared between different owners. Another example:

Peter Smith goes to the same gym as Peter van Dyke. They have the same name (the same value), which was fun in the start, but it gets a bit confusing when either of their personal trainers starts calling them. So, to make an end to it, Peter Smith decides to change his name to John Smith. When they meet next week, Peter van Dyke is still called Peter and not suddenly John because Peter Smith changed his first name to John.

This point is strongly related to the fact that values are immutable, mentioned before. Another important point to take from this is that values are side-effect free. They do not change other things than themselves and they behave the same under all circumstances.

Summary

The Value Object is a very useful pattern to structure logic about a single concept in a high cohesive way. It allows you to define the rules of your data in a solid way, making it harder for corrupt data to exist. VOs are immutable and can not be referenced which prevents unwanted side-effects.

Now that we have seen the benefits of VOs we want to find out if and how we could implement this pattern in JavaScript applications. In the next post we will see how primitive value types in JavaScript work and how we could replicate these with our own custom one. We will mainly concern about what the language allows us to do and what not, answering the question if it is possible to build a pattern that meets the requirements (key properties) of a VO.

Further reading

As I said, I might have over simplified the concept a bit, so if you want to dig deeper into this you might want to take a look at some of these resources, they sure helped me: