¿Cuán granular debe ser un comando en un modelo CQ [R] S?

17

Estoy considerando un proyecto para migrar parte de nuestra SOA basada en WCF a un modelo de bus de servicio (probablemente nServiceBus) y estoy usando algún pub-sub básico para lograr la separación de consulta de comandos .

No soy nuevo en SOA, ni siquiera en los modelos de bus de servicio, pero confieso que hasta hace poco mi concepto de "separación" se limitaba a la duplicación y replicación de bases de datos habituales. Aún así, me atrae la idea porque parece proporcionar todos los beneficios de un sistema eventualmente consistente , mientras que evita muchos de los inconvenientes obvios (especialmente la falta de soporte transaccional adecuado).

Leí mucho sobre el tema de Udi Dahan, quien es básicamente el gurú de las arquitecturas ESB (al menos en el mundo de Microsoft), pero una cosa que dice realmente me desconcierta:

A medida que obtenemos entidades más grandes con más campos en ellas, también obtenemos más actores que trabajan con esas mismas entidades, y mayor es la probabilidad de que algo toque algún atributo de ellas en un momento dado, lo que aumenta el número de conflictos de concurrencia.

[...]

Un elemento central de CQRS es repensar el diseño de la interfaz de usuario para permitirnos capturar la intención de nuestros usuarios de tal manera que hacer que un cliente sea preferido es una unidad de trabajo diferente para el usuario que indicar que el cliente se ha mudado o que se ha conseguido casado. El uso de una interfaz de usuario similar a Excel para los cambios de datos no captura la intención, como vimos anteriormente.

- Udi Dahan, CQRS aclarado

Desde la perspectiva descrita en la cita, es difícil discutir con esa lógica. Pero parece ir contra la corriente con respecto a las SOA. Se supone que una SOA (y realmente los servicios en general) se ocupan de los mensajes de grano grueso para minimizar el parloteo de la red, entre muchos otros beneficios.

Me doy cuenta de que la charla en la red es un problema menor cuando tienes sistemas altamente distribuidos con una buena cola de mensajes y nada del equipaje de RPC, pero no parece prudente descartar el problema por completo. Udi casi parece estar diciendo que cada cambio de atributo (es decir, actualización de campo) debería ser su propio comando, lo cual es difícil de imaginar en el contexto de un usuario que potencialmente actualiza cientos o miles de entidades y atributos combinados, como suele ocurrir con un sistema tradicional. servicio web.

Una actualización por lotes en SQL Server puede tomar una fracción de segundo dada una buena consulta altamente parametrizada, un parámetro con valores de tabla o una inserción masiva en una tabla de ensayo; procesar todas estas actualizaciones de una en una es lento, lento, lento , y el hardware de la base de datos OLTP es el más costoso de escalar / escalar.

¿Hay alguna manera de conciliar estas preocupaciones en competencia? ¿Estoy pensando en eso de manera incorrecta? ¿Este problema tiene una solución bien conocida en el mundo CQS / ESB?

Si no es así, ¿cómo se decide cuál debería ser el "nivel correcto" de granularidad en un Comando? ¿Existe algún "estándar" que se pueda usar como punto de partida, como el 3NF en las bases de datos, y que solo se desvíe cuando un perfil cuidadoso sugiera un beneficio de rendimiento potencialmente significativo?

¿O es posiblemente una de esas cosas que, a pesar de que varios expertos expresan varias opiniones fuertes, es realmente solo una cuestión de opinión?

Aaronaught
fuente

Respuestas:

7

Sobre el tema de "cada cambio de atributo"

Creo que te perdiste el punto. El Sr. Udi Dahan dice que debes capturar la intención del usuario como un comando. Un usuario final se preocupa por poder indicar que un cliente se ha mudado. Dependiendo del contexto, ese comando podría contener una identificación del cliente, la nueva dirección (dividida en calle, número de calle, código postal, ...), opcionalmente un nuevo número de teléfono (no es raro cuando se muda, quizás menos con todos estos teléfonos celulares) . Eso no es un atributo. Una mejor pregunta es "¿Cómo diseño comandos?". Los diseñas desde una perspectiva de comportamiento. Cada caso de uso, flujo, tarea que un usuario final intenta completar, se capturará en uno o más comandos. Los datos que acompañan a esos comandos vienen naturalmente, a medida que comienza a razonar sobre ellos con más detalle. Lo que hay que tener en cuenta son los datos que se interpretan como "podría ser una indicación de que necesita dividir el comando. Espero que nunca encuentres ese estándar con respecto a la granularidad de comandos. Buena pregunta sin embargo!

Yves Reynhout
fuente
Esta definición todavía me parece muy arbitraria; El modelo conceptual de un CSR puede agrupar el estado preferido y el estado marcial juntos de la misma manera que agrupa la dirección y el código postal. No me refiero a dividir los pelos, solo me parece que para comprender realmente si son comportamientos diferentes, debe ser capaz de predecir los efectos posteriores, y OTOH, toda la idea de ESB y CQS y pub / sub es que se supone que no debes saber o preocuparte por lo que sucede aguas abajo. Gracias por su respuesta, yo lo aprecio, aunque no puedo decir que me siento más iluminados hasta ahora ...
Aaronaught
@Aaronaught: La definición es arbitraria. La granularidad de un comando debe ser lo que tenga sentido para su escenario particular . No hay una talla única para todos. Existen varias pautas, como la coincidencia de comandos para usar casos, tareas o acciones disponibles en la interfaz de usuario; otra es preferir los comandos más granulares sobre los comandos menos granulares (especialmente porque Yves dijo que desconfía de los datos que se interpretan como flujo de control lógico). Pero no hay una regla dura y rápida. ¿Existe un escenario real en el que "un usuario pueda actualizar potencialmente cientos o miles de entidades y atributos combinados"?
quentin-starin
¡Ese es todo el punto! No te juntes. ¡Divide según el comportamiento! No ponga datos en el comando que no se alineen con la intención del comando / usuario final. Y eso no se trata de sistemas posteriores.
Yves Reynhout
@qes: En nuestros sistemas hay varios escenarios de este tipo, muy reales y muy necesarios. Para decirlo de la manera más simple posible, necesitan modificar secuencias completas de datos y estas secuencias solo tienen sentido como secuencias. Por supuesto, generalmente no realizan estos cambios registro por registro, aplican algún algoritmo a la mayor parte y luego solucionan algunas excepciones. Quizás este no sea un escenario apropiado para comenzar con CQS, pero esa decisión es solo un subconjunto de mi pregunta más amplia.
Aaronaught
1
@qes: bastante justo, y esa es una respuesta en sí misma. Ciertamente entiendo el concepto de una operación lógica (así es como se modelan los servicios existentes), supongo que me preocupa que CQS parezca cambiar algunas de las reglas sobre cómo debería definir una operación. La SOA "tradicional" parece comenzar desde la definición más gruesa posible y descender en la escala de abstracción si es necesario; Mi comprensión de CQS hasta ahora parece indicar lo contrario, comenzar desde la definición más granular posible y abstracto si se parece demasiado a RPC o flujo de control.
Aaronaught
2

El mensaje que Udi está tratando de transmitir es que CQRS es más que solo CRUD. ¿Por qué creé este registro? ¿Por qué estoy cambiando este registro? ¿Por qué se elimina / marca como eliminado?

Los comandos deben corresponder a acciones / casos de uso que el usuario realiza con el sistema y expresar la intención de la acción en lugar de simplemente decir cambiar esto. Además, puede parecer que es más fino, pero podría ser mucho más grueso de lo que parece. Por ejemplo, la actualización al estado de oro podría implicar un cambio en varios atributos y una serie de otros agregados podrían incluso responder y cambiar en respuesta al evento correspondiente.

CQRS se trata de capturar el idioma de la empresa en la capa de Servicio para que la interfaz de usuario no tenga que preocuparse por lo que sucede cuando realizo esa actualización de estado de oro o el transportista ha marcado que el envío no ha sido entregado o el empleado ha sido promovido al gerente del grupo de tecnología. Bueno, técnicamente estoy hablando de Event Sourcing ahora, pero me entiendes. Hay mensajes más distintos, pero no son necesariamente más detallados que los CUD estándar.

Michael Brown
fuente