ValueObjects stored as properties in other ValueObjects

As I mentioned in Testing and Coding a ValueObject it is necessary to clone an object, whenever you store it to or retrieve it from a ValueObject in order to make the ValueObject immutable. Just to add one fundamental topic to this general policy: Whenever you store a ValueObject (InnerVO) as a property inside another ValueObject (VOContainer), you don’t have to do this cloning process at all.

class InnerVO extends Tx_Extbase_DomainObject_AbstractValueObject {
    // ...
}

class VOContainer extends Tx_Extbase_DomainObject_AbstractValueObject {
    /**
     * @var InnerVO
     */
    protected $innerVO;

    /**
     * @param InnerVO $innerVO
     * @return void
     */
    public function __construct($innerVO) {
        $this->innerVO = $innerVO;
    }

    /**
     * Read the innerVO
     * @return InnerVO The innerVO attribute
     */
    public function getInnerVO() {
        return $this->innerVO;
    }
}

Why not cloning?

As long as you follow the formerly discussed policy to make each and every ValueObject immutable, you don’t have to clone it at all while throwing it all over your sourcecode, because it will never change. This is one of the major advantages of making a ValueObject immutable and ensure it’s immutability by forbidding each and every setter method.

The other way around: Whenever you want to change the value of the innerVO object (see above) stored inside VOContainer, you have to create a new innerVO object holding the new values. And because VOContainer is a ValueObject and therefor it’s immutable, you have to build a new VOContainer as well, because the VOContainer’s innerVO cannot be overwritten. There is no setter method and VOContainer must be immutable as well.

Leave a Reply