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!
Top comments (0)