Uma exceção é um erro de bloqueio .
Antes de tudo, a melhor prática deve ser não lançar exceções para qualquer tipo de erro, a menos que seja um erro de bloqueio .
Se o erro estiver bloqueando , lance a exceção. Uma vez que a exceção já foi lançada, não há necessidade de ocultá-la porque é excepcional; informe o usuário sobre isso (você deve reformatar toda a exceção para algo útil para o usuário na interface do usuário).
Seu trabalho como desenvolvedor de software é tentar evitar um caso excepcional em que algum parâmetro ou situação de tempo de execução possa terminar em uma exceção. Ou seja, as exceções não devem ser silenciadas, mas devem ser evitadas .
Por exemplo, se você souber que alguma entrada inteira pode vir com um formato inválido, use em int.TryParse
vez deint.Parse
. Existem muitos casos em que você pode fazer isso em vez de apenas dizer "se falhar, basta lançar uma exceção".
Lançar exceções é caro.
Se, afinal, uma exceção é lançada, em vez de gravar a exceção no log depois que ela é lançada, uma das práticas recomendadas é capturá-la em um manipulador de exceção de primeira chance . Por exemplo:
- ASP.net: Global.asax Application_Error
- Outros: evento AppDomain.FirstChanceException .
Minha opinião é que as tentativas / capturas locais são mais adequadas para lidar com casos especiais em que você pode converter uma exceção em outra, ou quando você deseja "silenciá-la" para um caso muito, muito, muito, muito, muito especial (um bug na biblioteca lançando uma exceção não relacionada que você precisa silenciar para solucionar o bug inteiro).
Para o restante dos casos:
- Tente evitar exceções.
- Se isso não for possível: manipuladores de exceção de primeira chance.
- Ou use um aspecto PostSharp (AOP).
Respondendo a @thewhiteambit em algum comentário ...
@thewhiteambit disse:
Exceções não são erros fatais, são exceções! Às vezes, eles nem são erros, mas considerá-los erros fatais é uma compreensão completamente falsa do que são exceções.
Primeiro de tudo, como uma exceção não pode ser um erro?
- Sem conexão com o banco de dados => exceção.
- Formato de sequência inválido para analisar algum tipo => exceção
- Tentando analisar JSON e enquanto a entrada não é realmente JSON => exceção
- Argumento
null
enquanto o objeto era esperado => exceção
- Alguma biblioteca possui um bug => lança uma exceção inesperada
- Há uma conexão de soquete e ela é desconectada. Então você tenta enviar uma mensagem => exceção
- ...
Podemos listar 1k casos de quando uma exceção é lançada e, afinal, qualquer um dos casos possíveis será um erro .
Uma exceção é um erro, porque no final do dia é um objeto que coleta informações de diagnóstico - possui uma mensagem e acontece quando algo dá errado.
Ninguém lançaria uma exceção quando não houvesse um caso excepcional. As exceções devem bloquear os erros porque, uma vez lançadas, se você não tentar usar o try / catch e as exceções para implementar o fluxo de controle , significa que seu aplicativo / serviço interromperá a operação que entrou em um caso excepcional .
Além disso, sugiro a todos que verifiquem o paradigma à prova de falhas publicado por Martin Fowler (e escrito por Jim Shore) . Foi assim que eu sempre entendi como lidar com exceções, mesmo antes de chegar a este documento há algum tempo.
[...] considerá-los Erros fatais é uma compreensão completamente falsa do que são exceções.
Geralmente, as exceções cortam algum fluxo de operação e são tratadas para convertê-las em erros compreensíveis pelo homem. Portanto, parece que uma exceção é realmente um paradigma melhor para lidar com casos de erro e trabalhar com eles para evitar uma falha completa do aplicativo / serviço e notificar o usuário / consumidor de que algo deu errado.
Mais respostas sobre preocupações de @whiteambit
Por exemplo, no caso de falta de uma conexão com o banco de dados, o programa pode excepcionalmente continuar gravando em um arquivo local e enviar as alterações ao banco de dados assim que estiver disponível novamente. Sua conversão inválida de String para número pode ser analisada novamente com a interpretação de idioma local em Exception, como quando você tenta o idioma inglês padrão para o Parse ("1,5") falhar e tenta novamente com a interpretação em alemão, que é completamente bom porque usamos vírgula em vez de apontar como separador. Você vê que essas exceções não devem nem estar bloqueando, elas precisam apenas de um tratamento de exceção.
Se seu aplicativo funcionar offline sem persistir os dados no banco de dados, você não deve usar exceções , pois a implementação do fluxo de controle try/catch
é considerada um antipadrão. O trabalho offline é um possível caso de uso; portanto, você implementa o fluxo de controle para verificar se o banco de dados está acessível ou não, não espere até que ele esteja inacessível .
A análise também é um caso esperado ( não EXCEPCIONAL CASE ). Se você espera isso, não usa exceções para controlar o fluxo! . Você obtém alguns metadados do usuário para saber qual é sua cultura e usa formatadores para isso! O .NET também oferece suporte a esse e outros ambientes, e uma exceção, porque a formatação de números deve ser evitada se você espera um uso específico de cultura do seu aplicativo / serviço .
Uma exceção não tratada geralmente se torna um erro, mas as exceções em si não são codeproject.com/Articles/15921/Not-All-Exceptions-Are-Errors
Este artigo é apenas uma opinião ou um ponto de vista do autor.
Como a Wikipedia também pode ser apenas a opinião do (s) autor (es) do artigo, não diria que é o dogma , mas verifique o que o artigo Coding by exception diz em algum lugar de algum parágrafo:
[...] O uso dessas exceções para lidar com erros específicos que surgem para continuar o programa é chamado de codificação por exceção. Esse antipadrão pode degradar rapidamente o software em desempenho e manutenção.
Também diz em algum lugar:
Uso de exceção incorreto
Geralmente, a codificação por exceção pode levar a outros problemas no software com o uso incorreto de exceções. Além de usar o tratamento de exceções para um problema único, o uso incorreto de exceções leva isso adiante, executando o código mesmo depois que a exceção é gerada. Esse método de programação ruim se assemelha ao método goto em muitas linguagens de software, mas ocorre apenas após a detecção de um problema no software.
Honestamente, acredito que o software não pode ser desenvolvido, não levando os casos de uso a sério. Se você sabe disso ...
- Seu banco de dados pode ficar offline ...
- Algum arquivo pode ser bloqueado ...
- Algumas formatações podem não ser suportadas ...
- Alguma validação de domínio pode falhar ...
- Seu aplicativo deve funcionar no modo offline ...
- qualquer que seja o caso de uso ...
... você não usará exceções para isso . Você apoiaria esses casos de uso usando o fluxo de controle regular.
E se algum caso de uso inesperado não for abordado, seu código falhará rapidamente, porque lançará uma exceção . Certo, porque uma exceção é um caso excepcional .
Por outro lado, e finalmente, às vezes você cobre casos excepcionais que lançam exceções esperadas , mas não os lança para implementar o fluxo de controle. Você faz isso porque deseja notificar as camadas superiores que não oferece suporte a algum caso de uso ou que seu código não funciona com alguns argumentos ou dados / propriedades do ambiente.