Value Objects, Barbara and Design Patterns

João Bizarro
Tech at Docler
Published in
5 min readNov 20, 2020

What do Value Objects, Barbara Liskov and the classic Design Patterns book have in common?

Ok, we need to refine the question above before answering it.

What are Value Objects?

Developers who have heard about Domain Driven Design might have found a term called Value Object. According to Eric Evans Value Objects can be defined as the following:

An object that represents a descriptive aspect of the domain with no conceptual identity is called a Value Object.

There are hundreds if not thousands of articles explaining what value objects are, their benefits and downsides. If you want to read about Value Objects in details from the beginning I recommend you reading this article here.

Usually the conclusion about this subject is that for some cases it's better to create these value objects and sometimes don't. As usual I say that knowing the trade offs gives you power to decide whether to use value objects.

Now the question: where does the idea behind value objects come from?

How many people have asked you that? More importantly, have you ever asked yourself that?

In order to answer that question we need to get some real examples and analyse them deeper to find clues.

Searching for clues

Let's take Age as our first example. According to the article I've recommended to you, Age is not an integer, string or boolean. This is how I imagined the Age class after reading that article:

Good, the Age class has self validation and it is immutable, exactly like the author explained. Now age is not a primitive type anymore.

However have you noticed that although age is not an integer, it contains an integer? That's interesting, because that might be happening with other value objects too. Maybe we should check how Email class would look like.

Hmm…Email is not a string, but it contains a string just like Age contains an integer! That's intriguing, don't you think?

What about more complex objects such as Address or Period? How would a Period class look like to you? What's a period?

I guess you said a period contains a start date and end date. Maybe the class would be like this:

Period class is even more interesting because it contains 2 parameters which aren't primitives.

Basically the idea of value objects is to compose one or more types (primitives or not) to create a new one, but it's not a data structure, because it's immutable.

Object composition…where did we see this term before?

Back to the future

Those ones who read the first chapters of the legendary book Design Patterns by "The Gang of Four" might have faced the following expression

Favor object composition over class inheritance.

What does that mean? Well, it's obvious what it means, but what does that mean in real life, in practice?

Going back to our first example, the Age class, it's clear that Age is being composed by an integer, but we're not favouring object composition over inheritance, are we?

How would the Person object look like if age was an integer instead of age?

When we assume that age is an integer, we're theoretically saying the Age object would be

Now it looks crazy, right? But we need to dig a little deeper into this subject. Imagine for a minute the sample above is not crazy. How would an integer object be composed?

Whatever the answer is, how would this other type be composed?

We can keep asking this question until the answer is electric signals. What does this have to do with the subject of this article?

At some degree, everyone and every company are using the same physical layer to transfer data. This layer must be as much generic as possible so anyone can use it, but as soon as you get closer to the end (user) the generic data needs to be refined and refined, passing through your WiFi, your computer, your compiler, your code until reach the user.

The purpose of a value object is to refine the complexity of data coming from lower layers to guarantee that the user has an age, but not an integer.

Nice, value objects are then objects which favors composition over inheritance, but what does this have to do with Barbara Liskov?

When Inheritance is valid

In 1994 Barbara Liskov wrote a paper with her description for the substitution principle as following:

Subtype Requirement: Let o(x) be a property provable about objects x of type T. Then o(y) should be true for objects y of type S where S is a subtype of T.

If you understand the principle by reading its description above and you do not need to read it again, you're Jedi. In my opinion this description can cause more confusion than enlightenment.

The popular description for LSP (Liskov Substitution Principle) is:

…objects of a superclass shall be replaceable with objects of its subclasses without breaking the application.

Well, it's easier to understand, but what does that mean in real life?

Imagine we have another class called ApartmentNumber, which can also be composed by an integer like following:

Now imagine that we don't have a value object for ApartmentNumber neither for Age, therefore both would be integers.

Now the question: since both are integers does it make sense to replace an age by an apartment number?

Does it make sense to replace an email by a string?

When we look to LSP's requirements it becomes clearer:

  • Contravariance of method arguments in the subtype: contravariance means the subtype does not need to preserve composition of method arguments. In other words, your subtype can override a method/function from base class and accept a more generic parameter type;
  • Covariance of return types in the subtype: covariance means the subtype needs to preserve the composition of return types. If you look closer this one seems to be obvious, because if you want to replace your subtype by another subtype the return types must be compliant;
  • No new exceptions should be thrown by methods of the subtype, except where those exceptions are themselves subtypes of exceptions thrown by the methods of the supertype: how can the client (consumer) of your subtype be prepared for new exceptions for each different subtype? If you want your subtype to be replaceable by another one all the consumers of your subtype must have knowledge about what kind of exception it might face;

There are other behavioural requirements for subtypes such as Preconditions, Postconditions and Invariants, but they deserve an exclusive article.

Based on those requirements, how easy is for you now to use inheritance? It's getting hard to think about good examples, isn't it?

If we need to match those requirements above to have a good object inheritance and it's really hard to match all those requirements , why don't we use composition?

Favor object composition over class inheritance.

Beyond that, by creating Value Objects we are, at some degree, following Liskov Substitution Principle, because now you can create Email, Age or and Address specialisations and, if you follow the principle, you'll be able to replace your specialisations by others or by your base class without any problems.

Now how would you answer the first question? What do Value Objects, Barbara Liskov and the classic Design Patterns book have in common?

--

--