Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
August 19, 2022 03:05 pm GMT

Design: CQRS - Desfazendo mal-entendidos

Ol!

Este mais um post da seo Design e, desta vez, trago o contedo em um formato diferente. No pretendo explicar detalhadamente o pattern arquitetural CQRS, mas sim esclarecer alguns pontos sobre ele que so comumente confundidos -- e mal difundidos! -- pela comunidade .NET.

Vou comear com duas provocaes:

  1. CQRS no tem a ver com MediatR;
  2. CQRS, sem um domnio complexo, no CQRS!

Perdido? J esclareo. Vamos l!

O objetivo do pattern

Quando Greg Young props o pattern, em 2010, o problema que ele visava resolver era a impossibilidade de conciliar um modelo de domnio rico, mais especificamente um Agregado do DDD, com um padro arquitetural baseado em dados, que suporta apenas 4 verbos (Create, Read, Update e Delete, o famoso CRUD).

Quando utilizamos DDD, nossa principal preocupao ter claro o jargo do domnio, aquilo que vai chamar de "Linguagem Ubqua (ou Onipresente)". Ou seja, se um dado modelo de domnio possui um verbo (que se traduzir em um mtodo) chamado, por exemplo, "Cancelar", simplesmente no haver um mtodo correspondente para este verbo em uma arquitetura baseada em CRUD (repare que, no caso de uma compra, por exemplo, "Cancelar" no o mesmo que "Deletar/Excluir").

Alm disso, existem duas questes quanto interface com o usurio: 1) interfaces do tipo CRUD se preocupam, exclusivamente, com o estado do DTO que a alimenta, enquanto em DDD estamos mais preocupados com o comportamento do modelo de domnio. Isso demanda um estilo de desenvolvimento de interface conhecido como "Interface baseada em tarefas". Ou seja, a ao a ser executada mais importante que o estado do modelo e; 2)nem sempre essa interface demanda todos os dados constantes do modelo de domnio, o que acaba gerando a necessidade de criar mapeamentos entre seu modelo de domnio e o DTO enviado ao usurio o que, alm de dar mais trabalho, acopla seu domnio sua camada de aplicao (seu controller, caso de uso ou qualquer que seja sua representao).

Com isso em mente, Greg Young resolveu pensar numa forma de criar um pattern arquitetural que desse conta dos problemas apresentados.

A origem do pattern

Greg Young se baseou em uma ideia proposta por Bertrand Meyer que, basicamente, dizia o seguinte:

"Uma operao que altera o estado de um objeto no deve retornar valor. E uma operao que retorne um valor no deve alterar o estado de um objeto".

Esta proposta ficou conhecida como CQS, que significa, em portus, "Segregao entre Consulta e Comando".

Ao contrrio da ideia do CQS, no entanto, que eventualmente precisa ser violada (como no mtodo pop de um array, que altera seu estado removendo um elemento mas tambm o retorna), o CQRS se pretende manter puro. Ou seja, um comando no deve retornar um valor (embora possa retornar um resulado), e uma consulta no deve executar um comando.

O aspecto mais importante, no entanto, no a mera separao entre comandos e consultas mas, sim, a separao entre modelo de domnio e modelo de apresentao (DTO). E neste ponto que comeo a responder s provocaes acima.

CQRS no tem nada a ver com MediatR

Muita gente acredita, por repetir informaes incorretas ou de fontes questionveis, que basta fazer uma implementao com MediatR, criando CommandHandlers e QueryHandlers e, pronto!, temos CQRS.

Pois bem. Esta crena est, completamente, incorreta!

Lembre-se do que foi dito acima: mais importante que separar comandos de consultas, separar o modelo de domnio do modelo de apresentao. Portanto, se voc apenas faz uma implementao com MediatR, mas segue utilizando DTOs que representam o estado do seu modelo de domnio (que, geralmente, vai refletir seu modelo de persistncia), voc estar, apenas, adicionando cdigo desnecessrio e, potencialmente, criando redundncias como, por exemplo, repetir em sua camada de persisncia a estrutura do DTO utilizado pela camada de aplicao. Voc poder dizer que est utilizando o Mediator Pattern, mas no que est implementando CQRS!

Nota: no tenho a pretenso de me colocar como uma fonte confivel. Estou, apenas, reproduzindo o contedo do prprio autor do pattern e, inclusive, estou sujeito a erros de interpretao. Portanto, eventuais crticas que me realinhem a este contedo sero muito bem-vindas!

Alm disso, h um segundo detalhe: MediatR sequer necessrio implementao de CQRS. No h, necessariamente, problema algum em sua camada de aplicao (por exemplo, um Controller em sua Web API) ter conhecimento sobre o CommandHandler ou QueryHandler -- isso sem dizer que haver um overhead no uso do MediatR, uma vez que o mesmo exige a criao de uma nova instncia do mediador a cada ativao.

Nota: claro que, se voc entender que este trade-off entre desempenho e desacoplamento tem uma relao positiva, no h razo para no usar, inclusive tenho um tutorial sobre o MediatR publicado no blog. Inclusive, faa um teste! Crie uma Web API com e uma sem MediatR e faa um teste de performance. um exerccio bem divertido!

A voc poderia me perguntar: mas, neste caso, vou injetar um monte de handlers no meu Controller?
E a resposta : definitavamente, no!
Pessoalmente, no recomendo o uso de um mesmo Controller para executar mais de uma operao neste caso, assumindo que seu Controller seja o equivalente ao seu Caso de Uso. A alternativa organizar seus Controllers no a partir do modelo de domnio que ele afeta (por ex.: OrderController), mas sim a partir das aes do usurio -- lembra da ideia de interface baseada em tarefas? aqui que ela faz sentido na camada de aplicao. Ou seja, seguindo o exemplo acima, teramos um PlaceOrderController, que teria injetado um PlaceOrderCommandHandler (ou uma instncia de IMediatR) e faria o restante do trabalho.

CQRS, sem um domnio complexo, no CQRS

Acredito que, a esta altura, este ponto esteja claro. Mas quero adicionar alguns comentrios.

Existem algumas estratgias possveis para separar seu modelo de domnio do modelo de apresentao, ento vou cit-las para conhecimento.

Eventos e Projees

Esta a primeira forma recomendada pelo Greg Young. Quando um comando executado, e o estado do modelo de domnio alterado, um evento de domnio lanado e, a partir dele, o modelo de apresentao atualizado. Neste cenrio, existiram duas reas de persistncia: uma para o modelo de domnio, e outra para o modelo de apresentao.

Note que, neste caso, a consistncia ser, necessariamente, eventual, j que haver algum tempo decorrido entre o lanamento do evento, sua captura, processamento, e atualizao do modelo de apresentao.

Nota: uma questo muito importante nesta situao a garantia de ordem no processamento dos eventos. Caso os eventos sejam processados fora de ordem, o estado tanto de seu modelo de domnio, quanto de seu modelo de apresentao, sero corrompidos. Este um ponto de ateno ao se optar por este modelo de atualizao.

Eventos como Persistncia

Esta a segunda forma recomendada pelo Greg Young. Da mesma forma que acima, um evento de domnio lanado aps a execuo de um comando mas, em vez de atualizar o estado do modelo de domnio, o prprio evento seria armazeado, e o estado do modelo seria um reflexo do processamento desses eventos em ordem de ocorrncia -- e a temos um outro pattern, chamado Event Sourcing.

Concluso

Como pudemos ver acima, CQRS muito mais que apenas separar algumas pores de cdigo e incluir o MediatR como uma espcie de service locator. Se voc no possui um domnio complexo, que demande essa diferenciao entre modelos de domnio e modelos de apresentao, interessante abrir mo desta abordagem para manter seu cdigo simples.

Do contrrio, vale muito a pena considerar o uso de CQRS junto com Event Sourcing, uma vez que estes patterns so complementares.

Gostou? Me deixe saber pelos indicadores.

Tem dvidas, crticas ou sugestes? Deixe um comentrio ou me procure nas redes sociais.

At a prxima!


Original Link: https://dev.to/wsantosdev/design-cqrs-desfazendo-mal-entendidos-5bpo

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To