I am a programmer and architect (the kind that writes code) with a focus on testing and open source; I maintain the PHPUnit_Selenium project. I believe programming is one of the hardest and most beautiful jobs in the world. Giorgio is a DZone MVB and is not an employee of DZone and has posted 638 posts at DZone. You can read more from them at their website. View Full User Profile

Practical PHP Patterns: Value Object

09.29.2010
| 13118 views |
  • submit to reddit

Today comes a pattern that I have wanted to write about for a long time: the Value Object. A Value Object is conceptually a small simple object, but a fundamental piece of Domain-Driven Design and of object-oriented programming.

Identity vs. equality

The definition of a Value Object, that establishes if we can apply the pattern to a class, is the following: the equality of two Value Objects is not based on identity (them being the same object, checked with the operator ===), but on their content.

An example of PHP built-in Value Object is the ArrayObject class, which is the object-oriented equivalent of an array. Two ArrayObjects are equal if they contain the same elements, not if they are the same identical object. Even if they were created in different places, as long as the contained scalars are equals (==) and the contained objects are identical (===), they are effectively "identical" for every purpose.

In PHP, the == operator is used for equality testing, while the === for identity testing. Also custom equals() method can be created.

Basically, the == operator checks that two scalars, like strings or integers, have the same value. When used on objects, it checks that their corresponding fields are equals. The === operator, when used between objects, returns true only if the two objects are actually the same (they refer to the same memory location and one reflects the changes made to another.)

Scalars, as objects

Other languages provide Value Objects also for basic values like strings and integers, while PHP limits itself to the ArrayObject and Date classes. Another example of a typical Value Object implementation is the Money class.

Continuing with the Date example, we usually don't care if two Date objects are the same, but we care instead to know if they had the exact identical timestamp in their internals (which means they are effectively the same date.)

On the contrary, if two Users are the same, they should be the same object (in the memory graph) which resides in a single memory location, or they should have an identity field (in databases) that allow us to distinguish univocally between two users.

If you and I have the same name and address in the database, we are still not the same User. But if two Dates have the same day, month, and year, they are the same Date for us. This second kind of objects, whose equality is not based on an Identity Field, are Value Objects.

For simplicity, ORMs automatically enforce the identity rules via an Identity Map. When you retrieve your own User object via Doctrine 2, you can be sure that only one instance would be created and handed to you, even if you ask for it a thousand times (obviously other instances would be created for different User objects, like mine or the Pope's one).

In Domain-Driven Design

The Value Object pattern is also a building block of Domain-Driven Design. In practice, it represents an object which is similar to a primitive type, but should be modelled after the domain's business rules. A Date cannot really be a primitive type: Date objects like Feb 31, 2010 or 2010-67-89 cannot exists and their creation should never be allowed.

This is a reason why we may use objects even if we already have basic, old procedural types. Another advantage of objects if that they can add (or prohibit) behavior: we can add traits like immutability, or type hinting. There's no reason to modelling a string as a class in PHP, due to the lack of support from the str*() functions; however, if those strings are all Addresses or Phonenumbers...

In fact, Value Objects are almost always immutable (not ArrayObject's case) so that they can be shared between other domain objects.

The immutability solves the issues named aliasing bugs: if an User changes its date of birth, whose object is shared between other two users, they will reflect the change incorrectly. But if the Date is a Value Object, it is immutable and the User cannot simply change a field. Mutating a Value Object means creating a new one, often with a Factory Method on the Value Object itself, and place it in the reference field that pointed to the old object.

In a sense, if transitions are required, they can be modelled with a mechanism similar to the State pattern, where the Value Object returns other instances of its class that can be substituted to the original reference. Garbage collecting will take care of abandoned Value Objects.

To a certain extent, we can say that Value Objects are "passed by value" even if the object reference is passed by handler/reference/pointer like for everything else. No method can write over a Value Object you pass to it.

The issues of using Value Objects extensively is that there is no support from database mapping tools yet. Maybe we will be able to hack some support with the custom types of Doctrine 2, which comprehend the native Date class, but real support (based on the JPA metadata schema) would come in further releases.

Examples

An example of Value object is presented here, and my choice fell onto the Paint class, an example treated in the Domain-Driven Design book in discussions about other patterns.
On this Value Object we have little but useful behavior (methods such as equals(), and mix()), and of course immutability.

<?php
/**
 * Subclassing a Value Object is rare, so we cut out this scenario
 * immediately.
 * This class represent a category of paint, like 'blue' or 'red',
 * not a quantity.
 */
final class Paint
{
    private $red;
    private $green;
    private $blue;

    /**
     * This is paint for screens... No CMYK.
     * @param int   0-255
     * @param int   0-255
     * @param int   0-255
     */
    public function __construct($red, $green, $blue)
    {
        $this->red = $red;
        $this->green = $green;
        $this->blue = $blue;
    }

    /**
     * Getters expose the field of the Value Object we want to leave
     * accessible (often all).
     * There are no setters: once built, the Value Object is immutable.
     * @return integer
     */
    public function getRed()
    {
        return $red;
    }

    public function getGreen()
    {
        return $green;
    }

    public function getBlue()
    {
        return $blue;
    }

    /**
     * Actually, confronting two objects with == would suffice.
     * @return boolean  true if the two Paints are equal
     */
    public function equals($object)
    {
        return get_class($object) == 'Paint'
           and $this->red == $object->red
           and $this->green == $object->green
           and $this->blue == $object->blue;
    }

    /**
     * Every kind of algorithm, just to expanding this example.
     * Since the objects are immutable, the resulting Paint is a brand 
     * new object, which is returned.
     * @return Paint
     */
    public function mix(Paint $another)
    {
        return new Paint($this->integerAverage($this->red, $another->red),
                         $this->integerAverage($this->green, $another->green),
                         $this->integerAverage($this->blue, $another->blue));
    }

    private function integerAverage($a, $b)
    {
        return (int) (($a + $b) / 2);
    }
}

// client code
$blue = new Paint(0, 0, 255);
$red = new Paint(255, 0, 0);
var_dump($blue->equals($red));
var_dump($violet = $blue->mix($red));
Published at DZone with permission of Giorgio Sironi, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Matthew Weier O... replied on Wed, 2010/09/29 - 1:02pm

In your example, shouldn't explicit protected or private properties be defined for $red, $green, and $blue? Otherwise, they're public, and thus mutable.

Also, by extension, the equals() and mix() methods should also use the explicit getters, instead of attribute access, in order to do their work, since both are accessing members of other instances.

Good article, though!

Giorgio Sironi replied on Wed, 2010/09/29 - 4:40pm in response to: Matthew Weier O'phinney

You're right about the properties, I forgot to include them (code fixed now). I *cannot* understand why PHP even with E_ALL error reporting does not tell me when I set a not defined property (must be some BC issue). You can be sure all code in my articles is run before posting.

For the getters usage, it's not necessary since the private scope includes the whole *class* and not the single *object*. In almost all object-oriented languages an object can access the private fields of other objects of the same class, and does so in the standard equals() methods. It make sense, if you think about it: encapsulation is preserved since the code that accesses the field is still in the same source file.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.