Na minha opinião, as exceções são uma ferramenta essencial para detectar erros de código em tempo de execução. Tanto em testes quanto em produção. Torne suas mensagens detalhadas o suficiente para que, em combinação com um rastreamento de pilha, você possa descobrir o que aconteceu em um log.
As exceções são principalmente uma ferramenta de desenvolvimento e uma maneira de obter relatórios razoáveis de erros da produção em casos inesperados.
Além da separação de preocupações (caminho feliz com apenas erros esperados vs. falhas até chegar a um manipulador genérico para erros inesperados), é uma coisa boa, tornando seu código mais legível e sustentável, é impossível preparar seu código para todos os possíveis casos inesperados, mesmo inchando-o com o código de tratamento de erros para concluir a ilegibilidade.
Esse é realmente o significado de "inesperado".
Aliás, o que é esperado e o que não é uma decisão que só pode ser tomada no local da chamada. É por isso que as exceções verificadas em Java não deram certo - a decisão é tomada no momento do desenvolvimento de uma API, quando não está claro o que é esperado ou inesperado.
Exemplo simples: a API de um mapa de hash pode ter dois métodos:
Value get(Key)
e
Option<Value> getOption(key)
o primeiro lançando uma exceção, se não encontrado, o último fornecendo um valor opcional. Em alguns casos, o último faz mais sentido, mas em outros, seu código simplesmente deve esperar que exista um valor para uma determinada chave; portanto, se não houver uma, é um erro que esse código não pode corrigir porque um código básico suposição falhou. Nesse caso, é realmente o comportamento desejado cair fora do caminho do código e cair em algum manipulador genérico, caso a chamada falhe.
O código nunca deve tentar lidar com suposições básicas com falha.
Exceto verificando-os e lançando exceções bem legíveis, é claro.
Lançar exceções não é mau, mas capturá-las pode ser. Não tente corrigir erros inesperados. Capture exceções em alguns lugares em que deseja continuar com algum loop ou operação, registre-as, talvez relate um erro desconhecido, e é isso.
Blocos de captura em todo o lugar são uma péssima idéia.
Crie suas APIs de maneira a facilitar a expressão de sua intenção, ou seja, declarando se você espera um determinado caso, como chave não encontrada ou não. Os usuários da sua API podem escolher a chamada de lançamento apenas para casos realmente inesperados.
Eu acho que o motivo pelo qual as pessoas se ressentem de exceções e vão longe demais ao omitir essa ferramenta crucial para automação do tratamento de erros e melhor separação de preocupações de novos idiomas são experiências ruins.
Isso e alguns mal-entendidos sobre o que eles realmente são bons.
Simulá-los, fazendo TUDO através de ligação monádica torna seu código menos legível e de fácil manutenção, e você acaba sem um rastreamento de pilha, o que torna essa abordagem MUITO pior.
O tratamento de erros de estilo funcional é excelente para os casos de erro esperados.
Deixe o tratamento de exceções cuidar automaticamente de todo o resto, é para isso que serve :)
panic
que não é exatamente o mesmo. Além do que é dito lá, uma exceção não é muito mais do que uma maneira sofisticada (mas confortável) de executar umaGOTO
, embora ninguém chame dessa maneira, por razões óbvias.