Se um idioma suportar inerentemente exceções, é preferível lançar exceções e os clientes poderão capturar a exceção se não quiserem que ela resulte em falha. De fato, os clientes do seu código esperam exceções e se deparam com muitos bugs porque não verificarão os valores de retorno.
Existem algumas vantagens em usar exceções, se você tiver uma escolha.
Mensagens
Exceções contêm mensagens de erro legíveis pelo usuário que podem ser usadas pelos desenvolvedores para depuração ou mesmo exibidas aos usuários, se desejado. Se o código de consumo não puder manipular a exceção, ele poderá sempre registrá-lo para que os desenvolvedores possam percorrer os logs sem precisar parar em todos os outros rastreamentos para descobrir qual era o valor de retorno e mapeá-lo em uma tabela para descobrir qual era o valor. exceção real.
Com valores de retorno, não há informações adicionais que possam ser fornecidas com facilidade. Alguns idiomas suportam a realização de chamadas de método para obter a última mensagem de erro. Portanto, essa preocupação é um pouco menor, mas isso exige que o chamador faça chamadas extras e às vezes exigirá acesso a um 'objeto especial' que carrega essas informações.
No caso de mensagens de exceção, forneço o máximo de contexto possível, como:
Não foi possível recuperar uma política do nome "foo" para o usuário "bar", que foi referenciado no perfil do usuário.
Compare isso com um código de retorno -85. Qual você prefere?
Pilhas de chamadas
As exceções também costumam ter pilhas de chamadas detalhadas que ajudam a depurar o código cada vez mais rápido e também podem ser registradas pelo código de chamada, se desejado. Isso permite que os desenvolvedores identifiquem o problema normalmente na linha exata e, portanto, são muito poderosos. Mais uma vez, compare isso com um arquivo de log com valores de retorno (como -85, 101, 0 etc.), qual você prefere?
Falha na abordagem tendenciosa rápida
Se um método for chamado em algum lugar que falhar, lançará uma exceção. O código de chamada deve suprimir a exceção explicitamente ou ela falhará. Eu achei isso realmente incrível, porque durante o desenvolvimento e teste (e até na produção) o código falha rapidamente, forçando os desenvolvedores a corrigi-lo. No caso de valores de retorno, se uma verificação de um valor de retorno for perdida, o erro será ignorado silenciosamente e o erro aparecerá em algum lugar inesperado, geralmente com um custo muito maior para depuração e correção.
Quebrando e desembrulhando exceções
Exceções podem ser agrupadas dentro de outras exceções e depois desembrulhadas, se necessário. Por exemplo, seu código pode lançar o ArgumentNullException
que o código de chamada pode quebrar dentro de um UnableToRetrievePolicyException
porque essa operação falhou no código de chamada. Enquanto o usuário pode receber uma mensagem semelhante ao exemplo que forneci acima, algum código de diagnóstico pode desembrulhar a exceção e descobrir que ArgumentNullException
ele causou o problema, o que significa que é um erro de codificação no código do consumidor. Isso pode disparar um alerta para que o desenvolvedor possa corrigir o código. Esses cenários avançados não são fáceis de implementar com os valores de retorno.
Simplicidade do código
Este é um pouco mais difícil de explicar, mas aprendi com essa codificação tanto com valores de retorno quanto com exceções. O código que foi escrito usando valores de retorno normalmente fazia uma chamada e, em seguida, fazia uma série de verificações sobre qual era o valor de retorno. Em alguns casos, ele chamaria outro método e agora terá outra série de verificações para os valores de retorno desse método. Com exceções, o tratamento de exceções é muito mais simples na maioria, se não em todos os casos. Você tem um bloco try / catch / finalmente, com o tempo de execução tentando o melhor para executar o código nos blocos finalmente para limpeza. Até blocos try / catch / finalmente aninhados são relativamente mais fáceis de acompanhar e manter do que aninhados if / else e valores de retorno associados de vários métodos.
Conclusão
Se a plataforma que você está usando suporta exceções (especialmente Java ou .NET), você deve definitivamente assumir que não há outra maneira, exceto lançar exceções, porque essas plataformas têm diretrizes para lançar exceções e seus clientes esperam tão. Se eu estivesse usando sua biblioteca, não me preocuparei em verificar os valores de retorno, porque espero que exceções sejam lançadas, é assim que o mundo nessas plataformas é.
No entanto, se fosse C ++, seria um pouco mais desafiador determinar porque já existe uma grande base de código com códigos de retorno e um grande número de desenvolvedores é ajustado para retornar valores em vez de exceções (por exemplo, o Windows é repleto de HRESULTs) . Além disso, em muitos aplicativos, também pode ser um problema de desempenho (ou pelo menos percebido).
try
/catch
existe para. Além disso, você pode colocar sua pilhatry
/catch
muito mais longe em um local mais apropriado para manipulá-la (permitindo uma maior separação de preocupações).