Ainda me lembro dos bons e velhos tempos dos repositórios. Mas os repositórios costumavam ficar feios com o tempo. Então o CQRS se tornou popular. Eles eram legais, eram uma lufada de ar fresco. Mas, recentemente, tenho me perguntado repetidamente por que não mantenho a lógica correta no método Action do controlador (especialmente na API da Web, onde action é algum tipo de manipulador de comando / consulta).
Anteriormente, eu tinha uma resposta clara para isso: faço isso para testar, pois é difícil testar o Controller com todos esses singletons imbatíveis e a feia infraestrutura geral do ASP.NET. Mas os tempos mudaram e as classes de infraestrutura do ASP.NET são muito mais amigáveis hoje em dia, principalmente nos testes de unidade (especialmente no ASP.NET Core).
Aqui está uma chamada típica da WebApi: o comando é adicionado e os clientes SignalR são notificados sobre isso:
public void AddClient(string clientName)
{
using (var dataContext = new DataContext())
{
var client = new Client() { Name = clientName };
dataContext.Clients.Add(client);
dataContext.SaveChanges();
GlobalHost.ConnectionManager.GetHubContext<ClientsHub>().ClientWasAdded(client);
}
}
Eu posso facilmente testar / zombar dele. Além disso, graças ao OWIN, posso configurar servidores WebApi e SignalR locais e fazer um teste de integração (e bem rápido, a propósito).
Recentemente, senti cada vez menos motivação para criar manipuladores pesados de comandos / consultas e tenho a tendência de manter o código nas ações da API da Web. Só faço uma exceção se a lógica for repetida ou for realmente complicada e eu quiser isolá-la. Mas não tenho certeza se estou fazendo a coisa certa aqui.
Qual é a abordagem mais razoável para gerenciar a lógica em um aplicativo ASP.NET moderno típico? Quando é razoável mover seu código para manipuladores de comandos e consultas? Existem padrões melhores?
Atualizar. Encontrei este artigo sobre a abordagem DDD-lite. Portanto, parece que minha abordagem de mover partes complicadas do código para manipuladores de comandos / consultas pode ser chamada de CQRS-lite.
Respostas:
O CQRS é um padrão relativamente complicado e caro? Sim.
É excesso de engenharia? Absolutamente não.
No artigo original em que Martin Fowler fala sobre o CQRS, você pode ver muitos avisos sobre a não utilização do CQRS, onde não é aplicável:
Minha ênfase acima.
Se o seu aplicativo está usando o CQRS para tudo, então não é o CQRS que tem excesso de engenharia, é o seu aplicativo. Esse é um excelente padrão para resolver alguns problemas específicos, especialmente aplicativos de alto desempenho / alto volume, nos quais a simultaneidade de gravação pode ser uma grande preocupação.
E pode não ser o aplicativo inteiro, mas apenas uma pequena parte dele.
Como exemplo ao vivo do meu trabalho, empregamos o CQRS no sistema de entrada de pedidos, onde não podemos perder nenhum pedido, e temos picos em que milhares de pedidos vêm ao mesmo tempo de diferentes fontes, em algumas horas específicas. O CQRS nos ajudou a manter o sistema ativo e responsivo, enquanto nos permitia escalar bem os sistemas de back-end para processar esses pedidos mais rapidamente quando necessário (mais servidores de back-end) e mais lento / barato quando não necessário.
O CQRS é perfeito para o problema em que você tem vários atores colaborando no mesmo conjunto de dados ou gravando no mesmo recurso.
Fora isso, espalhar um padrão feito para resolver um único problema para todos os seus problemas criará mais problemas para você.
Alguns outros links úteis:
http://udidahan.com/2011/04/22/when-to-avoid-cqrs/
http://codebetter.com/gregyoung/2012/09/09/cqrs-is-not-an-architecture-2/
fonte
O CQRS não é um substituto um para um dos Repositórios, exatamente porque é um padrão complexo e caro que só é útil em alguns casos.
Aqui está o que Udi Dahan tem a dizer em mérito:
( fonte )
Martin Fowler:
( fonte )
Finalmente, Greg Young:
( fonte )
fonte