A bonsai tree

The simple class

Posted Tue Apr 02 2019

I work in many legacy codebases, and in fact, I’ve made it a big part of my career. I love diving into big monoliths that have grown out of proportion and tidying them up. One of the best parts of that work is rewriting a God class into a collection of small reusable classes. Let’s take a look at what makes a simple class great.

One of my favourite types of classes is a value object. For those not in the known, a value object is a small class that holds a value with a tiny bit of extra logic surrounding it. Sounds simple enough right? I think a nice way of looking at these classes is implementing them as an extension of the type system of your programming language. Let take a look at an uncomplicated example.


This small class doesn’t do anything really, and it just holds two strings. The only tiny bit of function (at first glance) is that it concatenates the two strings. However, for the minimal amount of code in this class, it does offer a ton of value to your codebase.

Putting an end to the class struggle 

Once we start replacing every occurrence of the first name and last name with this simple class, you will quickly begin to see the value. First of all, every time you come across this class in your code, you know that it has a first name and the last name in it. You also know that both of these values will be strings. And that you have an easy way to display the first name - last name combination.

You can now also add this as a safety in your new classes. You could, for example, do something like this:

Here you easily guard your method from all kinds of extra logic. You know that the variables that enter the method are of the type Email and Customer class.

There is however still a major issue with our values objects. We could still trick our system into accepting empty strings. Let’s take a look at how we can make these classes just a tiny bit more robust.

Putting a stop to empty values 

We know that our values in our object will always be of the typed string, but “” is also a string. so you could do

new CustomerName('', ''); or even new CustomerName('\$', '!');

You could allow that last one if you are building a platform for rappers, but in most cases, you would want to guard against that.

If you are using PHP (like the examples are), I would suggest using a package like webmozart/assert.

(you could add a private validation method to the class that is called on the first line of the constructor if there are many validation rules)

The class is now a lot smarter; it validates the values that come in and will throw an exception when they don’t meet the expectations of the class.

Now you can be sure that whenever you encounter this class, the values within will be usable.

Adding more means of production to the classes 

It might be very tempting to start now adding more and more logic to these classes. However, I would caution restraint here.

A common thing you see is people adding getters and setters to these classes. You might notice we already have getters (we just not named them getters), and I would strongly recommend against adding setters.

If you need to update a value in the class, create a new instance of the class. Value objects are meant to be built and discarded. By creating new value objects you also make sure you pass the constructor every time, and therefore including the validation.

If you really feel like adding setters, make sure they create new instances themselves:

Another thing to touch upon is named constructors. A named constructor allows you to create the value object under different circumstances. I feel like it is easiest to explain with another example.

(this example is to demonstrate the function of a named constructor. This method assumes that a name is always in 2 pieces with the first name as the first piece. If you want to implement this, please add extra logic)

These constructors are a small convenient way to create the value object. Named constructors allow for great flexibility. However, like always, you should not take this flexibility too far.

You should always ask yourself, is this method solving a real problem, or am I just adding this for a one-off small convenience?

Named constructors are very useful in a “Time” class, where you can create the class from a string format, or from the hour, minute and second parameters as further explained here by Mathias Verraes.

In closing 

There is still a lot to be said about value objects. We haven’t touched upon testing, logging, naming…

For more information about these topics, I would advise you to look into some DDD books or even better check out Matthias Noback’s book “Style Guide for Object Design”. A book that prompted me to write this article. (I get no personal benefits for advertising this book, I just think it’s a great book)

If you haven’t implemented Value objects into your codebase, I would greatly advise you to give it a try. You will wonder how you ever lived without it.

Hey thanks for reading!

Hope you enjoyed this post. There is no comments section here, if you've ever seen the YouTube comments section you'll probably understand why. If you have any remarks or comments on this topic, you can find links below to social media discussions

Bird's eye view of a landscape

A bird's eye view on API development

Posted Sun Nov 15 2015

So you want to build a web API. You have to start somewhere, why not here

Continue reading
Mother board

Connect microservices with the help of GRPC

Posted Sun Jul 23 2017

Microservices can solve a lot of architectural problems, and sometimes create a few fun new ones. A big problem however is connecting these services to each other.Can GRPC lend a hand here?

Continue reading
max verstappen formula 1 car

What performance tricks actually work

Posted Mon Jul 23 2018

We've all been there before, you submit a pull request and moments later you get a comment like: ''Hey you should use a native function here, they are so much faster'' or ''You can declare this final, that way we save some processing power''

Continue reading