Não acredito que as capturas locais sejam um antipadrão, na verdade, se bem me lembro, ele é realmente aplicado em Java!
O que é essencial para mim ao implementar o tratamento de erros é a estratégia geral. Você pode querer um filtro que capte todas as exceções no limite do serviço, interceptá-las manualmente - ambas são boas, desde que exista uma estratégia geral que se enquadre nos padrões de codificação de suas equipes.
Pessoalmente, gosto de detectar erros em uma função quando posso executar um dos seguintes procedimentos:
- Adicione informações contextuais (como o estado dos objetos ou o que estava acontecendo)
- Manipule a exceção com segurança (como um método TryX)
- Seu sistema está ultrapassando um limite de serviço e chamando para uma biblioteca ou API externa
- Você deseja capturar e relançar um tipo diferente de exceção (talvez com o original como uma exceção interna)
- A exceção foi lançada como parte de alguma funcionalidade de fundo de baixo valor
Se não for um desses casos, não adiciono uma tentativa / captura local. Se for, dependendo do cenário, eu posso lidar com a exceção (por exemplo, um método TryX que retorna um false) ou repetir novamente, para que a exceção seja tratada pela estratégia global.
Por exemplo:
public bool TryConnectToDatabase()
{
try
{
this.ConnectToDatabase(_databaseType); // this method will throw if it fails to connect
return true;
}
catch(Exception ex)
{
this.Logger.Error(ex, "There was an error connecting to the database, the databaseType was {0}", _databaseType);
return false;
}
}
Ou um exemplo de repetição:
public IDbConnection ConnectToDatabase()
{
try
{
// connect to the database and return the connection, will throw if the connection cannot be made
}
catch(Exception ex)
{
this.Logger.Error(ex, "There was an error connecting to the database, the databaseType was {0}", _databaseType);
throw;
}
}
Então você captura o erro no topo da pilha e apresenta uma boa mensagem amigável para o usuário.
Seja qual for a abordagem adotada, sempre vale a pena criar testes de unidade para esses cenários, para garantir que a funcionalidade não mude e interrompa o fluxo do projeto posteriormente.
Você não mencionou em qual idioma está trabalhando, mas como desenvolvedor do .NET e já viu isso muitas vezes para não mencionar.
NÃO ESCREVA:
catch(Exception ex)
{
throw ex;
}
Usar:
catch(Exception ex)
{
throw;
}
O primeiro redefine o rastreamento de pilha e torna seu nível superior capturado totalmente inútil!
TLDR
Capturar localmente não é um antipadrão, geralmente pode fazer parte de um design e pode ajudar a adicionar contexto adicional ao erro.