Value Objects en PHP

Los value objects (VO) o objetos de valor son uno de los bloques de construcción en los principios de «Domain Driven Design«. Representan un valor y no tienen identidad. Dicho esto, dos objetos de valor son iguales si sus valores son iguales.

Otra característica importante es que los objetos de valor son inmutables, es decir, no se pueden modificar después de la creación.

La única forma válida de crear Value Objects es pasar toda la información requerida al constructor y validando dicha información en algún método interno.

Martin Fowler define los value objects (VO) o objetos de valor de la siguiente manera: un objeto pequeño y simple, como el dinero o un rango de fechas, cuya igualdad no se basa en la identidad.

Esto significa, dos objetos de valor son iguales, no cuándo se refieren al mismo objeto, sino cuándo el valor que tienen es igual.

Por ejemplo, dos billetes diferentes de cien dólares tienen el mismo valor cuando los usamos para comprar algo (la clase Dinero sería un objeto de valor).

Por otro lado, tenemos entidades que se comparan en identidad, por ejemplo: dos personas pueden tener el mismo nombre, pero no son la misma persona (la clase Persona sería una entidad), por lo tanto, no son iguales.

Es muy importante tener en cuenta que si algo debe representarse como un objeto de valor o una entidad, depende del contexto en el que se utilice.

Atributos de los Value Objects:

Inmutabilidad:

Un objeto no puede ser cambiado por nadie. Una vez creado, solo se puede clonar, por lo que la lógica que creó el objeto confía en que los datos nunca se alterarán. Esto agrega durabilidad adicional al sistema por diseño.

Validación incorporada:

Un objeto contiene validadores integrados que imponen su formato interno. Digamos, una dirección debe tener una ciudad, un código postal y una dirección postal.

Cada vez que crea una instancia de un nuevo objeto de dirección, debe proporcionarle datos válidos; de lo contrario, la creación de instancia del objeto falla.

Ejemplo de un Value Object:

final class Money
{
    /** @var int */
    private $value;
 
    /** @var string */
    private $currency;
 
    public function __construct(
        int $value,
        string $currency = 'USD'
    ){
        $this->value = $value;
        $this->currency = $currency;
    }
 
    public function equals(Money $money): bool
    {
        return $this->value === $money->value
            && $this->currency === $money->currency;
    }
 
    public function getValue(): int
    {
        return $this->value;
    }
 
    public function getCurrency(): string
    {
        return $this->currency;
    }
}

Ejemplo de una Entidad:

class Person
{
    /** @var int */
    private $id;
    
    /** @var string */
    private $name;
 
    public function __construct(string $name)
    {
        $this->name = $name;
    }
 
    public function equals(Person $person): bool
    {
        return $this === $person;
    }
 
    public function getId()
    {
        return $this->id;
    }
    
    public function getName()
    {
        return $this->name;
    }
}

Por tanto, los value objects son clases que definen tipos de valores que pueden ser utilizados en cualquier parte de nuestro sistema.

Lo interesante de ellos es que encapsulan información valiosa de nuestro core business y por otro lado, que son fácilmente serializables y totalmente desacoplados a cualquier tecnología.

Y por otro lado, como vemos en el ejemplo, las entidades contienen identificadores «ID» que identifican entidades por tanto una entidad nunca sera igual a otra pese a que su contenido relevante sea el mismo.

Referencias sobre los Value Objects

Esto corresponde entonces al principio Tell Don’t Ask mostrado en mi post anterior.

Recuerda que si tienes alguna sugerencia o pregunta, no dudes en dejar tus comentarios al final del post.

Si te gustó este post, ayúdame a que pueda servirle a muchas más personas, compartiendo mis contenidos en tus redes sociales.

Espero que este post haya sido de gran ayuda para ti, y como siempre, cualquier inquietud o duda que tengas, puedes contactarme por cualquiera de las vías disponibles, o dejando tus comentarios al final de este post. También puedes sugerir que temas o post te gustaría leer a futuro.


Si te gustó el post, regálame tus aplausos!!!