domain-driven-design cqrs

domain-driven-design - cqrs c#



Comandos y consultas de CQRS: ¿pertenecen al dominio? (3)

El comando y los eventos son DTOs. Puede tener manejadores de comandos y consultas en cualquier capa / componente. Un evento es solo una notificación de que algo cambió. Puedes tener todo tipo de eventos: Dominio, Aplicación etc.

Los eventos pueden ser generados por el manejador y el agregado depende de usted. Sin embargo, independientemente de dónde se generen, el controlador de comandos debe usar un bus de servicio para publicar los eventos. Prefiero generar eventos de dominio dentro de la raíz agregada.

Desde el punto de vista estratégico de DDD, solo hay conceptos de negocios y casos de uso. Eventos de dominio, comandos, manejadores son detalles técnicos. Sin embargo, todos los casos de uso de dominio generalmente se implementan como un controlador de comandos, por lo tanto, los controladores de comandos deben ser parte del dominio, así como los controladores de consultas que implementan las consultas utilizadas por el dominio. Las consultas utilizadas por la interfaz de usuario pueden ser parte de la interfaz de usuario y así sucesivamente.

El punto de CQRS es tener al menos 2 modelos y el Comando debe ser el propio modelo de dominio. Sin embargo, puede tener un modelo de consulta , especializado para el uso del dominio, pero sigue siendo un modelo de lectura (simplificado). Considere el modelo de comando como usado solo para actualizaciones, el modelo de lectura solo para consultas. Pero, puede tener múltiples modelos de lectura (para ser utilizados por una capa o componente específico) o simplemente uno genérico (usado para todo lo que se consulte).

En CQRS, ¿los comandos y las consultas pertenecen al dominio?

¿Los eventos también pertenecen al dominio?

Si ese es el caso, ¿son las implementaciones de Command / Query Handlers solo en la infraestructura?

Ahora mismo lo tengo dispuesto así:

Application.Common Application.Domain - Model - Aggregate - Commands - Queries Application.Infrastructure - Command/Query Handlers - ... Application.WebApi - Controllers that utilize Commands and Queries

Otra pregunta, ¿de dónde planteas los eventos? ¿El controlador de comandos o el agregado de dominio?


En algunas implementations , los comandos y los controladores están en la capa de aplicación. In others , pertenecen al dominio. A menudo he visto lo primero en sistemas OO, y lo último más en implementaciones funcionales, que también es lo que hago yo mismo, pero YMMV.

Si por eventos te refieres a Eventos de Dominio, bueno ... sí, recomiendo definirlos en la capa de Dominio y emitirlos desde objetos de dominio. Los eventos de dominio son una parte esencial de tu lenguaje ubicuo e incluso serán acuñados directamente por expertos en dominios si practicas Storming de eventos, por ejemplo, por lo que definitivamente tiene sentido colocarlos allí.

Lo que creo que debería tener en cuenta es que no hay una regla sobre la mayoría de estos detalles técnicos que merece ser escrita en piedra. Existen innumerables preguntas sobre los proyectos de plantillas de DDD y las capas y el código de "topografía" en el SO, pero, francamente, no creo que estos problemas sean decisivos para crear una aplicación sólida, eficaz y mantenible, especialmente porque dependen del contexto. Lo más probable es que no organice el código para un sistema de comercio con millones de cambios agregados por minuto de la misma manera que lo haría con una plataforma de publicación de blogs utilizada por 50 personas, incluso si ambas están diseñadas con un enfoque DDD. A veces tienes que probar cosas por ti mismo según tu contexto y aprender a lo largo del camino.


Comandos y eventos pueden ser de muy diferentes preocupaciones. Pueden ser problemas técnicos, problemas de integración, problemas de dominio ...

Supongo que si pregunta por el dominio, está implementando un modelo de dominio (tal vez incluso con Diseño impulsado por dominio).

Si este es el caso, intentaré darte una respuesta realmente simplificada, para que puedas tener un punto de partida:

  • Comando : es una intención comercial, algo que quieres que haga un sistema. Mantener la definición de los comandos en el dominio. Técnicamente es solo un DTO puro. El nombre del comando siempre debe ser imperativo " PlaceOrder ", " ApplyDiscount " Un comando se maneja solo por un controlador de comandos y se puede descartar si no es válido (sin embargo, debe hacer toda la validación posible antes de enviar el comando a su dominio para no puede fallar)
  • Evento : esto es algo que ha sucedido en el pasado. Para el negocio es el hecho inmutable que no se puede cambiar. Mantener la definición del evento de dominio en el dominio. Técnicamente también es un objeto DTO. Sin embargo, el nombre del evento siempre debe estar en el pasado " OrderPlaced ", " DiscountApplied ". Los eventos en general son pub / sub. Un editor de muchos manejadores.

Si ese es el caso, ¿son las implementaciones de Command / Query Handlers solo en la infraestructura?

Los controladores de comandos son semánticamente similares a la capa de servicio de la aplicación. En general, la capa de servicio de la aplicación es responsable de organizar el dominio. A menudo se construye alrededor de casos de uso comercial como, por ejemplo, "Realizar un pedido". En esos casos de uso, invoque la lógica de negocios (que siempre debe estar encapsulada en el dominio) a través de raíces agregadas, consultas, etc. También es un buen lugar para manejar asuntos transversales como transacciones, validación, seguridad, etc.

Sin embargo, la capa de aplicación no es obligatoria. Depende de los requisitos funcionales y técnicos y de las opciones de arquitectura que se hayan realizado. Su layring parece correcto. Mejor mantendría a los manejadores de comandos en el límite del sistema. Si no hay una capa de aplicación adecuada, un controlador de comandos puede desempeñar una función del orquestador de casos de uso. Si lo coloca en el Dominio, no podrá manejar las preocupaciones transversales con mucha facilidad. Es una compensación. Usted debe ser consciente de los pros y los contras de su solución. Puede funcionar en un caso y no en otro.

En cuanto a los manipuladores de eventos. Lo manejo en general en

  • Capa de aplicación si el evento activa la modificación de otro Agregado en el mismo contexto acotado o si el evento activa algún servicio de infraestructura.
  • Capa de infraestructura si el evento debe dividirse en varios consumidores o integrar otro contexto acotado.

De todos modos no debes seguir ciegamente las reglas. Siempre hay compensaciones y se pueden encontrar diferentes enfoques.

Otra pregunta, ¿de dónde planteas los eventos? ¿El controlador de comandos o el agregado de dominio?

Lo estoy haciendo desde la raíz agregada del dominio. Porque el dominio es responsable de elevar eventos. Como siempre hay una regla técnica, no debe publicar eventos si hubo un problema que persista en los cambios en el agregado y viceversa. Tomé el enfoque utilizado en la obtención de eventos y eso es pragmático. Mi raíz agregada tiene una colección de eventos no Unpublished . En la implementación de mi repositorio inspeccionaría la colección de eventos no Unpublished y los pasaría al middleware responsable de la publicación de eventos. Es fácil controlar que si hay una excepción que persiste en una raíz agregada, los eventos no se publican. Algunos dicen que no es responsabilidad del repositorio, y estoy de acuerdo, pero a quién le importa. Cual es la eleccion ¿Tiene un código extraño para la publicación de eventos que se arrastra en su dominio con todas las preocupaciones de infraestructura (transacción, manejo de excepciones, etc.) o es pragmático y controla todo en la capa de Infraestructura? He hecho ambas cosas y créeme, prefiero ser pragmático.

En resumen, no hay una sola manera de hacer las cosas. Siempre conozca las necesidades de su negocio y los requisitos técnicos (escalabilidad, rendimiento, etc.). Que haga sus elecciones basadas en eso. He descrito lo que generalmente he hecho en la mayoría de los casos y eso funcionó. Es solo mi opinión.