Use exceções para coisas excepcionais, coisas que você não pode esperar razoavelmente encontrar com muita frequência, coisas que indicam que algo dá errado. Por exemplo, se a rede estiver inoperante, é algo excepcional para um servidor da web. Se o banco de dados não estiver disponível, isso significa que algo está errado. Se o arquivo de configuração estiver ausente, provavelmente significa que o usuário fez uma bagunça.
Não use exceções para manipular código incorreto. Para verificar a correção do código, você deve usar as asserções ou, no .NET Framework 4 e posterior, os contratos de código (que substituem as asserções e possuem recursos adicionais, particularmente valiosos).
Não use exceções em casos não excepcionais. O fato de o usuário, quando solicitado a inserir um número, inserir "cão" não é tão excepcional para merecer uma exceção.
Tenha cuidado ao escolher os tipos de exceções. Crie seus próprios tipos quando necessário. Escolha cuidadosamente a herança, tendo em mente que a captura dos pais também pegará os filhos. Nunca throw Exception
.
Não use códigos de retorno para erros. Os códigos de erro são facilmente mascarados, ignorados, esquecidos. Se houver um erro, manipule-o ou propague-o para a pilha superior.
Nos casos em que se espera que um método retorne um erro e o erro não seja excepcional, use enumerações, nunca números de erro. Exemplo:
// Note that the operation fails pretty often, since it deals with the servers which are
// frequently unavailable, and the ones which send garbage instead of the actual data.
private LoadOperationResult LoadProductsFromWeb()
{
...
}
O significado de LoadOperationResult.ServerUnavailable
, LoadOperationResult.ParsingError
etc. é muito mais explícito do que, digamos, lembrar que o código 12 significa que o servidor está inoperante e o código 13 - que os dados não podem ser analisados.
Use códigos de erro quando eles se referirem aos comuns, conhecidos por todos os desenvolvedores que trabalham no domínio específico. Por exemplo, não reinvente um valor de enumeração para HTTP 404 não encontrado ou Erro interno do servidor HTTP 500.
Cuidado com os booleanos. Mais cedo ou mais tarde, você desejará saber não apenas se um método específico foi bem-sucedido ou falhou, mas por quê. Exceções e enumerações são muito mais poderosas para isso.
Não pegue todas as exceções (a menos que você esteja no topo da pilha). Se você pegar uma exceção, deve estar pronto para lidar com isso. Capturar tudo está mostrando que você não se importa se o seu código é executado corretamente. Isso pode resolver o "Não quero pesquisar agora como corrigir isso", mas machucará você mais cedo ou mais tarde.
Em C #, nunca repita exceções como esta:
catch (SomeException ex)
{
...
throw ex;
}
porque você está quebrando a pilha. Faça isso:
catch (SomeException)
{
...
throw;
}
Faça um esforço ao escrever mensagens de exceção. Quantas vezes eu vi algo parecido throw Exception("wrong data")
ou throw Exception("shouldn't call this method in this context")
. Outros desenvolvedores, inclusive você seis meses depois, não teriam idéia de quais dados estão errados e por que ou por que não deveríamos chamar algum método em um contexto, nem qual contexto com precisão.
Não mostre mensagens de exceção para o usuário. Eles não são esperados para pessoas comuns e geralmente são ilegíveis para os próprios desenvolvedores.
Não localize mensagens de exceção. Pesquisando na documentação por uma mensagem localizada é exaustivo e inútil: todas as mensagens devem estar apenas em inglês e em inglês.
Não se concentre exclusivamente em exceções e erros: os logs também são extremamente importantes.
No .NET, não esqueça de incluir exceções na documentação XML do método:
/// <exception cref="MyException">Description of the exception</exception>
A inclusão de exceções na documentação XML facilita muito as coisas para a pessoa que está usando a biblioteca. Não há nada mais irritante do que tentar adivinhar qual exceção poderia ser lançada por um método e por quê.
Nesse sentido¹, o tratamento de exceções Java fornece uma abordagem melhor e mais rígida. Obriga você a lidar com exceções potencialmente lançadas pelos métodos chamados ou declarar em seu próprio método que pode lançar as exceções que você não lida, tornando as coisas particularmente transparentes.