Eu tenho uma parte do padrão CQRS implementada usando a arquitetura S # arp como esta:
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;
}
}
Gostaria de saber por que não apenas ter classe Command
contendo dados e método de manipulação? É um tipo de benefício de testabilidade, no qual você precisa testar a lógica de manipulação de comandos separadamente das propriedades do comando? Ou é algum requisito comercial frequente, onde você precisa ter um comando tratado por diferentes implementações de ICommandHandler<MyCommand, CommandResult>
?
c#
design-patterns
architecture
cqrs
rgripper
fonte
fonte
Respostas:
Engraçado, essa pergunta me lembrou exatamente a mesma conversa que tive com um de nossos engenheiros sobre a biblioteca de comunicações em que estava trabalhando.
Em vez de comandos, eu tinha classes Request e, em seguida, tinha RequestHandlers. O design era muito parecido com o que você está descrevendo. Eu acho que parte da confusão que você tem é que você vê a palavra em inglês "comando" e pensa instantaneamente em "verbo, ação ... etc".
Mas neste design, pense em Command (ou Request) como uma carta. Ou para aqueles que não sabem o que é um serviço postal, pense no e-mail. É simplesmente conteúdo, dissociado de como esse conteúdo deve ser usado.
Por que você faria isso? Na maioria dos casos simples, do Padrão de Comando não há razão e você pode fazer com que essa classe execute o trabalho diretamente. No entanto, fazer a dissociação como no seu design faz sentido se sua ação / comando / solicitação precisar percorrer alguma distância. Por exemplo, entre, soquetes ou tubulações, ou entre domínio e infraestrutura. Ou talvez na sua arquitetura seus comandos precisem ser persistentes (por exemplo, o manipulador de comandos pode executar 1 comando por vez, devido a alguns eventos do sistema, 200 comandos chegam e após os primeiros 40 processos serem desligados). Nesse caso, tendo uma classe simples de mensagem, torna-se muito simples serializar apenas a parte da mensagem em JSON / XML / binário / qualquer que seja e transmiti-la pelo pipeline até que seu manipulador de comandos esteja pronto para processá-la.
Outra vantagem da dissociação do Command do CommandHandler é que agora você tem a opção de hierarquia de herança paralela. Por exemplo, todos os seus comandos podem derivar de uma classe de comando base que suporta serialização. E talvez você tenha 4 dos 20 manipuladores de comando que têm muita semelhança, agora você pode derivar aqueles da classe base do manipulador fornecido. Se você tivesse manipulação de dados e comandos em uma classe, esse tipo de relacionamento rapidamente sairia do controle.
Outro exemplo para a dissociação seria se o seu comando exigisse muito pouca entrada (por exemplo, 2 números inteiros e uma string), mas sua lógica de manipulação fosse complexa o suficiente para que você desejasse armazenar dados nas variáveis de membro intermediárias. Se você enfileirar 50 comandos, não deseja alocar memória para todo esse armazenamento intermediário, para separar Command e CommandHandler. Agora você enfileira 50 estruturas de dados leves e o armazenamento de dados mais complexo é alocado apenas uma vez (ou N vezes se você tiver N manipuladores) pelo CommandHandler que está processando os comandos.
fonte
O padrão de comando normal é sobre ter os dados e o comportamento em uma única classe. Esse tipo de 'padrão de comando / manipulador' é um pouco diferente. A única vantagem comparada ao padrão normal é a vantagem adicional de não ter seu comando dependente das estruturas. Por exemplo, seu comando pode precisar de acesso ao banco de dados, portanto, ele precisa ter algum tipo de contexto ou sessão de banco de dados, o que significa que depende das estruturas. Mas esse comando pode fazer parte do seu domínio, portanto você não deseja que ele dependa de estruturas de acordo com o Princípio de Inversão de Dependência . Separar os parâmetros de entrada e saída do comportamento e ter algum despachante para conectá-los pode corrigir isso.
Por outro lado, você perderá vantagem da herança e da composição dos comandos. O que eu acho que é o verdadeiro poder.
Além disso, nitpick menor. Só porque ele tem Command no nome, não faz parte do CQRS. Isso é algo muito mais fundamental. Esse tipo de estrutura pode servir como comando e como consulta, mesmo ao mesmo tempo.
fonte