2011-02-02 27 views
32

Digamos que tenemos una arquitectura inspirada en CQRS, con componentes tales como Comandos, Modelo de dominio, Eventos de dominio, Leer modelos DTO.
Por supuesto, podemos usar objetos de valor en nuestro modelo de dominio. Mi pregunta es, en caso de que también se pueden utilizar en:Objetos de valor en CQRS: dónde usar

  1. Comandos
  2. Eventos
  3. dtos

No he visto ningún ejemplo donde se utilizan los objetos de valor (VO) en los componentes mencionado anteriormente. En cambio, se usan tipos primitivos. Tal vez solo sean los ejemplos simplistas. Después de todo, mi comprensión del uso de VO en DDD es que actúan como un pegamento para toda la aplicación.

Mi motivación:

Comandos.
Digamos que el usuario envía un formulario que contiene campos de dirección. Tenemos Address Value Object para representar este concepto. Al construir un comando en el cliente, debemos validar la entrada del usuario de todos modos, y cuando está bien formado, podemos crear el objeto de Dirección allí mismo e inicializar el Comando con él. No veo la necesidad de delegar la creación del objeto Address en el controlador de comandos.

Eventos de dominio.
El modelo de dominio ya funciona en términos de objetos de valor, por lo que al publicar eventos con VO en lugar de convertirlos a tipos primitivos, podemos evitar algunos códigos de mapeo. Estoy bastante seguro de que está bien usar VO en este caso.

DTOs.
Si nuestros DTO del lado de la consulta pueden contener objetos de valor, esto permite un poco más de flexibilidad. Por ejemplo, si tenemos un objeto Money, podemos elegir si mostrarlo en EUR o USD, sin necesidad de cambiar el Modelo de lectura.

+3

Después de reflexionar sobre esto por un tiempo, mi conclusión: tener objetos ricos en comportamiento en Eventos es simplemente imposible, ya que deben representar datos históricos, y no tenemos forma de serializar el comportamiento hoy. En cuanto a los comandos y modelos de lectura DTO, esto podría funcionar, y todavía no está claro si el acoplamiento que introduce es aceptable o no (de todos modos, esto se trata más de "si las capas de dominio y presentación hacen referencia a la misma implementación de Money VO" en lugar de 'should TransferMoneyCommand contiene Money VO o MoneyDTO'). – driushkin

Respuesta

22

Ok, he cambiado de opinión. He intentado tratar con los VO un montón últimamente y después de ver esto http://www.infoq.com/presentations/Value-Objects-Dan-Bergh-Johnsson me aclararon un par de cosas.

Los comandos y eventos son mensajes (y no objetos, objetos son datos + comportamiento), en algunos aspectos muy parecidos a los DTO, comunican datos sobre un evento y no encapsulan ningún comportamiento.

Value Objects no son como DTO en absoluto. Son una representación de dominio y, en términos generales, son muy ricas en comportamiento, como en todas las demás representaciones de dominio.

Los comandos y eventos comunican información dentro y fuera del dominio respectivamente, pero ellos mismos no encapsulan ningún comportamiento. Desde esa perspectiva, parece incorrecto y posiblemente una violación de los límites del contexto pasar VO dentro de ellos.

Parafraseando a Oren (aunque se refería a nHibernate y WCF) "No envíe su dominio por el cable". http://ayende.com/Blog/archive/2009/05/14/the-stripper-pattern.aspx

Si desea comunicar un objeto de valor, sugiero que pase los atributos necesarios necesarios para reconstruir el VO dentro de ellos.

texto original (para la posteridad):

Si se está preguntando si el valor de los objetos se pueden pasar por el modelo de dominio a eventos o aprobadas en los comandos, realmente no ver un gran problema con el anterior, aunque este último puede violar algunas de las reglas de la raíz agregada como el "dueño" de los valores.

Dicho esto, un objeto de valor representa conceptos como, por ejemplo, un color. Usted no tiene verde, usted es verde o no. Parece que no hay nada intrínsecamente incorrecto con un comando que te dice que eres verde al pasar esto.

Al leer el capítulo de DDD en el patrón de raíz agregada, se explican Entidades y objetos de valor bastante bien y vale la pena leerlo varias veces.

+0

Creo que está bien desde la perspectiva DDD pura tener VO compartidos, pero desde el punto de vista de cqrs, esto puede presentar algunos problemas técnicos, como el control de versiones de eventos si se aplica Event Sourcing. Y luego surge la pregunta natural: ¿es realmente solo una cuestión técnica o es algo intrínsecamente erróneo con toda la idea? – driushkin

+0

La comprensión que tomé del libro DDD es que, aunque las raíces agregadas son las propietarias de sus respectivas entidades y objetos de valor, pueden transmitir una referencia a esos objetos transitoriamente. El único propósito de la raíz agregada es definir los límites transaccionales del sistema. De nuevo, puedo estar malinterpretando algo de esto y como siempre YMMV. Aunque definitivamente sería malo serializar una entidad como parte de un evento, no puedo ver ningún problema para los VO, ya que deberían representar un verdadero valor inmutable. –

+5

"Los objetos de valor no son como los DTO. Son una representación de dominio y son [...] ricos en comportamiento como en todas las demás representaciones de dominio". Estoy totalmente en desacuerdo con la última parte. Si bien forman parte del dominio (por ejemplo, definir qué es * una * dirección), están destinados a ser desechables y no tener ningún comportamiento asociado a ellos. Es por eso que generalmente son inmutables, para evitar que te metas con tu VO. – Dav

4

Digo que es una mala idea.

Hay una razón por la que no hacemos lo mismo con las entidades: para evitar acoplar otras partes del sistema al dominio (en los lugares incorrectos). Lo mismo es cierto para los objetos de valor, la única diferencia entre los objetos de valor y las entidades es la duración y la propiedad: estas diferencias no afectan la forma en que deberíamos y no deberíamos asociarlas.

Imagine que hace que un evento contenga un VO. Un cambio en su dominio requiere que cambie ese VO. Ahora ha encajado en una esquina donde su evento también es forzado para cambiar, lo mismo para cualquier Comando o DTO de los que sea parte.

Esto debe evitarse.

Use DTO y/o primitivos. Localícelos (AutoMapper lo convierte en un acuerdo de 1 línea).

+1

Bueno, esos VO no pertenecerían únicamente al Modelo de Dominio. Serían un conocimiento compartido en todos los componentes del sistema (como el ensamblado MyApp.Core al que cualquier persona puede hacer referencia). Siempre y cuando los conceptos sean estables, o incluso no tengan cambios de ruptura, creo que esto debería estar bien. Ofc, si usamos Event Sourcing, esto complicaría nuestro código con conceptos heredados que ya no están en uso pero que son parte de eventos antiguos. Así que este es un inconveniente que puedo pensar. Pero aún así, la idea de tener un módulo de conceptos compartidos (como Moneda, Dinero, Velocidad) en la aplicación me parece muy tentador. – driushkin

+0

Si son conceptos compartidos entre aplicaciones, diría que no son tanto parte del dominio (ya que el dominio, prácticamente por definición, es específico de la aplicación) ya que son infraestructura o código común. Estaba pensando eso en dinero específicamente cuando respondí. –

+0

También creo que el VO en CQRS es una mala idea, pero entonces, ¿cómo podemos encapsular la lógica de dominio cuando el agregado se vuelve complejo? –

3

Al igual que en otras respuestas, en SOA esto rompería la encapsulación del servicio ya que ahora se está filtrando el dominio.

0

De acuerdo con Clean Code sus DTO son estructuras de datos (solo para agregar otro término), mientras que los objetos de valor son objetos. La diferencia de que los objetos pueden tener comportamiento. En general, mezclar estructuras de datos con objetos es una muy mala idea, porque será difícil mantener el híbrido que obtienes.

No me parece correcto poner objetos de valor a los DTO desde una perspectiva de arquitectura también. Los objetos de valor están dentro del modelo de dominio mientras que los DTO que mencionó están definiendo la interfaz del modelo. Usualmente construimos una interfaz para desacoplar el mundo exterior del interior de algo. Entonces, en el caso actual, agregamos DTO para desacoplar el mundo exterior de los objetos de valor (y otras cosas relacionadas con el modelo). Después de eso, agregar objetos de valor a la interfaz es una locura.

Por lo tanto, aún no ha encontrado esta solución porque es un antipatrón.

+0

Entonces, ¿no deberíamos agregar ningún tipo de cadena o entero a DTO, ya que también es un objeto de valor? – bojanv55

+0

@ bojanv55 Las cadenas y los enteros son primitivos, no objetos de valor. Un objeto Date o DateTime hubiera sido un mejor ejemplo. Quise decir que los DTO no deberían transferir los VO definidos en el dominio. Por ejemplo, tenemos un VO en nuestro dominio relacionado con el nacimiento de alguien, p. 1985-12-20. Si consultamos el cumpleaños, entonces deberíamos devolver 12-20 en el DTO. Si consultamos la fecha de nacimiento, entonces deberíamos devolver 1985-12-20 en el DTO. Si consultamos la edad, entonces deberíamos devolver 31 años en el DTO. Entonces, la DTO no contendrá todo el VO con su lógica, solo la representación que realmente necesitamos. – inf3rno

+0

@ bojanv55 Al menos así es como uso DTOs y VOs. Este enfoque funcionó hasta ahora, pero ofc. No soy infalible :-) – inf3rno