ValueObjects with lots of (optional) objects

If you want to define ValueObjects with a lot of optional objects using the implementation described in Making a ValueObject NULL-prove, this will lead to a very long constructor and a lot of copy / paste code. Not nice.

Solution #1: divide et impera

The very first idea is to define private setters for each object. These setters are called by the constructor only and every setter is responsible for one object only. This will reduce the length of the constructor code, but it won’t solve the copy-paste issue.

Solution #2: Define a generic (optional) object setter

class MyValueObject {
    protected $param1;
    protected $param2;
    protected $param3;
    protected $param4;
    protected $param5;

    public function __construct($param1, $param2, $param3, $param4, $param5) {
        $this->setParam('param1', $param1, DateTime);
        $this->setParam('param2', $param2, SomeOtherClass);
        //....
    }

    private setParam($name, $value, $class) {
        if($value === NULL) {
            $this->$name = NULL;
        } elseif($value instanceof $class) {
            $this->$name = clone $value;
        } else {
            throw new InvalidArgumentException('expecting parameter ' . $name . ' to be of type ' . $class, 1413833055);
        }
    }
}

Now you can use setParam(…) to set all internal objects including cloning, NULL values (you might switch this functionality on/off for certain parameters to make them mandatory) and type/class checks. This reduces your code, because your constructor uses just one line of code per parameter and your setter is defined just once, thus you don’t do copy/paste and can rely on the centralised functionality. Nice? Nice.

Leave a Reply