Design Pattern Operation Result em C#
Felipe Santos
Posted on June 18, 2024
O Operation Result Design Pattern é um ferramenta incrível para você ter nas bases do seu projeto. Isso ajuda a lidar de forma muito mais assertiva com os resultados de operações do seu sistema.
O que é o Operation Result Design Pattern
Para começar, o Operation Result Design Pattern é utilizado para encapsular o resultado de operações de forma que permite uma estrutura consistente de retornar tanto o sucesso quanto a falha de alguma operação.
Ele também é uma alternativa ao disparos de exceções, ao invés de lidar com as exceções, você trabalha com um resultado.
Alguns obejtivos ao utilizar o Operation Result
Ter um indicador de sucesso ou falha da operação;
Ter acesso ao motivo da falha se a operação tiver falhado ou o valor resultante da operação caso tenha sido sucedida.
Criação da classe Resultado
A classe Resultado em si encpasula o resultado de alguma operação. Ela pode incluir um valor de retorno quando a operação for bem sucedida ou os detalhes de erros em operações que falharam.
Em C# podemos escrever a classe Resultado da seguinte maneira, assim conseguimos usar o Resultado para tipos diferentes de valores
public class Resultado<Tipo>
{
public Resultado()
{
Erros = [];
}
public Resultado(params string[] erros)
{
Erros = erros.ToImmutableList();
}
public Tipo? Valor { get; init; }
public bool TemErros() => Erros.Count > 0;
public bool Sucesso => !TemErros();
public IReadOnlyCollection<string> Erros { get; init; }
}
Com essa pequena implementação você já tem disponível a lista de erros, caso a operação tenha falhado, armazenadas em um objeto ImmutableList, caso a operação tenha falhado, e consegue retornar como um IReadOnlyCollection. Além disso consegue saber se a operação foi sucedida ou não e no caso do sucesso, trabalhar em cima do valor resultante.
Lendo um pouco mais a classe, conseguimos entender que a criação do objeto com o construtor vazio representa uma operação de sucesso e quando tem itens no construtor significa que a operação falhou.
Adicionando a gravidade da mensagem!
Ao invés de retornar somente mensagens de erros quando houverem erros, você pode retornar mensagens e em cada mensagem disponibilizar um nível de gravidade, ou seja, a mensagem pode ser somente uma informação, quer seria o caso de sucesso, ou pior, ela pode ser um erro, que seria uma mensagem com maior gravidade.
Assim, podemos escrever uma nova classe para representar essas mensagens e um enum para representar os níveis
public class ResultadoMensagem
{
public ResultadoMensagem(string menssagem, MensagemGravidade gravidade)
{
Mensagem = menssagem?? throw new ArgumentNullException(nameof(menssagem));
Gravidade = gravidade;
}
public string Mensagem { get; }
public MensagemGravidade Gravidade{ get; }
}
public enum MensagemGravidade
{
Informacao = 0,
Aviso = 1,
Erro = 2,
}
Por fim vamos adaptar a classe de resultado ao novo padrão utilizando as mensagens com gravidade!
public class Resultado<Tipo>
{
public Resultado()
{
Mensagens = [];
}
public Resultado(params ResultadoMensagem[] mensagens)
{
Mensagens = [.. mensagens];
}
public Tipo? Valor { get; init; }
public bool TemErros() => Mensagens.Count > 0;
public bool Sucesso => !TemErros();
public IReadOnlyCollection<ResultadoMensagem> Mensagens { get; init; }
public IEnumerable<ResultadoMensagem> ProcurarErros()
=> Mensagens.Where(mensagem => mensagem.Gravidade == MensagemGravidade.Erro);
}
Espero que eu tenha ajudado de alguma forma, pode deixar um comentário caso tenha alguma dúvida sobre esse design pattern!
Posted on June 18, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.