CQRS significa "Segregação de Responsabilidade entre Comando e Consulta" (do inglês Command Query Resposibility
Segregation). É um padrão que ouvi pela primeira vez descrito por Greg Young.
Segundo ele é a simples noção de que você pode usar um modelo diferente, para
atualizar informações, do modelo que você usa para ler as informações. Esta
simples ideia leva à algumas profundas consequências para o projeto de sistemas
de informação.
A abordagem tradicional que as pessoas usam para
interagir com um sistema de informação é tratar isto como um armazenamento de
dados CRUD. Com isto eu digo que nós temos um modelo mental de alguma estrutura
de registro onde nós podemos criar novos registro, ler registros, atualizar
registros existentes e excluir registros quando terminarmos com eles. Em um
simples caso, nossas interações são todas sobre o armazenamento e recuperação
destes registros.
Como nossas necessidades se tornam mais sofisticadas,
nós constantemente afastamos desse modelo. Nós podemos querer ver as informações
em um caminho diferente da base de registros, talvez unindo muitos registros em
um, ou formando registros virtuais para combinar informações em diferentes
lugares. Do lado da atualização nós podemos buscar regras de validação que
permita apenas certas combinações de dados para ser armazenado, ou podemos até
mesmo inferir que os dados sejam armazenados de forma diferente do que nós
fornecemos.
Como isso acontece, nós começamos a ver várias
representações da informação. Quando usuários interagem com a informação eles
usam várias apresentações para esta informação, cada uma das quais é uma
apresentação diferente. Desenvolvedores geralmente constroem seu próprio modelo
conceitual que eles usam para manipular os elementos centrais do modelo. Se você
estiver usando um modelo de domínio, então isso é geralmente sua representação
conceitual do domínio. Você normalmente também faz a armazenamento de
persistência o mais próximo do modelo conceitual que você puder.
Esta estrutura de muitas camadas de apresentação pode
ficar muito complicada, mas quando as pessoas fazem isto elas ainda simplificam
para uma única representação conceitual que atua como um ponto de integração
conceitual entre todas as apresentações.
A mudança que o CQRS introduz é dividir esse modelo
conceitual e separá-los em modelo para atualização e exibição, que ele se
refere como Command e Query respectivamente seguindo o vocabulário de
CommandQuerySeparation. A justificativa é que para muitos problemas,
particularmente em domínios mais complicados, tendo o mesmo modelo conceitual
para comandos e consultas leva a um modelo mais complexo que não faz bem.
Por ser modelos separados nós normalmente pensamos em
diferentes modelos de objeto, provavelmente executando em diferentes processos
lógicos, talvez em hardware separado. Um exemplo web seria um usuário olhando
para uma página web que foi processada usando um modelo de consulta. Se iniciar
uma mudança, que esta mudança é encaminhada para o modelo de comando separado
para processamento, o resultado da mudança é comunicada ao modelo de consulta
para tornar o estado atualizado. Há espaço para uma variação considerável aqui.
Os modelos em memória poderiam compartilhar o mesmo banco de dados, que no caso
o banco de dados aja como a interação entre os dois modelos. Porém eles também
podem usar base de dados separadas, efetivamente tornando o lado da base de
dados de consulta um ReportingDatabase em tempo real. Neste caso, eles precisam
de algum mecanismo de comunicação entre
os dois modelos ou seus banco de dados.
Os dois modelos podem não ser modelos de objetos
separados, pode ser que o mesmo objeto tenha diferentes interfaces para seu lado
command e seu lado query, um pouco como vistas em banco de dados relacionais.
Mas geralmente quando eu escuto sobre CQRS, eles são claramente modelos
separados.
CQRS se encaixa naturalmente com algum outro padrão
arquitetural.
- À medida que afastamos de uma única representação que interagimos via CRUD, nós podemos facilmente mover para um UI baseada em tarefas.
- Interagindo com o modelo de comando naturalmente caímos em comandos ou eventos, que entrosa melhor com Event Sourcing.
- Tendo modelos separados levanta questões sobre o quanto é difícil manter modelos consistentes, o que levanta a possibilidade da utilização de consistência eventual.
- Para muitos domínios, muita da lógica é necessária quando você está atualizando, então pode fazer sentido o uso de EagerReadDerivation para simplificar seu modelo do lado de consulta.
- CQRS é adequada para domínios complexos, do tipo que também se beneficiam de Domain-Driven Design.
Quando usar
Como todo padrão, CQRS é utilizado em alguns lugares,
mas não em outros. Muitos sistemas ajustam um modelo mental CRUD, e assim deve
ser feito neste estilo.
CQRS é um salto mental significativo para todos os
envolvidos, então não deve ser abordada ao menos que os benefícios vale a pena
o salto.
Em particular CQRS seria apenas usado em porções
especificas de um sistema (Bounded Context no jargão DDD), e não no sistema
como um todo. Nesta forma de pensar, cada Bounded Context precisa de suas
próprias decisões de como será modelado.
Até agora eu vi benefícios em duas direções.
Primeiramente é para lidar com complexidade - um domínio complexo pode ser
fácil de resolver usando CQRS. Eu tenho que limitar isso, normalmente há
sobreposição suficiente entre os lados de comando e consulta, e compartilhar um
modelo é fácil. Cada domínio tem diferentes características.
O outro principal benefício está em lidar com a
aplicações de alta performance. CQRS permite você separar o carregamento dos
leitores e escritores, permitindo você escalar cada independentemente. Se sua
aplicação vê um grande divergência entre leitura e escrita isto é muito útil.
Mesmo sem que, você possa aplicar diferentes estratégias de otimização dos dois
lados. Um exemplo disso é o uso de diferentes técnicas de acesso a banco de
dados para leitura e atualização.
Se seu domínio não é adequado para o CQRS, mas você
tem consultas que demandam complexidade adicional ou problemas de performance,
lembre que você ainda pode usar um ReportingDatabase. CQRS utiliza um modelo
separado para todas consultas. Com um reporting database você ainda usa seu
sistema principal para a maioria das consultas, mas deixa as mais exigentes a
cargo do reporting database.
Também é verdade que nós não temos uso suficiente de
CQRS na área ainda para estar confiante que entendemos os prós e contras.
Então, enquanto CQRS é um padrão, eu certamente o que na minha "caixa de
ferramentas", só não o manteria no topo.
Outras leituras
- Greg Young foi a
primeira pessoa que li sobre o assunto - este é o artigo dele que mais gosto.
- Udi Dahan é um outro defensor de CQRS, e ele tem uma
descrição detalhada da técnica.
- Há um site com informações de CQRS que Greg mantém. Sua
seção de documentos contém alguns materiais interessantes.
- Existe uma lista de email ativa para discutir o assunto.
- Greg Young está trabalhando em um livro sobre CQRS.
Traduzido por Antônio Flávio Castro
Artigo Original: http://martinfowler.com/bliki/CQRS.html
Data da Tradução: 19/01/2015
Última atualização: 03/03/2021
obrigado
ResponderExcluirGrato pela tradução, Antonio. Porém, "Comando de consulta de responsabilidade segregada" não é uma boa tradução para "Command Query Resposibility Segregation". Seria melhor: "Segregação de Responsabilidade entre Comando e Consulta" ou ainda "Responsabilidades Segregadas de Comando e Consulta"
ResponderExcluirMuito Obrigado, desculpe pela imensa demora!
ExcluirConcordo com o Ramalho quanto à tradução "Segregação de Responsabilidade entre Comando e Consulta".
ResponderExcluirObrigado, atualizado!
Excluir