Existem muitos padrões de arquitetura disponíveis no momento e muitos outros estão por vir. Fato é que alguns projetos foram bem sucedidos e outros não, sejam estes utilizando o padrão da moda DDD (Domain Driven Desing) ou qualquer outro padrão de arquitetura.

Mas o que seria um Padrão?

O arquiteto e Professor Christopher Alexande no livro “A Times Way of Building” descreveu que um padrão é uma regra de três partes que expressa a relação entre um contexto, um problema e uma solução.

Costumo responder esta pergunta apresentando um padrão sendo uma formula para solucionar um problema sob um contexto definido podendo ser aplicável de tal forma que sua solução possa ser utilizada muitas vezes, mesmo que você o faça de maneiras diferentes.

Um padrão só se constituirá como um padrão se puder ser utilizado repetidamente.

Imagine um mapa nele você pode escolher e aplicar uma estratégia para chegar a um destino, uma solução. Entenda os padrões como um mapa, eles não ajudarão a determinar qual aplicação você deve estar escrevendo mas pode lhe mostrar como implementar melhor sua aplicação. Os padrões ajudam com o que e como, mas não com o por que ou quando.

Nestes últimos anos como desenvolvedor entendi a necessidade do alinhamento do código com o negócio, mas também vejo muitos as mudanças nos negócios se adaptando ao mercado ou pura e simplesmente como uma evolução do estado anterior.

Com estes pensamentos dispostos, como podemos atender a evolução (ágil) dos dias atuais e ainda conseguir favorecer a reutilização de código (ou blocos de construção), como desacoplar um sistema o dividindo em varias partes e como não se perder com o tempo?

As imagens abaixo fazem parte um estudo feito por Pablo Picasso, que durou cerca de dois meses. Durante esse tempo, o pintor refez várias vezes um desenho de um touro. Desenho a desenho ele identificava partes do desenho anterior que poderiam ser removidas, sem que a essência da idéia fosse perdida.

Pablo Picasso

Pablo Picasso

Utilizamos Padrões com o objetivo de extrair e reconhecer a essência de um sistema mesmos nestes dias loucos de tecnologias brotando pelo chão, que mudam freqüentemente modelos de negócio e os requisitos que vai e vem, um padrão de arquitetura sólido e estável é praticamente uma ilusão.

E nesta utopia toda gostaria de falar de um padrão não muito novo mas que acredito seja maleável o suficiente buscando atender os dias atuais, atendendo pequenos problemas de forma específica, lembra do touro? utilize o padrão a seguir apenas quando o que sobrar for simples e facilmente reconhecido.

Quero falar de CQRS (Command Query Responsibility Segregation).

O padrão CQRS foi documentado originalmente por Greg Young, durante a implementação de projetos utilizando os conceitos de Domain Driven Design (DDD) descrevendo como separar as operações de leitura e escrita em diferentes modelos.

Alguns projetos foram bem sucedidos, outros não. A verdade é que um modelo de objeto abrangente que cubra todos os aspectos funcionais ou não funcionais de um sistema de software é uma utopia, mas sempre seguiremos tentando certo?

Mesmo não sendo o brinquedo mais recente e legal de especialistas de software o CQRS não é tão complexo como a maioria dos exemplos disponíveis. O que ajuda muito sua aplicação.

Simplificando, CQRS é um padrão de arquitetura provavelmente mais apropriado para aplicativos simples de pequeno porte, independentemente do tempo de vida esperado e de sua complexidade.

Em outro artigo descreverei o conceito de aplicativos ou sistemas de grande porte formado por pequenos aplicativos simples e especialistas estando estes totalmente desacoplados e independentes, o que faz com que o CQRS possa ser adotado em quase todos os projetos de Software. Fazendo uma referencia ao touro de Picasso imagine pequenos desenhos onde removemos traços de outros animais e ainda sim não perdemos sua essência e em conjunto com o todo conseguimos entender o ecossistema estando harmonioso. Pequenos sistemas especialistas atendendo em conjunto formando um sistema de grande porte.

Voltando a falar sobre CQRS, não há apenas uma maneira de fazer CQRS existem pelo menos três sabores diferentes a sua escolha: o simples, o premium e o deluxo. Em uma busca rápida na internet encontraremos mais exemplos e artigos na categoria de deluxo, que em sua maioria são uma abordagem muito complexa e um exagero para aplicações mais comuns, é o inverso do touro de Picasso adicionamos muitos traços perdendo a essência do projeto.

A separação disposta no CQRS está no agrupamento das operações de leitura em uma camada e a de escrita/comandos em outra camada. Cada camada tem seu próprio modelo de dados, seu próprio conjunto de serviços e é construído utilizando a sua própria combinação de padrões e tecnologias.

cqrs

O mais importante, as duas camadas podem até estar em dois níveis distintos e ser optimizadas separadamente sem afetar uma a outra.

Lembra quando comentei sobre Padrões, então vamos utilizar da regra e contextualizar um problema a ser solucionado utilizando o padrão CQRS.

Contexto e Problema.

Nos sistemas tradicionais de gerenciamento de dados, ambos comando de escrita e leitura são executadas contra o mesmo conjunto de entidades em um único repositório de dados. Essas entidades podem ser um subconjunto de linhas em uma ou mais tabelas em um banco de dados relacional como o SQL Server.

Normalmente a interação com estas aplicações são aplicadas à mesma representação da entidade. Por exemplo, um objeto de transferência de dados (DTO) representando um cliente é recuperado do repositório de dados pela camada de acesso de dados (DAL) e apresentada em uma tela. Um usuário atualiza alguns campos do DTO (talvez através de ligação de dados) e do DTO então é salvo de volta no repositório de dados pela DAL. O mesmo DTO é utilizado para operações tanto de leitura quando de escrita.

As desvantagens do modelo tradicional

Em muitos casos há uma incompatibilidade entre as representações de leitura e escrita dos dados, como colunas ou propriedades adicionais que devem ser atualizados corretamente mesmo que eles não sejam requeridas como parte de uma operação.

Corremos sempre o risco de encontrar contenção de dados (onde múltiplos atores operam em paralelo sobre o mesmo conjunto de dados) quando os registros são bloqueados no repositório de dados, ou em conflitos de atualização causado por atualizações simultâneas. Esses riscos aumentam à medida que a complexidade e a taxa de transferência do sistema cresce.

Além disso, a abordagem tradicional pode também ter um efeito negativo sobre o desempenho devido à carga na camada de repositório de dados e de acesso a dados, pois exigem consultas complexas para recuperar informação.

O modelo tradicional transforma o gerenciamento de segurança e permissões muito mais complicado porque cada entidade está sujeita a ambas as operações de leitura e escrita, que pode inadvertidamente expor dados no contexto errado.

Contextualizamos o problema e Solução? Vamos tentar utilizar uma solução utilizando o CQRS.

O CQRS é um padrão que segrega as operações de leitura dos dados (consultas) das operações que atualizam dados (comandos de escrita) usando interfaces separadas. Onde os modelos de dados usados para leitura e escrita são diferentes e os modelos podem ser, em seguida, isolados, embora isso não seja um requisito absoluto.

Utilizando de modelos de leitura e escrita separadas para os dados em sistemas baseados no CQRS simplificamos consideravelmente desenho e implementação da solução. No entanto, uma desvantagem é que, ao contrário de projetos CRUD, código CQRS não pode ser automaticamente gerado por mecanismos de scaffold.

A camada de domínio que cuida dos comandos de escrita só se preocupa com os dados e regras de negócio e de segurança necessários para realizar tarefas. A camada de domínio que cuida da leitura, por outro lado, pode ser tão simples como uma consulta SQL direta através de uma ligação ADO.NET.

O modelo de consulta para leitura de dados e o modelo de atualização para gravação de dados podem acessar o mesmo repositório de dados, ou pode-se distinguir fisicamente entre repositórios de escrita e outro somente leitura mantendo um espelhamento periódico entre as alterações efetuadas no repositório de dados liberado para gravação. Isso nos traz mais performance, porém por outro lado incluiremos uma possível item de falha, quando ocorre algum problema na infra-estrutura de replicação de dados no projeto.

Caso necessite do acesso on-line dos dados alterados por seus usuários ou processos não indico adicionar um repositório de dados distinto somente leitura pois causaria uma complexidade grande em seu modelo de replicação de dados.

Existem outros casos onde o acesso a informação atualizada pode ocorrer após alguns minutos ou horas, como por exemplo, uma atualização em um sistema WIKI que em sua regra de negócio compreende uma fase de analise e aprovação, com dois repositório de dados nos preocupamos apenas em liberar o dado para a sua replicação e manter um historio de alterações enquanto isso o repositório somente leitura está atendendo seu publico.

Para projetos onde o dado atualizado é imprescindível também podemos utilizar o modelo CQRS porém adicionando um controle de segurança na camada de apresentação, a pilha de consulta torna-se um wrapper em torno Entity Framework ou o que quer que você usa para consultar dados.

Assim na camada de leitura, você estará livre para moldar dados em estreita semelhança com suas necessidades sem duplicar ou replicar dados para acomodar as necessidades de apresentação ou de negócios variadas.

Em CQRS, a camada de domínio de escrita só está preocupada com a execução de tarefas que modificam o estado do aplicativo. A camada de aplicação recebe solicitações a partir da apresentação e orquestra execução dos comandos de escrita para o pipeline.

No caso mais simples, a execução do comando consiste em simplesmente invocar uma transação desencadeando um fluxo de trabalho simples que realiza todas as etapas exigidas pela tarefa, que por sua vez pode ser executado de forma paralela agilizando a sua conclusão.

É importante analisarmos os prós e contras do padrão CQRS.

O poder da CQRS reside no fato de que você pode otimizar pipelines de escrita e leitura à vontade, sem o risco de que uma otimização possa quebrar a outra. A forma mais básica de CQRS usa um, banco de dados compartilhado e chama bibliotecas distintas para leituras e gravações de camada de aplicação.

Formas mais sofisticadas podem ter vários bancos de dados, persistência poliglota, desnormalização dados para fins de consulta, event sourcing e, mais importante, uma forma mais flexível para distribuir comandos para o back-end.

A camada de escrita tem uma pilha de processamento completa com lógica de negócios, validação de entrada, e a validação de negócios para garantir que tudo está sempre consistente, na camada de escrita cada conjunto de objetos associados ou não são tratados como uma unidade para efeitos de alterações de dados.

Na camada de leitura não existe nenhuma lógica de negócios ou de validações retornando um DTO para uso em um modelo de exibição.

Quando posso utilizar o Padrão CQRS?

Quando suas interfaces são baseadas em tarefas guiando os usuários através de um processo complexo como uma série de etapas. Com modelos de domínio complexos e apenas com equipes que já estão familiarizados com tecnicas de DDD (Domain-Driven Design).

Cenários onde o número de operações de leitura é em magnitude maior do que o número de operações de escrita, lembrando que com um pequeno número de instâncias de escrita ajudamos a minimizar a ocorrência de conflitos de mesclagem.

Cenários onde uma equipe de desenvolvedores podem se concentrar no modelo de domínio mais complexo que é parte da camada de escrita, e uma outra equipe menos experiente possa se concentrar na camada de leitura e as interfaces de usuário.

Onde a integração com outros sistemas, especialmente em combinação com Event Sourcing, onde a falha temporal da execução de uma alteração não afete a disponibilidade dos outros.

Quando não utilizar o CQRS?

Onde o domínio ou as regras de negócio são complexas demais ou quando uma interface de usuário de estilo CRUD e operações de acesso a dados relacionados são suficientes.

Existem entusiastas buscando implementar CQRS em todo tipo de sistema. Mas quase sempre adicionamos mais complexidade e muitas vezes desnecessariamente trazemos para o projeto pontos para o insucesso, não utilize CQRS onde realmente não é necessário.

Ser útil vai depender muito se a equipe tem experiência com DDD ajudando a determinar a arquitetura de todo o sistema, mas lembre-se quando o sistema é bastante complexo e você está utilizando CQRS você está adquirindo alguns problemas. Utilize de forma a atender componentes de seu sistema não como arquitetura mais alta.

O CQRS é um detalhe de implementação tática, não uma implementação estratégia.

Fique ligado, nos próximos artigos desta série iremos desenvolver alguns exemplos neste Padrão utilizando ASP .NET MVC.

Referencias:
https://msdn.microsoft.com/pt-br/library/dn568103.aspx
http://www.infoq.com/br/news/2011/11/cqrs
http://www.infoq.com/news/2013/05/cqrs-tutorial-csharp
http://martinfowler.com/bliki/CQRS.html
http://www.cqrsinfo.com/

Leonardo Norbiato – Apaixonado por tecnologia atuando como consultor em desenvolvimento de softwares desde 1998. Fundador da Workinside Tecnologia atendendo empresas do ramo high tech a partir de 2006. Coordenador de Projetos no Grupo NewSpace desde 2013. Praticante de cubo de rubik, curioso e dedicado buscando sempre colaborar com o munto Open Source. Está em um relacionamento sério com o .NET desde 2002 mas tem algumas amantes como Java, PHP, Perl, ABAP. Pode ser localizado no site workinside.com.br.

Frase
“O que vai deixar, trocar, prover ou criar nesta vida? Transforme, mude, crie, viva! Faça como o primeiro relampejo de vida se agarre nas oportunidades e não se esqueça, compartilhe e evoluiremos!”
Leonardo Norbiato

Facebook LinkedIn 

Comentários

comentarios