.NET - O padrão ServiceResult
Hoje veremos o padrão ServiceResult, o que é e para que serve. |
Este padrão fornece uma maneira padronizada para encapsular o resultado de uma chamada de serviço sendo útil para serviços que podem retornar valores, erros ou ambos.
O padrão ServiceResult é composto por duas classes:
Vejamos como implementar este padrão usando o seguinte código :
public
struct
ServiceResult<T> { public T? Data { get; } public Exception? Error { get; } public bool IsSuccess => Error == null; public ServiceResult(T data) { Data = data; Error = null; } public ServiceResult(Exception error) { Data = default; Error = error; } // operador Implicito para os dados public static implicit operator ServiceResult<T>(T data) => new ServiceResult<T>(data); // operador implicito para exceção public static implicit operator ServiceResult<T>(Exception ex) => new ServiceResult<T>(ex); } |
Neste código
temos:
- Os dados contêm o resultado da operação.
- O erro contém qualquer exceção que possa ter ocorrido.
- IsSuccess é uma propriedade que indica se a operação foi
bem-sucedida (ou seja, sem exceções).
Ao usar o operador implícito, tornamos o código
UserService mais limpo e intuitivo. Em vez de criar explicitamente um
novo ServiceResult<User> com dados ou uma exceção,
simplesmente retornamos os dados ou a exceção diretamente, e a conversão
implícita cuida do resto.
Nota: Embora o operador implícito possa tornar o código mais limpo, é
essencial usá-lo criteriosamente. Usá-lo excessivamente ou de maneiras não
intuitivas pode tornar o código mais difícil de entender para outros
desenvolvedores. Sempre busque clareza e legibilidade.
Exemplo:
public class UserService
{
public ServiceResult<User> GetUserById(int userId)
{
try
{
// Logica para retornar o usuário do banco de dados
User user = UserRepository.GetUserById(userId);
if (user != null)
{
// Retorna o user como resultado
return ServiceResult<User>.Success(user);
}
else
{
// retorna o erro notfound como resultado
return ServiceResult<User>.Error("User not found");
}
}
catch (Exception ex)
{
// retorna a exceção como resultado
return ServiceResult<User>.Exception(ex);
}
}
}
|
Neste exemplo, a
classe UserService possui um método GetUserById que
recupera um usuário do banco de dados com base no userId fornecido. O método
retorna um objeto ServiceResult<User>.
A classe ServiceResult<T> é uma classe genérica que
encapsula o resultado da operação. Possui métodos de fábrica estáticos
Success, Error e Exception para criar instâncias de
ServiceResult<T> com resultados diferentes.
Ao usar o padrão ServiceResult, o chamador do método GetUserById pode manipular facilmente os diferentes resultados da operação. Por exemplo:
UserService userService = new UserService();
ServiceResult<User> result = userService.GetUserById(123);
if (result.Success)
{
User user = result.Data;
// Processa o objeto user
}
else if (result.Error)
{
string errorMessage = result.ErrorMessage;
// Trata o erro
}
else if (result.Exception)
{
Exception exception = result.Exception;
// Trata a exceção
}
|
Ao encapsular o resultado e possíveis erros ou exceções de maneira padronizada, o padrão ServiceResult melhora a legibilidade e a manutenção do código, facilitando o tratamento de diferentes resultados e erros em métodos de serviço.
Por que usar o padrão de resultado de serviço ?
Este padrão fornece uma maneira robusta e clara de lidar com os resultados da operação, facilitando a escrita e a manutenção do código pelos desenvolvedores e a compreensão dos resultados de suas chamadas pelos consumidores.
Pode
ser usado para melhorar a legibilidade e manutenibilidade do código, facilitando
a compreensão do resultado de uma chamada de serviço. Ele também pode ajudar a
evitar erros de programação, garantindo que os erros sejam tratados
adequadamente.
Essa abordagem pode ser particularmente benéfica em cenários como a construção
de APIs, onde você deseja fornecer feedback claro ao cliente sobre o resultado
de sua solicitação, sejam dados ou um erro detalhado.
E estamos conversados...
"Porque Deus enviou o seu Filho ao mundo, não para que
condenasse o mundo, mas para que o mundo fosse salvo por ele."
João 3:17
Referências:
C# - Tasks x Threads. Qual a diferença
DateTime - Macoratti.net
Null o que é isso ? - Macoratti.net
Formatação de data e hora para uma cultura ...
C# - Calculando a diferença entre duas datas
NET - Padrão de Projeto - Null Object Pattern
C# - Fundamentos : Definindo DateTime como Null ...
C# - Os tipos Nullable (Tipos Anuláveis)