Partilhar via


Aplicar padrões CQRS e DDD simplificados em um microsserviço

Gorjeta

Este conteúdo é um trecho do eBook, .NET Microservices Architecture for Containerized .NET Applications, disponível no .NET Docs ou como um PDF para download gratuito que pode ser lido offline.

.NET Microservices Architecture for Containerized .NET Applications eBook cover thumbnail.

CQRS é um padrão arquitetônico que separa os modelos de leitura e gravação de dados. O termo relacionado Command Query Separation (CQS) foi originalmente definido por Bertrand Meyer em seu livro Object-Oriented Software Construction. A ideia básica é que você pode dividir as operações de um sistema em duas categorias bem separadas:

  • Consultas. Essas consultas retornam um resultado e não alteram o estado do sistema, e são livres de efeitos colaterais.

  • Comandos. Esses comandos alteram o estado de um sistema.

CQS é um conceito simples: trata-se de métodos dentro do mesmo objeto sendo consultas ou comandos. Cada método retorna o estado ou muta o estado, mas não ambos. Mesmo um único objeto padrão de repositório pode estar em conformidade com o CQS. O CQS pode ser considerado um princípio fundamental para o CQRS.

Command and Query Responsibility Segregation (CQRS) foi introduzido por Greg Young e fortemente promovido por Udi Dahan e outros. Baseia-se no princípio CQS, embora seja mais detalhado. Pode ser considerado um padrão baseado em comandos e eventos e, opcionalmente, em mensagens assíncronas. Em muitos casos, o CQRS está relacionado a cenários mais avançados, como ter um banco de dados físico diferente para leituras (consultas) do que para gravações (atualizações). Além disso, um sistema CQRS mais evoluído pode implementar o Event-Sourcing (ES) para seu banco de dados de atualizações, portanto, você armazenaria apenas eventos no modelo de domínio em vez de armazenar os dados de estado atual. No entanto, essa abordagem não é usada neste guia. Este guia usa a abordagem CQRS mais simples, que consiste em apenas separar as consultas dos comandos.

O aspeto de separação do CQRS é alcançado agrupando operações de consulta em uma camada e comandos em outra camada. Cada camada tem seu próprio modelo de dados (note que dizemos modelo, não necessariamente um banco de dados diferente) e é construída usando sua própria combinação de padrões e tecnologias. Mais importante ainda, as duas camadas podem estar dentro da mesma camada ou microsserviço, como no exemplo (ordenação de microsserviço) usado para este guia. Ou podem ser implementados em diferentes microsserviços ou processos para que possam ser otimizados e dimensionados separadamente sem afetar uns aos outros.

CQRS significa ter dois objetos para uma operação de leitura/gravação onde em outros contextos há um. Há razões para ter um banco de dados de leituras desnormalizado, que você pode aprender na literatura CQRS mais avançada. Mas não estamos usando essa abordagem aqui, onde o objetivo é ter mais flexibilidade nas consultas em vez de limitar as consultas com restrições de padrões DDD, como agregados.

Um exemplo desse tipo de serviço é o microsserviço de pedidos do aplicativo de referência eShopOnContainers. Este serviço implementa um microsserviço baseado numa abordagem CQRS simplificada. Ele usa uma única fonte de dados ou banco de dados, mas dois modelos lógicos mais padrões DDD para o domínio transacional, como mostra a Figura 7-2.

Diagram showing a high level Simplified CQRS and DDD microservice.

Figura 7-2. Microsserviço simplificado baseado em CQRS e DDD

O Microsserviço Lógico de "Pedidos" inclui seu banco de dados de Pedidos, que pode ser, mas não precisa ser, o mesmo host do Docker. Ter o banco de dados no mesmo host do Docker é bom para o desenvolvimento, mas não para a produção.

A camada de aplicação pode ser a própria API Web. O aspeto de design importante aqui é que o microsserviço dividiu as consultas e ViewModels (modelos de dados criados especialmente para os aplicativos cliente) dos comandos, modelo de domínio e transações seguindo o padrão CQRS. Essa abordagem mantém as consultas independentes de restrições e restrições provenientes de padrões DDD que só fazem sentido para transações e atualizações, conforme explicado nas seções posteriores.

Recursos adicionais