DDD y objetos de valor. Son objetos de valor mutables un buen candidato para Non Aggr. Entidad Raíz?

9

Aquí hay un pequeño problema

Tener una entidad, con un objeto de valor. No es un problema. Reemplazo un objeto de valor por uno nuevo, luego nhibernate inserta el nuevo valor y deja huérfano al antiguo, luego lo elimina. Ok, eso es un problema

Asegurado es mi entidad en mi dominio. Tiene una colección de direcciones (objetos de valor). Una de las direcciones es MailingAddress. Cuando queremos actualizar la dirección de correo, digamos que el código postal era incorrecto, siguiendo la doctrina del Sr. Evans, debemos reemplazar el objeto antiguo por uno nuevo ya que es inmutable (¿un objeto de valor correcto?).

Pero no queremos eliminar la fila, porque la PK de esa dirección es un FK en una tabla MailingHistory. Entonces, siguiendo la doctrina del Sr. Evans, estamos bastante jodidos aquí. A menos que haga mis Entidades de direcciones, así que no tengo que "reemplazarlo", y simplemente actualizar su miembro de código postal, como en los viejos tiempos.

¿Qué me sugerirías en este caso? A mi modo de ver, ValueObjects solo son útiles cuando desea encapsular un grupo de columnas de la tabla de la base de datos (componente en nhibernate). Todo lo que tenga una identificación de persistencia en la base de datos, es mejor convertirlo en una Entidad (no necesariamente una raíz agregada) para que pueda actualizar sus miembros sin recrear todo el gráfico del objeto, especialmente si es un objeto anidado profundamente.

¿Está de acuerdo? ¿Está permitido por el Sr. Evans tener un objeto de valor mutable? ¿O es un objeto de valor mutable un candidato para una Entidad?

Gracias

Pepito Fernández
fuente
2
¿Existe tal cosa como "objeto de valor mutable"? Siempre tuve la impresión de que los objetos de valor son inmutables.
herby
@herby Supongo que podría tener un objeto mutable que represente un objeto de valor DDD en el código, pero debería tener en cuenta que una vez que muta el objeto, ya no hace referencia al mismo objeto lógico de valor DDD sino a uno nuevo. Esto puede ser deseable, pero es una receta para la confusión, hacer que los objetos de valor sean inmutables en el código es una convención inteligente.
MattDavey

Respuestas:

8

Todo lo que tiene una identidad debe ser una Entidad, y todo lo que no tiene una identidad es un valor simple, por lo tanto, un objeto de valor.

Para citar a Martin Fowler (que a su vez le pregunta a Eric Evans)

  • Entidad: Objetos que tienen una identidad distinta que se ejecuta a través del tiempo y diferentes representaciones. También escucha estos llamados "objetos de referencia".
  • Objeto de valor: los objetos que importan solo tienen la combinación de sus atributos.

Motivo para hacer de su dirección un Objeto de valor:

Si su dirección es mutable, probablemente arruinará su historial de correo al final. Por ejemplo, si está enviando artículos a un cliente, no puede estar seguro de a qué dirección envió realmente algo en el pasado si la dirección a la que se refiere su tabla MailingHistory ha cambiado.

La entrada de MailingHistory Enviamos A764 a la dirección 657 podría significar que enviamos el artículo A764 a Boston ayer y enviamos el artículo A764 a Nueva York mañana.

Si se debe cambiar la dirección de correo, no es necesario eliminar la anterior. Guárdelo y márquelo como inactivo , y el nuevo como activo .


Por supuesto, podría tratar su dirección como una Entidad, pero solo al actualizarla no cambiaría el lugar real al que se refiere la dirección, por lo tanto, solo permitirá la corrección de errores tipográficos.

Si está seguro de que podría asegurarse de eso, sería posible usar una Entidad.


Pero la mejor solución en mi humilde opinión es no hacer referencia a una entidad de dirección en su historial de correo, sino guardar la dirección específica directamente en su tabla de historial de correo (básicamente copiando los datos de la dirección).

De esta manera, siempre sabrá dónde envió sus cosas (o lo que sea que esté enviando), y dado que usaría una Entidad mutable, su tabla de direcciones no estará abarrotada.

He trabajado con / en varios sistemas ERP, y casi todos utilizaron este enfoque.

Tendrá algo de redundancia en su base de datos, pero es la forma más pragmática en mi humilde opinión.

perezoso
fuente
Esta es probablemente la solución más libre de dolor de cabeza. Solo si espera que los canales de comunicación futuros requieran columnas adicionales, y su base de datos es demasiado grande ALTER, puede ser necesario usar entidades en tablas separadas. Eso, a su vez, requiere estrategias como "unirse siempre a la dirección / teléfono / correo electrónico más reciente " en sus SELECTconsultas, que son difíciles de mantener mantenibles y eficientes. Mantenlo simple, si es posible.
Timo
@Timo "unirse siempre a la nueva dirección / teléfono / correo electrónico" no es difícil si desnormaliza un poco sus datos simplemente agregando una activebandera. Por supuesto, debe asegurarse de usar siempre and active = trueen sus Uniones, mantener actualizado el indicador y agregar una restricción a su tabla para que, por ejemplo, solo un correo electrónico para cada cliente pueda tener este indicador establecido en verdadero.
pereza
Esto introduce el problema de desactivar el anterior. Si ha reemplazado el objeto de Dirección "actual" de su instancia en el código, y va a su código de acceso a datos, entonces no sabrá (1) si hay uno nuevo, ni (2) cuál es el potencial viejo uno fue. Por lo tanto, cada operación de guardar tendrá que hacer algo complicado como "primero ir y desactivar todas las direcciones relacionadas en la base de datos", y luego guardar la actual con active=true. Esto no es lo que yo llamaría simple, que es exactamente por qué me gusta su solución.
Timo
2

Veo 2 cosas:

  1. ¿Está bien que el cambio de código postal afecte un registro de historial? Creo que sería lógico que el registro del historial apunte a la dirección anterior sin cambios, para que sepa que la envía a una dirección incorrecta.

  2. En el momento en que MailingHistory tiene FK en la dirección, la dirección dejó de ser un objeto de valor y se convirtió en una entidad. Los objetos de valor no tienen identidad, lo que permite que otras entidades hagan referencia a esta identidad. Puede tener direcciones en una sola tabla con otras tablas apuntando a ella, pero el único efecto es ahorrar espacio. Desde el punto de vista del dominio, si dos entidades tienen el mismo tipo de objeto de valor de referencia, entonces no comparten ningún tipo de información.

Eufórico
fuente
2

OMI, el objeto de dirección es una entidad en su dominio. Es compartido por múltiples entidades, tiene su propia identidad y es único en todo el sistema.

Evans dice:

Un objeto definido principalmente por su identidad se llama entidad.

margabit
fuente
Las identidades de dominio, a mi entender, no tienen nada que ver con la identidad de persistencia. Según el libro del señor Evan.
Pepito Fernández
Tienes razón. Edito mi respuesta. Lo que quiero decir es que la dirección del objeto sí importa en este dominio específico, es único. OMI, la clave externa y la clave primaria es una señal de que en realidad es un objeto único en todo el dominio, por lo que tiene una identidad.
margabit
1
"el objeto de la dirección ... tiene su propia identidad" , ¿qué atributo de una dirección lo identifica de forma exclusiva? Ningún atributo único de una dirección es único, pero la combinación de atributos sirve como identidad. Esta es la definición misma de un objeto de valor
MattDavey
@MattDavey: es una buena conclusión, pero me confundo cuando Tony dice "no queremos eliminar la fila, porque la PK de esa dirección es un FK en una tabla de MailingHistory". Esto significa para mí que el objeto Dirección también tiene un significado fuera del 'Asegurado' agregado. Lo que me indica que el objeto 'Dirección' no debería ser un ValueObject. ¿Qué piensas?
margabit
¿Podríamos decir que los objetos de valor serían invariablemente una composición de propiedad total (UML) del padre? Además, un objeto de valor no tendría sentido sin su padre y no se puede compartir entre los padres.
Sudarshan