Image for post
Image for post

Little Thing — Value Objects

This is part of my Little Things series. Although these examples are in ruby, they should be understandable to anyone familiar with an object-oriented language.

What are value objects, and when should we use them?

Let’s imagine that we have a some code that uses coordinates, and we’re defining a couple of variables:

canvas_position_x = 25
canvas_position_y = 200
draw_canvas(canvas_positionX, canvas_position_y)

Most programmers would see this and think: that’s a smell, those two variables always belong together — they should be one thing. The obvious next step is to put them in some sort of hash table. In ruby, that’s a hash:

canvas_position = {
x: 25,
y: 200
draw_canvas(canvas_position[:x], canvas+position[:y])

This is better, but is still not perfect. We are still using a primitive data type which doesn’t know or care that it’s holding a coordinate. Instead, we could create a value object to store our coordinates.

class Coordinate
attr_reader :x, :y
def initialize(x:, y:)
@x, @y = x, y
canvas_position = Coordinate.new(x: 25, y: 200)draw_canvas(canvas_position.x, canvas_position.y)

Advantages to this approach

class Coordinate  #...  def reverse
self.class.new(x: y, y: x)

For rubyists, this might all feel pretty obvious, since everything in ruby is an object. Ruby’s primitive data types like Symbol, String, Integer and Range are all value objects anyway. They also all share a property which our Coordinate objects do not…

Their Equality is based on their values.

a = Coordinate.new(x: 1, y: 2)
b = Coordinate.new(x: 1, y: 2)
a == b #=> false

One of the most important properties of a value object, when compared with other sorts of object, is how they handle equality. According to Martin Fowler

…their notion of equality isn’t based on identity, instead two value objects are equal if all their fields are equal.

So we need fix this. We can implement a == method that only returns true if the x and y values are the same as the thing we’re comparing to and if the thing we’re comparing to is also a kind of Coordinate. We should alias eql? since that’s pretty standard in ruby.

class Coordinate  #...  def ==(other)
self.class == other.class &&
x == other.x &&
y == other.y
alias :eql? :==

If two Coordinate objects are considered equal, then they should also have the same hash. Let’s override the hash method provided by BasicObject with our own, which generates the hash based on the values our object is holding:

class Coordinate#...  def hash
[@x, @y].hash
a = Coordinate.new(x: 1, y: 2)
b = Coordinate.new(X: 1, y: 2)
a == b #=> true

What about Structs, tho?

You might be thinking that a Struct would remove a lot of this boilerplate. We could get everything working — including all the equality stuff — with just one line of code:

Coordinate = Struct.new(:x, :y, keyword_init: true)

Awesome, right?

Maybe not. While structs tick almost every box, they are mutable. 😞 In other words, they define setter methods for x and y. For me, this is a dealbreaker, though you could always get round this by creating an immutable version of Struct, like this.

I tend to reach for value objects when I see…

  • A data clump: two or more values that always belong together. These are often pairs values like x and y or start_date and end_date. If you see the same values being passed through multiple methods together, it’s usually a good indicator.
  • A piece of data which has functionality. Temperature is a good example: Although it’s a single value, it might also have methods like below_freezing?. If you see a group of methods that are all operating on the same value, it’s a good indicator.

My rules for writing value objects


For me, using value objects has advantages and disadvantages. On the one hand, they can make your code easier to understand and less coupled. In ruby, you can take advantage of duck typing to make your code code more flexible. Value objects also make your code more defensive: you will likely more descriptive errors.

On the other hand, you’ll end up with a lot more classes and unit tests to maintain and the cognitive burden on people reading your code can be a bit higher. Over time, it’s also easy to inflate value objects into massive classes that do too many things (and aren’t really value objects anymore).

I’m coming round to the idea that value objects are most useful when working with the core business logic of your application: the domain layer. If you watch a few talks on Domain-Driven Design, you’ll see what I mean.

Further Reading


If we wanted to, we could try to pull some of this functionality into a generic class and inherit from it. It might look something like this…


Written by

Software Engineer and Teacher. Passionate about technology education and helping people be happy at work. I also play blues music.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store