Modelo de Value Object vs. Entity Object

Ana Martínez Aguilar
4 min readJun 6, 2018

--

Antes de comenzar a definir qué es Value Object y Entity Object, hay que tener en cuenta que estamos hablando de patrones y convenciones, es decir, se trata de la descripción de algo, no de algo en sí mismo. Estos dos patrones diferencian objetos por su contenido o por su identidad, una diferencia que aplicamos dependiendo del contexto para mejorar nuestro código, pero no se trata de una diferenciación de la que sepa JS -que siempre compara objetos por referencia-.

Value Object

En el modelo Value Object, un objeto se diferencia de otro por su contenido, no por su identidad propia.

Value Object es un concepto. No quiere decir que JavaScript identifique como iguales dos objetos con el mismo contenido, de hecho compara los objetos por su referencia:

var object1 = {a: 1, b: 2};var object2 = {a: 1, b: 2};object1 == object2
→ false

Podemos entender el concepto de Value Object con el ejemplo de las monedas. Aunque cada moneda de 1 euro tiene su propia identidad (un número de serie), la economía funciona porque entiende que una moneda de 1 euro es igual que otra moneda de un euro, ambas valen lo mismo y a efectos prácticos son iguales.

function createCoin() {
return {
value: 1
}
}

Los estados en un modelo Value Object son inmutables -llamamos estado de la aplicación, de una función, etc, a todos aquellos datos que representan cómo está la aplicación en un momento determinado- .

Si queremos cambiar una característica, crearemos un nuevo objeto con esa característica, en lugar de ir modificando los estados de un único objeto. Un objeto que tiene variables de estado y que nunca cambia se llama objeto inmutable. Por lo tanto, utilizaré el modelo de Value Object cuando tenga sentido crear nuevos objetos en lugar de confiar en un único objeto e ir cambiando su estado.

Veamos un ejemplo de cómo se implementa. La siguiente función devuelve un color dependiendo del código que se haya insertado. En cada operación, devuelve un objeto diferente. En ningún método alteramos la variable del estado, sino que devolvemos un objeto nuevo.

function createColor(colorValue) {
function name(){
if(colorValue === “#000”) {
return “black”;
}
if(colorValue === “#fff”) {
return “white”;
}
if(colorValue === “#999”) {
return “gray”;
}
return “Unknown color”;
}
function mix(otherColor) {
if (createColor(otherColor).name() == “white” && name() == “black”) {
return createColor(“#999”).name();
}
}
return {
mix: mix,
name: name
}
}
createColor(“#fff”).name();
--> “white”
createColor(“#000”).mix(“#fff”);
--> “gray”

En este caso, diferenciamos los objetos por el contenido. Si los objetos tienen el mismo valor, para nosotros son iguales.

-String

String en JS es un objeto inmutable y lo tratamos como Value Object. Por ello, todos los métodos que se aplican sobre string generan un nuevo string y no modifican el original.

var string = “Hello”;
string.replace(“H”, “x”);
--> “xello”
string
-->“Hello”

Entity objects

Este tipo de objetos se comparan en función de su identidad. Son iguales si tienen la misma identidad, sin importar el contenido o valor. También es usual encontrarlos con atributos de identificación.

En este modelo, el objeto tiene una identidad única e irrepetible. Además, el modelo permite que el estado del objeto vaya cambiando a lo largo del tiempo. Por lo tanto, aquello que tiene sentido que mute a lo largo del tiempo, suele implementarse como Entity Object.

Los Entity Objects suelen ser complejos y grandes. Pueden ser referenciados en muchas partes del código.

Custormer, Account o User son ejemplos típicos de este modelo.

Veamos un ejemplo. La siguiente función trabaja con la edad y la identidad de un usuario. El estado de la variable age va cambiando, así como el de la variable id. Conceptualmente, me sirve para comparar y diferenciar un objeto de otro por su identidad.

function user() {
let id = Math.random();
let age = 23;
return {
getAge: function() {
return age;
},
birthday: function() {
++age;
},
getId: function() {
return id;
}
}
}
var user1 = user();user1.getId();
--> 0.06233091571730198
var user2 = user();user2.getId();
--> 0.9024949171443875
user1.birthday();
user1.getAge();
--> 24

Elementos del DOM

Un ejemplo común de Entity se produce con los elementos del DOM.

Este botón es una entidad. Le puedo cambiar su estado, por ejemplo, al modificar una clase, pero siempre tendrá la misma identidad. Lo que diferencia al botón de otro botón no es su contenido, si no su identificador.

¿Cuándo usar Value Object y cuando Entity Object?

Es el contexto quien nos indica si implementamos el modelo Value Object o Entity Object.

Los objetos pequeños, como podría ser points, son buenos ejemplos de Value Object, aunque estructuras más grandes también se pueden programar con este modelo. Dependerá de si tiene sentido que cambie el estado o no, de si necesita compartir referencias, si no tiene una identidad conceptual…

En otros casos, tendrá sentido utilizar referencias. Por ejemplo, con pedidos de ropa, puedo cargar cada pedido en un mismo lugar. Y si quiero ver que un determinado pedido se encuentra en la próxima entrega, puedo tomar la referencia de la memoria (identidad o referencia) del pedido y compararlo con la lista de pedidos en la entrega.

Es importante hacerse una idea de cómo cada objeto puede manejar la igualdad y programarlo según las expectativas que realizamos de su comportamiento.

Fuentes

http://wiki.c2.com/?ValueObject

https://martinfowler.com/bliki/ValueObject.html

https://www.youtube.com/watch?v=h3vWBe0f1OA

--

--