Exceptions são muito intrusivas

No post anterior, compartilhei um exemplo de como containers podem nos ajudar a deixar o código mais claro sobre os resultados de um método.

public interface IEmployeeRepository
{
  Option<Employee> GeyById(string id);
}
 
class EmployeeRepository : IEmployeeRepository
{
  public Option<Employee> GeyById(string id)
    =>; new DbContext().Find(id);
}

E o que temos sobre Exceptions?! O método GetById irá lançar uma exception se alguma coisa der errado (se não for possível conectar com o banco, por exemplo), mas não há nada sobre isso na assinatura do método.

Either

Uma abordagem superior seria:

public interface IEmployeeRepository
{
    Either<Exception, Option<Employee>> GeyById(string id);
}

class EmployeeRepository : IEmployeeRepository
{
    public Either<Exception, Option<Employee>> GeyById(string id)
    {
        try
        {
            return new DbContext().Find(id);
        }
        catch (Exception e)
        {
            return e;
        }
    }
}

O tipo Either é apenas uma struct comum com conversões implícitas e algumas operações funcionais. Ele permite diferentes tipos de retorno. Neste exemplo, estamos usando o container para tornar explícito que o método pode resultar tanto uma instância de Employee quanto uma exceção.

Try

Eu amo o Either, mas ele não é bom o suficiente! Eu tenho trabalhando bastante para tornar o meu código ainda mais claro.

public interface IEmployeeRepository
{
    Try<Exception, Option<Employee>> GeyById(string id);
}

class EmployeeRepository : IEmployeeRepository
{
    public Try<Exception, Option<Employee>> GeyById(string id)
        => Try.Run(return new DbContext().Find(id));
}

O tipo Try, assim como Either, é uma struct que provê conversões implícitas e algumas operações muito básicas. Ela permite que diferentes tipos de retorno para falha e para sucesso.

A coisa mais interessante sobre esta abordagem é que os programadores que consomem EmployeeRepository são agora forçados a tratar exceções.

public IActionResult Get(string id) => _repository.GetById(id).Match<IActionResult>(
  failure: _ => DatabaseError(),
  success: e => e .Match<IActionResult>(
    some: employee => Ok(employee),
    none: () => NotFound()
  ));

Implementações de Either e Try estão disponíveis no meu github.

Compartilhe este insight:

Elemar Júnior

Sou fundador e CEO da EximiaCo e atuo como tech trusted advisor ajudando diversas empresas a gerar mais resultados através da tecnologia.

Elemar Júnior

Sou fundador e CEO da EximiaCo e atuo como tech trusted advisor ajudando diversas empresas a gerar mais resultados através da tecnologia.

Mais insights para o seu negócio

Veja mais alguns estudos e reflexões que podem gerar alguns insights para o seu negócio:

Decidi aprender a programar com R. Aqui está algo que escrevi. ## defining a function makeCacheMatrix <- function(x = matrix())...
I’ve been spending some time learning from the “Designing Data-Intensive Applications” book. I am reading it for the third time,...
Um dos princípios que mais valorizo em práticas ágeis é o feedback. De todos os tipos de feedback que já...
Empresas, famílias e grupos de amigos mudam. Entretanto, uma coisa permanece constante: o fato de que todos percebemos a vida...
Este post foi originalmente publicado em 2015 (infelizmente, a postagem original não está mais disponível) Nesse post vamos implementar, passo-a-passo,...
Geralmente, quanto maior é uma organização, menos relevante é a qualidade das ideias ou das iniciativas. Nelas, o fundamental para...

Crie sua conta

Preencha os dados para iniciar o seu cadastro no plano anual do Clube de Estudos:

Crie sua conta

Preencha os dados para iniciar o seu cadastro no plano mensal do Clube de Estudos:

× Precisa de ajuda?