Tengo una parte del patrón CQRS implementado usando S # arp Architecture de esta manera:
public class MyCommand
{
public CustomerId { get; set; }
// some other fields
}
public class MyCommandHandler<MyCommand> : ICommandHandler<MyCommand, CommandResult>
{
Handle(MyCommand command)
{
// some code for saving Customer entity
return CommandResult.Success;
}
}
Me pregunto por qué no solo tener una clase que Command
contiene datos y un método de manejo. ¿Es un tipo de beneficio de comprobabilidad, donde necesita probar la lógica de manejo de comandos por separado de las propiedades del comando? ¿O es algún requisito comercial frecuente, donde necesita tener un comando manejado por diferentes implementaciones ICommandHandler<MyCommand, CommandResult>
?
c#
design-patterns
architecture
cqrs
rgripper
fuente
fuente
Respuestas:
Es curioso, esta pregunta me recordó exactamente la misma conversación que tuve con uno de nuestros ingenieros sobre la biblioteca de comunicaciones en la que estaba trabajando.
En lugar de comandos, tuve clases de Request y luego tuve RequestHandlers. El diseño se parecía mucho a lo que estás describiendo. Creo que parte de la confusión que tienes es que ves la palabra inglesa "comando", y al instante piensas "verbo, acción ... etc.".
Pero en este diseño, piense en Command (o Request) como una carta. O para aquellos que no saben qué es un servicio postal, piense en el correo electrónico. Es simplemente contenido, desacoplado de cómo se debe actuar sobre ese contenido.
¿Por qué harías esto? En la mayoría de los casos simples, del Patrón de comando no hay razón y puede hacer que esta clase realice el trabajo directamente. Sin embargo, hacer el desacoplamiento como en su diseño tiene sentido si su acción / comando / solicitud debe recorrer cierta distancia. Por ejemplo, a través de enchufes o tuberías, o entre dominio e infraestructura. O tal vez en su arquitectura sus comandos deben ser persistentes (por ejemplo, el controlador de comandos puede hacer 1 comando a la vez, debido a algunos eventos del sistema, llegan 200 comandos y después del cierre de los primeros 40 procesos). En ese caso, al tener una clase simple de solo mensaje, se vuelve muy simple serializar solo la parte del mensaje en JSON / XML / binary / whatever y pasarlo por la tubería hasta que su controlador de comandos esté listo para procesarlo.
Otra ventaja de desacoplar Command de CommandHandler es que ahora tiene la opción de jerarquía de herencia paralela. Por ejemplo, todos sus comandos podrían derivar de una clase de comando base que admita la serialización. Y tal vez tenga 4 de 20 manejadores de comandos que tengan mucha similitud, ahora puede derivarlos de la clase base de manejador vino. Si tuviera que manejar datos y comandos en una clase, este tipo de relación se descontrolaría rápidamente.
Otro ejemplo para el desacoplamiento sería si su comando requiriera muy poca entrada (por ejemplo, 2 enteros y una cadena), pero su lógica de manejo era lo suficientemente compleja como para almacenar datos en las variables miembro intermedias. Si pone en cola 50 comandos, no desea asignar memoria para todo ese almacenamiento intermedio, por lo que separa Command de CommandHandler. Ahora puede poner en cola 50 estructuras de datos livianas y el almacenamiento de datos más complejo se asigna solo una vez (o N veces si tiene N controladores) por el CommandHandler que procesa los comandos.
fuente
El patrón de comando normal se trata de tener los datos y el comportamiento en una sola clase. Este tipo de 'patrón de comando / controlador' es ligeramente diferente. La única ventaja en comparación con el patrón normal es la ventaja añadida de que su comando no dependa de los marcos. Por ejemplo, su comando puede necesitar acceso a la base de datos, por lo que debe tener algún tipo de contexto o sesión de base de datos, lo que significa que depende de los marcos. Pero este comando puede ser parte de su dominio, por lo que no desea que dependa de marcos de acuerdo con el Principio de Inversión de Dependencia . Separar los parámetros de entrada y salida del comportamiento y tener un despachador para conectarlos puede solucionar esto.
Por otro lado, perderá la ventaja de la herencia y la composición de los comandos. Lo que creo que es el verdadero poder.
Además, menor nitpick. El hecho de que tenga Command in name no lo hace parte de CQRS. Eso se trata de algo mucho más fundamental. Este tipo de estructura puede servir como comando y como consulta incluso al mismo tiempo.
fuente