Você está na página 1de 43

CQRS

É originado no padrão CQS, ou Command-Query Separation,


de Bertrand Meyer, que diz o seguinte: Cada método deve ser
um comando que realiza uma ação ou uma consulta que
retorna dados, mas não ambos
"Because the term command is widely used in other
contexts I prefer to refer to them as modifiers, you also
see the term mutators"

Martin Fowler

CQS ajuda a eliminar os efeitos colaterais que


podem existir quando invocamos um método
Além de respeitar o Single Responsibility Principle,
evitando que o método mude por motivos diferentes
De certa forma é mais um conselho do que uma regra já
que em muitos cenários é complicado de aplicar, por
exemplo, na hora de desempilhar um elemento ou em
um ambiente multi-thread mais intenso
Qual é a relação do CQS com o CQRS?
O padrão CQRS, ou Command Query Responsibility
Segregation, criado por Greg Young, também envolve separar
os comandos que processam regras de negócio, realizando
mutação de estado, das consultas que retornam apenas uma
visão sobre os dados, só que de uma forma mais ampla
CQS está apenas no nível de classes e métodos,
CQRS tem relação com o modelo de domínio
No Domain-Driven Design, modelamos nossas
regras de negócio por meio de objetos de domínio
A execução de uma regra de negócio tem mais
relação com a escrita ou com a leitura?
Comprar de um produto
Calcular os impostos
Agendar um exame
Matricular um aluno
Normalmente, a persistência dos aggregates é
feita por meio dos repositories
A granularidade do repository é no nível de
aggregate, que por padrão devem ser pequenos
Todos os dados precisam ser obtidos por meio de
um repositório? Qual é o problema disso?
Dependendo da consulta pode ser muito
complexo obter dados de múltiplos aggregates
O relacionamento entre aggregates é por identidade
{
"date": "2021-03-10",
"code": "2021000001", Order
"itens": [
{
"description": "Guitar",
"price": 1000,
"quantity": 1
},
{
"description": "Amplifier", Item
"price": 5000,
"quantity": 1
}
],
"total": 6000,
"freight": 300,
"customer": {
"name": "Rodrigo Branas", DTO Assembly Customer
"cpf": "11111111111",
"telephone": "99999999"
},
"taxes": [
{
"ipi": 120,
"icms": 200
} Taxes
]
}

CQRS promove a separação do modelo de


escrita do modelo de leitura
CQRS

• Comandos devem ser orientados a tarefas


específicas, não aos dados
• Eventualmente podem ser colocados em
uma fila e processados de forma assíncrona
• Consultas nunca modificam os dados, não
envolvem o domínio e apenas retornam os
dados em um DTO

Favorece a existência de objetos de domínio e


repositórios focados nas regras de negócio
Obtenção de dados sem passar pelo domínio,
evitando complexidade nas consultas
Application

Command Stack

Domain Model

Usuário Banco de dados


Read Model

Query Stack
Para utilizar CQRS precisamos obrigatoriamente
separar os dados de escrita e de leitura?
Calma, não necessariamente...
O principal motivo é performance, o modelo de
persistência nem sempre é otimizado para consulta
Qual é o papel da normalização em um banco de
dados relacional?
Normalização

• Reduzir a duplicação de dados entre


diferentes tabelas, otimizando a ocupação de
disco e também o risco de atualizar uma
informação em uma tabela e esquecendo
das outras
• Garantir a consistência nas operações
realizadas sobre os dados
• Permite a combinação criando projeções
especificadas dependendo das necessiades

A normalização tem mais relação com a escrita ou


com a leitura dos dados?
Não é recomendado renderizar relatórios ou estatísticas
complexas a partir do banco de dados utilizado para a
escrita, principalmente se ele for relacional
Application

Command Stack
Banco de dados
(escrita)

Domain Model

Sync

Usuário
Read Model

Banco de dados
(leitura)

Query Stack

É importante entender que ao separar os dados


temos que lidar com um outro problema...
CAP Theorem

• AC: Sem particionamento, os dados estão


consistentes e disponíveis
• AP: Com particionamento, ao optar pela
disponibilidade, se a conexão entre os nodos
cair, perdemos consistência
• CP: Com particionamento, ao optar pela
consistencia, se a conexão entre os nodos
cair, perdemos disponibilidade

Normalmente neste tipo de cenário se favorece a


disponibilidade com consistência eventual
O banco de dados de escrita precisa ser relacional
e o de leitura precisa ser NoSQL?
Se o objetivo é armazenar múltiplas projeções
não estruturadas, talvez seja melhor usar NoSQL
Como manter o banco de leitura sincronizado?
É possível atualizar ao longo da transação de escrita
de forma síncrona ou mesmo criar um mecanismo
mais resiliente e assíncrono, publicando eventos e
consumindo em uma fila
A utilização de eventos adiciona
complexidade no espaço da solução

Você também pode gostar