Fail Fast — Validando Commands com MediatR e Fluent Validation

Nicolas Takashi
4 min readJul 15, 2019

--

CQS — Command Query Separation

Nos meus dois últimos artigos, falei sobre o padrão Command Query Segregation, desde a parte teórica até uma simples implementação em um projeto ASP.NET Core utilizando MediatR, caso você ainda não viu vou deixar os dois links aqui.

No artigo de hoje, vou continuar dentro do tópico abordado nos dois últimos artigos, porém hoje irei falar sobre validação dos parâmetros de uma Command.

Falhe rápido

Existe um conceito dentro do desenvolvimento de software chamado Fail Fast, não vou entrar muito afundo sobre o tópico, pois ele é ligeiramente extenso.

O conceito de Fail Fast prega que, quanto mais rápido você falhar mais rápido você vai saber, com isso devemos parar a nossa operação o mais rápido possível quando um erro acontecer.

Se você quiser saber mais sobre o assunto, recomendo que leia o artigo do Vladimir Khorikov, pois ele trata o assunto de forma mais completa.

Fluent Validation

Fluent Validation é uma famosa biblioteca no mundo .NET para criarmos regras de validação para nossos objetos de forma fluente e fortemente tipada.

Além de ser extremamente poderosa, essa ferramenta nos da possibilidade de retirar aquele código feio que geralmente temos para a validação de um modelo.

O Problema

Antes de entrarmos na solução e código, acho que é válido darmos um pequeno resumo sobre o problema.

Validar o estado e as informações de um objeto é algo extremamente comum no dia a dia do desenvolvedor, existem diversas bibliotecas para realizar esse tipo de trabalho, porém é muito comum que o que precisamos fazer é tão simples que não faz sentido utilizarmos uma biblioteca para isso.

A ideia do artigo de hoje é mostrar uma de várias possibilidades para realizar validações dos nossos objetos.

Implementação

No último artigo, criamos um projeto ASP.NET Core Web API para realizar a implementação do padrão CQS utilizando MediatR, vamos continuar trabalhando sobre esse projeto.

Primeira coisa que iremos fazer é adicionar o Fluent Validation para nosso projeto.

Install-Package FluentValidationInstall-Package FluentValidation.AspNetCore

Feito isso, estamos preparados para criar a nossa primeira classe de validação utilizando o Fluent Validation. Atualmente temos apenas uma única Command em nosso projeto, será sobre ela que iremos aplicar as validações necessárias.

Criaremos uma classe chamada CreateUserCommandValidation, e realizaremos a seguinte implementação.

Eu não entrarei em detalhes sobre métodos de validação com o Fluent Validation, deixo você a vontade para olhar a documentação oficial e se divertir.

Basicamente estamos validando se as propriedades são nulas e se a data de nascimento inserida é de uma pessoa maior de idade, com isso temos a nossa classe para validação da nossa Command criada.

Notificando o cliente sobre os erros de validação

No artigo onde apresento o padrão CQS Command Query Segregation, falamos sobre Commands não terem retorno, com isso você deve estar se perguntando como nós iremos retornar as mensagens de erro após a validação da nossa Command.

Para essa implementação, iremos utilizar um padrão chamado Domain Notification, assim conseguiremos notificar o recurso que disparou a Command, sem necessariamente ter o retorno de um objeto.

Caso você ainda não conheça esse padrão, aconselho você olhar o artigo que o Martin Fowler escreveu.

Não entrarei em detalhes sobre a implementação desse padrão, para não perdermos o foco do artigo, porém ao longo do artigo vocês entenderam o uso do padrão.

MediatR Pipeline Behaviour

Uma das funcionalidades do MediatR, é poder adicionar comportamentos antes ou depois de um Handler ser acionado.

Essa funcionalidade funciona de forma similar aos Middlewares do ASP.NET ou Pipeline Behaviors do NService Bus.

Nós vamos utilizar esse recurso com o intuito de validar a nossa Command antes que o Handler seja acionado.

A implementação acima, criamos um Behavior, onde iremos invocar de forma dinâmica a validação da nossa Command e notificar caso exista erros de validação.

Registrando dependências

Para que nosso código funciona como o esperado, precisamos realizar alguns ajustes na classe no método ConfigureServices na classe Startup do projeto ASP.NET Core.

Primeira coisa que precisamos alterar é o código da linha 3, onde adicionarmos uma extensão fornecida pelo Fluent Validation, para registrarmos todos os Validators que estão dentro de um Assembly.

Segundo ponto, foi o código adicionado na linha 11, onde adicionamos o Behavior criado para dentro do container de IoC.

Obtendo Notificações

Agora que temos tudo que precisamos implementado e configurado, vamos ver como podemos obter as notificações que foram geradas no momento da validação da nossa Command.

Note que no método CreateUserAsync, temos agora uma nova implementação, onde acessamos a classe que guarda as nossas notificações para obter as mensagens que foram geradas a partir da validação da Command.

Com isso agora conseguimos ter a as mensagens de validação sem ferir o conceito de que uma Command não deve ter retorno.

Considerações Finais

A implementação que utilizei no na Action do Controller para obter as mensagens de validação, foi com foco na simplicidade para mostrar como podemos obter as respostas de validação.

Entretanto se seguíssemos com essa abordagem adiante em um código produtivo, teríamos uma repetição do código em diversos lugares, o que seria um pouco ruim.

Uma solução elegante para isso seria criar um Filtro do ASP.NET para evitar a repetição do código acima.

Outro ponto que pudemos colocar em pauta é uma segunda estratégia para a validação das Commands.

Nós também podemos utilizar uma estratégia com Data Annotations em nossas Commands e seguir a abordagem que o Gustavo Fontes propôs em seu último artigo.

Conclusão

Espero que vocês tenham gostado do artigo e caso exista qualquer dúvida ou sugestão eu ficarei bem feliz em ouvir.

Todo o código fonte que utilizamos para realizar demonstração estará disponível em meu Github.

--

--

Nicolas Takashi
Nicolas Takashi

Written by Nicolas Takashi

I love to speak, teach, and write about distributed systems, cloud computing, architecture, systems engineering, and APIs.

Responses (1)