Controladores de comando y DDD

10

Tengo una aplicación ASP.NET MVC, que utiliza un servicio de consulta para obtener datos y un servicio de comando para enviar comandos. Mi pregunta es sobre la parte del comando.

Si llega una solicitud, el servicio de comando usa un despachador de comando que enrutará el comando a su controlador de comando designado. Este controlador de comandos valida primero el comando y, si todo es aceptable, ejecuta el comando.

Ejemplo concreto: AddCommentToArticleCommandHandler recibe un AddCommentToArticleCommand, que tiene un ArticleId, CommentText y EmailAddress.

Primero; la validación tiene que ocurrir, como: - verifique si el artículo existe - verifique si el artículo no está cerrado - verifique si el texto del comentario está completado y entre 20 y 500 caracteres - verifica si la dirección de correo electrónico está completa y tiene un formato válido.

Me pregunto dónde poner esta validación.

1 / en el controlador de comandos en sí. Pero entonces, no se puede reutilizar en otros controladores de comandos.

2 / en la entidad de dominio. Pero como una entidad de dominio no conoce los repositorios o servicios, no puede hacer la validación necesaria (no puede verificar si existe un artículo). Pero, por otro lado, si la entidad no contiene lógica, se convierte en un simple contenedor de datos, que no sigue los principios DDD.

3 / el controlador de comandos utiliza validadores, de modo que la validación se puede reutilizar en otros controladores de comandos.

4 / Otros mecanismos?

Estoy buscando la cadena de responsabilidades para este ejemplo en particular y qué objetos (entidades, repositorios, ...) juegan un papel en él.

¿Tiene ideas sobre cómo implementar esto, comenzando desde el controlador de comandos hasta los repositorios?

L-cuatro
fuente
"Pero como una entidad de dominio no conoce los repositorios o servicios, ¿no puede hacer la validación necesaria"? Por qué no? ¿Qué principio de DDD requiere esto?
S.Lott
Leí en todas partes que una entidad no debería saber sobre repositorios ni nada más.
L-Four
¿Puede proporcionar una cita, un enlace o un ejemplo de lo que, específicamente, ha leído? No sabemos qué descripciones de DDD está leyendo.
S.Lott
Jimmy Bogard compartió algunos puntos de vista sobre este tema ... lostechies.com/jimmybogard/2009/02/15/validation-in-a-ddd-world
Mayo

Respuestas:

4

Creo que necesita separar dos tipos de validación en este caso; validación de dominio y validación de aplicaciones .

La validación de la aplicación es lo que tiene cuando verifica que la propiedad del comando 'texto' tiene entre 20 y 200 caracteres; entonces usted valida esto con la GUI y con un ver-modelo-validador que también se ejecuta en el servidor después de una POST. Lo mismo ocurre con el correo electrónico (por cierto, espero que se dé cuenta de que un correo electrónico como `32.d +" Hello World .42 "@ mindomän.local" es válido según la RFC).

Entonces tienes otra validación; compruebe que el artículo existe: debe hacerse la pregunta de por qué el artículo no debería existir si efectivamente hay un comando enviado desde la GUI que trata de adjuntarle un comentario. ¿Su GUI finalmente fue consistente y usted tiene una raíz agregada, el artículo, que puede eliminarse físicamente del almacén de datos? En ese caso, simplemente mueve el comando a la cola de errores porque el controlador de comandos no puede cargar la raíz agregada.

En el caso anterior, tendría una infraestructura que maneja los mensajes de envenenamiento; por ejemplo, volverían a intentar el mensaje de 1 a 5 veces y luego lo moverían a una cola de poision donde podría inspeccionar manualmente la colección de mensajes y volver a enviar los relevantes. Es bueno monitorear.

Entonces ahora hemos discutido:

  • Validación de la aplicación

    • Con javascript en la GUI
    • Con validación MVC en el servidor web
  • Faltan raíces agregadas + colas de veneno

¿Qué pasa con los comandos que no están sincronizados con el dominio? Tal vez tenga una regla en su lógica de dominio que dice que después de 5 comentarios a un artículo, solo se permiten comentarios por debajo de 400 caracteres, pero un tipo llegó demasiado tarde con el quinto comentario y llegó a ser el sexto: la GUI no lo captó porque no era coherente con el dominio en el momento en que él envió su comando; en este caso, tiene una 'falla de validación' como parte de la lógica de su dominio y devolvería el evento de falla correspondiente.

El evento podría tener la forma de un mensaje en un intermediario de mensajes o en su despachador personalizado. El servidor web, si la aplicación es monolítica, podría escuchar sincrónicamente tanto el evento de éxito como el evento de falla mencionado y mostrar la vista / parcial apropiada.

A menudo tiene eventos personalizados que significan fallas para muchos tipos de comandos, y es este evento al que se suscribe desde la perspectiva del servidor web.

En el sistema en el que estamos trabajando, estamos haciendo una solicitud-respuesta con comandos / eventos a través de un bus + broker de mensajes Mass Transit + RabbitMQ y tenemos un evento en este dominio en particular (modelando un flujo de trabajo en parte) que se denomina InvalidStateTransitionError. La mayoría de los comandos que intentan moverse a lo largo de un borde en el gráfico de estado pueden hacer que este evento suceda. En nuestro caso, estamos modelando la GUI según un paradigma eventualmente consistente, por lo que enviamos al usuario a una página de "comando aceptado" y, a partir de entonces, dejamos que las vistas del servidor web se actualicen pasivamente a través de suscripciones de eventos. Cabe mencionar que también estamos haciendo eventos de origen en las raíces agregadas (y también lo haremos para las sagas).

Como puede ver, muchas de las validaciones de las que está hablando son en realidad validaciones de tipo de aplicación, no lógica de dominio real. No hay problema en tener un modelo de dominio simple si su dominio es simple pero está haciendo DDD. Sin embargo, a medida que continúe modelando su dominio, descubrirá que es posible que el dominio no sea tan simple como resultó. En muchos casos, la entidad / raíz agregada podría aceptar una invocación de método causada por un comando y cambiar parte de su estado sin siquiera realizar ninguna validación, especialmente si confía en sus comandos como lo haría si los valida en el servidor web que usted controla

Puedo recomendar ver las dos presentaciones sobre DDD de Norwegian Developer Conference 2011 y también la presentación de Greg en Öredev 2010 .

Saludos, Henke

Henrik
fuente
¡Gracias! Una cosa acerca de la validación: en este momento, esta validación es activada por la IU (al emitir una solicitud de Validación (comando) al servicio), que utiliza la Validación () de la entidad Comentario. Luego, si el comando es válido, el cliente emite un comando Ejecutar, que ejecutará nuevamente Validate () para asegurarse, y si es válido, se ejecuta el comando real. Entonces, la validación principal la realiza la entidad Comentario, porque en todos los contextos la validación será la misma (el correo electrónico siempre debe ser válido, el texto del comentario no es demasiado largo, etc.) ¿Es este un buen enfoque?
L-Four
La validación que parece estar describiendo no me parece que justifique modelarla con un protocolo de validación de 2 fases; claro, valide los parámetros de invocación del método en la entidad como lo haría en una prueba unitaria, pero además de esto; la capa de aplicación / GUI podría validar fácilmente las reglas que está describiendo sin enviar comandos al dominio. Imo A menos que el cliente sea malicioso, el comando debería funcionar. Si el cliente es malicioso, entonces el comando falla y su modelo de lectura nunca obtiene un evento correspondiente y puede inspeccionar el comando problemático en la cola de errores.
Henrik
En la interfaz de usuario (ASP.NET MVC) estoy usando atributos de validación para hacer toda la validación. Entonces, si esta validación tiene éxito, entonces no tengo que validar de nuevo en el dominio, sino simplemente ejecutar el comando.
L-Four
1
Sí, ejecuta el comando pero asegúrese de que el comando no sea inválido tanto en la capa de aplicación como en el dominio.
Henrik
0

EDITAR: enlace WaybackMachine: http://devlicio.us/blogs/billy_mccafferty/archive/2009/02/17/a-response-to-validation-in-a-ddd-world.aspx

No hay una respuesta fácil.

Hay dos escenarios de proyecto claros que me vienen a la mente cuando intento responder dónde debería vivir la validación. El primero es en el que se usa una capa DTO para transferir información entre la vista y las capas de dominio. Por ejemplo, puede tener un objeto Cliente en su capa de dominio y un DTO de Cliente asociado en otra capa a la que asigna la información del Cliente, para luego dar a la vista la posibilidad de presentar la información del Cliente al usuario.

El segundo escenario es un proyecto en el que las entidades dentro de la capa de dominio se comparten directamente con la vista para presentar los datos al usuario. Por ejemplo, en lugar de mantener una capa DTO separada y un objeto de dominio de mapeo a los DTO que se entregarán a la vista, la vista podría recibir el objeto Cliente directamente. Entonces, en lugar de hablar a través de un DTO mantenido por separado para mostrar el nombre de un Cliente, la vista simplemente le pedirá al Cliente que se oponga por la información.

S.Lott
fuente