quinta-feira, 22 de janeiro de 2015

CQRS


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

Data da Tradução: 19/01/2015
Última atualização: 03/03/2021