In DDD (domain driven design) value objects are simple objects that quantify, measure or describe something that belongs to our domain. They represent a value and it is their value that matters and what differentiates them from other value objects.

There are two aspects to take into account to understand it better:

  1. As Ward Cunningham says, it is a measure or a description of something.
  2. Its identity is defined through its state and not using a unique identifier field. So, as Martin Fowler says, two value objects are equal if their attributes contain the same values. They must be immutable.

Some examples of value objects could be:

  1. A date.
  2. Money.
  3. A name.
  4. An address.
  5. A quantity.

A concrete example

For example, in a cooking recipe, we could have a value object that represents the quantity “250 grams”. Actually that particular instance of the quantity “250 grams” does not matter too much in itself, if not through its value. As an immutable object, whether this or another instance, the important thing is the value it has. It will be equal to another with the same value “250 grams”.

If we need to represent the value “1 kilogram”, although it is also a quantity, instead of modifying the previous instance, we will create a new one.

An advantage of conceptualizing these descriptions in the form of value objects is that all the behavior relative to them can be implemented within those classes, for example, a validation. In this way we have another advantage: we fight against the anti-pattern of the anemic domain models.

Show me the code

I would like to translate into code the example of the quantity for the ingredients of a recipe. For example “250 grams” could be solved with a class that keeps the type of measurement (grams, kilos, milliliters …) and another that links this concept to an amount (1, 250, 3.5).

Both are value objects, in this case they measure the necessary amount of an ingredient in a recipe.

class Measure
{
    private $name;

    public function __construct($name)
    {
        $this->setName($name);
    }

    private function setName($name)
    {
        $this->name = $name;
    }

    public function name()
    {
        return $this->name;
    }
}

class Quantity
{
    private $amount;
    private $measure;

    public function __construct($amount, Measure $measure)
    {
        $this->setAmount($amount);
        $this->setMeasure($measure);
    }

    private function setAmount($amount)
    {
        $this->amount = floatval($amount);
    }

    private function setMeasure(Measure $measure)
    {
        $this->measure = $measure;
    }

    public function amount()
    {
        return $this->amount;
    }

    public function Measure()
    {
        return $this->measure;
    }
}