Introduction
The pattern (rather mini-pattern) we are going to see today is widely used in Domain-Driven-Design (DDD). The Value Object pattern reinforces a sometimes forgotten concept of object-oriented principles, especially for those of us who are used to weakly typed languages: encapsulation.
There are several definitions of what a Value Object (VO) is, we have for example that of Ward Cunningham:
Examples of value objects are things like numbers, dates, monies and strings. Usually, they are small objects which are used quite widely. Their identity is based on their state rather than on their object identity. This way, you can have multiple copies of the same conceptual value object. Every $5 note has its own identity (thanks to its serial number), but the cash economy relies on every $5 note having the same value as every other $5 note.
The Martin Fowler:
When programming, I often find it's useful to represent things as a compound. A 2D coordinate consists of an x value and y value. An amount of money consists of a number and a currency. A date range consists of start and end dates, which themselves can be compounds of year, month, and day.
(...) Objects that are equal due to the value of their properties, in this case their x and y coordinates, are called value objects.
Or that of Carlos Buenosvinos, Keyvan Akbary and Christian Soronellas:
Value Objects are a fundamental building block of Domain-Driven Design, and they're used to model concepts of your Ubiquitous Language in code.
Basically, to put it another way: if we compare our system to a living being, the Value Object would be equivalent to cells, if we compare it to a building, they would be the bricks.
A Value Object is used to model concepts of our system, such as identifiers, dates or date ranges, prices, weights, velocities (practically any magnitude can be modeled as a VO), or even titles, names or addresses. Entities, for example, are composed of Value Objects.

Features
There are a number of distinguishing characteristics that make a class a Value Object.
Measures, quantifies or describes a concept
VOs are intended to measure, quantify or describe a concept in our domain layer. They are not considered something, They are a value, and as such have an end.
Immutability
VOs are conceived as immutable objects. Given their limited size, their construction does not have a strong impact on memory consumption, so it is preferable to create a new instance rather than modifying an existing one, thus avoiding side-effects derived from their modification.
When we talk about primitives, we can assign the value to a variable and compare it with the value of another variable:
$a = 1;
$b = 1;$a == $b; //true
We can reassign the value as many times as we want, discarding the previous value:
$a = 1;
$a = 2;
$a = 3;$a == 1; //false
$a == 2; //false
$a == 3; //true
And we can also modify them through operations, always receiving a new value:
$a = 1;
$a = $a + 9;$a == 10; //true
On the other hand, if we pass a primitive as an argument to a function, we do it by value (unless we explicitly do it by reference) and the function cannot modify its value except by assigning the result of the function to the variable:
/** Incorrect Form */function add(int $a, int $b)
{
$a = $a + $b;
}$a = 1;
$b = 9;
add($a, $b);$a == 10; //false/** Correct form */function add(int $a, int $b)
{
return $a + $b;
}$a = 1;
$b = 9;
$a = add($a, $b);$a == 10; //true
The idea is that a VO behaves like a basic type.
Always valid
The constructor of a VO is always passed the primitives (or other VOs) needed to instantiate the new object, so it will always be in a valid state, since in case of missing or invalid values, it will not be constructed and will throw an exception.
A good practice is to provide semantic constructors The use of static parameters facilitates the creation of VOs, especially when one of the parameters has a limited set of valid values.
No identity
Never confuse an entity with a value object. The main difference is that the former possesses a identity, an identifier that makes them unique from another instance of the same class. A value object on the other hand has no identity, so comparisons between value objects must be made based on their content, and not an identifier or reference.
This clashes quite a bit with the default behavior of most programming languages. Let's look at the following example:
<?php declare(strict_types=1);
class Point
{
private $x;
private $y;
public function __construct(float $x, float $y)
{
$this->x = $x;
$this->y = $y;
}
public function getX(): float
{
return $this->x;
}
public function getY(): float
{
return $this->y;
}
public function equalsTo(Point $point)
{
return $point === $this;
}
}
$a = new Point(2, 3);
$b = new Point(2, 3);
var_dump($a->equalsTo($b)); // Returns false<?php declare(strict_types=1);
class Point
{
private $x;
private $y;
public function __construct(float $x, float $y)
{
$this->x = $x;
$this->y = $y;
}
public function getX(): float
{
return $this->x;
}
public function getY(): float
{
return $this->y;
}
public function equalsTo(Point $point)
{
return ($point->x === $this->x) && ($point->y === $this->y);
}
}
$a = new Point(2, 3);
$b = new Point(2, 3);
var_dump($a->equalsTo($b)); // Returns trueAs can be seen in the first example, we have defined a class Point and we have created two equal instances, but when executing the method equalsTo the result is not the expected one, since the check is being done based on the object reference, and not on its content.
In the second case, the comparison does return the expected result, because we have made the comparison based on the content of the object.
Encapsulation
Suppose we have a class Product which contains, among others, the attributes amount y currency. Given this scheme, we would have to provide separately the two parameters, and in case of requiring a validation of the currency to know if it is valid or is supported by our system, where would we put it? In the class Product does not seem to make much sense, and furthermore, it breaks with the Principle of Sole Responsibility. Moreover, it seems that this validation will be reused many times and not only in the context of a product.
If, on the other hand, we create a used-vehicle Price that allows us to encapsulate the quantity and currency and also performs all the necessary validations during its construction, we will be simplifying validations and their reuse, as well as efficiently encapsulating attributes that individually do not make sense by themselves in the context of their use.
Value Objects Testing
It is quite obvious that testing these small objects is a fairly simple task, since they have practically no logic beyond the validations in their constructors, but let's not forget that Value Object should to be immutable, and during our testing we have to make sure that this is the case, checking that there are no side-effects when executing any operation with them.
If, for example, our class Temperature representing the temperature would have a method increase(Temperature $temperature), If we call the method, we would have to make sure that after calling the method, the instance has not been modified, but has returned a new Temperature VO with the new incremented value.
Example
Given the principles we have seen, we can see below an example of a VO representing a velocity:
<?php declare(strict_types=1);
class Speed
{
const KILOMETERS_PER_HOUR = 'km/h';
const MILES_PER_HOUR = 'm/h';
private $amount;
private $magnitude;
private function __construct(int $amount, string $magnitude)
{
$this->checkAmount($amount);
$this->amount = $amount;
$this->magnitude = $magnitude;
}
private function checkAmount(int $amount)
{
if (0 > $amount) {
throw new NegativeSpeedException();
}
}
public static function inKilometersHour(int $amount): self
{
return new self($amount, self::KILOMETERS_PER_HOUR);
}
public static function inMilesPerHour(int $amount): self
{
return new self($amount, self::MILES_PER_HOUR);
}
public function getAmount(): int
{
return $this->amount;
}
public function getMagnitude(): string
{
return $this->magnitude;
}
public function increase(Speed $speed): self
{
if ($speed->getMagnitude() !== $this->magnitude) {
throw new MagnitudeMismatchException();
}
$newAmount = $this->amount + $speed->getAmount();
return new self($newAmount, $this->magnitude);
}
public function equalsTo(Speed $speed): bool
{
return
($this->amount === $speed->getAmount())
&&
($this->magnitude === $speed->getMagnitude())
;
}
public function __toString(): string
{
return $this->amount . $this->magnitude;
}
}<?php declare(strict_types=1);
use PHPUnit TestCase;
class SpeedTest extends TestCase
{
/**
* @test
* @expectedException NegativeSpeedException
*/
public function itShouldThrownAnExceptionWhenAmountIsNegative()
{
Speed::inKilometersPerHour(0);
Speed::inMilesPerHour(0);
}
/** @test */
public function itShouldCompareWithOthers()
{
$speedA = Speed::inKilometersPerHour(100);
$speedB = Speed::inKilometersPerHour(100);
$this->assertTrue($speedA->equalsTo($speedB));
$speedB = Speed::inMilesPerHour(100);
$this->assertFalse($speedA->equalsTo($speedB));
}
/** @test */
public function originalSpeedShouldNotBeModifiedOnIncrease()
{
$speedA = Speed::inKilometersPerHour(100);
$speedB = Speed::inKilometersPerHour(100);
$speedA->increase($speedB);
$this->assertEquals(100, $speedA->getAmount());
}
/** @test */
public function speedShouldBeIncreased()
{
$speedA = Speed::inKilometersPerHour(100);
$speedB = Speed::inKilometersPerHour(100);
$speedC = $speedA->increase($speedB);
$this->assertEquals(200, $speedC->getAmount());
}
/**
* @test
* @expectedException MagnitudeMismatchException
*/
public function speedShouldNotBeIncreasedIfMagnitudeIsDifferent()
{
$speedA = Speed::inKilometersPerHour(100);
$speedB = Speed::inMilesPerHour(100);
$speedC = $speedA->increase($speedB);
}
}As you can see:
- Measures, quantifies or describes a concept.
- It is immutable.
- It provides semantic constructors for its construction.
- It is valid in construction, so it will always have a valid status.
- It is compared by value, not by reference (It has no identity).
- Encapsulates in a class two attributes that by themselves have no meaning

Conclusion
Although it may seem at first a bit cumbersome to model each concept of our system as an object, the long-term advantages are more than evident, both at the level of implementation and code reuse as well as at the testing level.
It is true that the mapping with the database can be more complex with entities composed by VO, but if we use ORMs based on Data Mapper (like Doctrine) the task is simplified much more, we will see this later in another post.

References
- Domain-Driven Design in PHP, by Carlos Buenosvinos, Christian Soronellas and Keyvan Akbary
- Domain-Driven Design: Tackling Complexity in the Heart of Software by Eric J. Evans
- Implementing Domain-Driven Design by Vaughn Vernon
- Domain-Driven Design (Distilled) Reduced version of the previous book.
