MethodA chama um MethodB que por sua vez chama MethodC.
Não há manipulação de exceção no MethodB ou MethodC. Mas há manipulação de exceção no MethodA.
No MethodC, ocorre uma exceção.
Agora, essa exceção está ocorrendo no MethodA, que lida com isso adequadamente.
O que está errado com isto?
Na minha opinião, em algum momento um chamador executará MethodB ou MethodC, e quando ocorrerem exceções nesses métodos, o que será obtido com o tratamento de exceções nesses métodos, que basicamente é apenas um bloco try / catch / finalmente, em vez de apenas deixar eles borbulham até o chamado?
A declaração ou consenso sobre o tratamento de exceções é lançada quando a execução não pode continuar devido a isso - uma exceção. Entendi. Mas por que não capturar a exceção ainda mais na cadeia, em vez de ter blocos try / catch por todo o caminho.
Entendo quando você precisa liberar recursos. Essa é uma questão completamente diferente.
fonte
try-catch
bloco.Result<T>
tipo (um tipo que armazene um resultado de uma computação ou um erro) e retorne-o de suas funções de lançamento. Propagar um erro na pilha implicaria a leitura de todos os valores de retorno, verificando se é um erro e retornando um erro, se houver.Respostas:
Como princípio geral, não pegue exceções, a menos que você saiba o que fazer com elas. Se o MethodC lançar uma exceção, mas o MethodB não tiver uma maneira útil de lidar com isso, deverá permitir que a exceção se propague até o MethodA.
As únicas razões pelas quais um método deve ter um mecanismo de captura e religação são:
Caso contrário, capturar exceções no nível errado tende a resultar em código que falha silenciosamente, sem fornecer nenhum feedback útil ao código de chamada (e, finalmente, ao usuário do software). A alternativa de capturar uma exceção e, em seguida, relançar imediatamente, é inútil.
fonte
try ... finally ...
, então use-o, não pegue eLoadDataException
e inclua os detalhes da exceção original de acordo com os recursos do seu idioma, para que futuros mantenedores possam ver a causa raiz sem precisar anexar um depurador e descobrir como reproduzir o problema.Absolutamente nada.
"lida com isso adequadamente" é a parte importante. Esse é o cerne da manipulação de exceções estruturadas.
Se o seu código puder fazer algo "útil" com uma exceção, vá em frente. Se não, então deixe bem em paz.
É exatamente o que você deveria estar fazendo. Se você está lendo um código que possui manipuladores / repetidores "até o fim", provavelmente está lendo um código muito ruim.
Infelizmente, alguns desenvolvedores apenas veem os blocos catch como código "boiler-plate" que eles inserem (sem trocadilhos) em todos os métodos que escrevem, geralmente porque eles realmente não "recebem" o Exception Handling e pensam que precisam adicionar algo para que as exceções não "escapam" e matam seu programa.
Parte da dificuldade aqui é que, na maioria das vezes, esse problema nem é percebido, porque as exceções não são lançadas o tempo todo, mas, quando são , o programa vai desperdiçar muito tempo e gradualmente, desmarcando a pilha de chamadas para chegar a algum lugar que realmente faça algo útil com a exceção.
fonte
catch
no nível mais alto possível que registre o erro e retorne uma resposta de erro. Nãocatch
havia blocos espalhados por toda parte. Se você não deseja listar todas as exceções verificadas possíveis (em linguagens como Java), basta agrupá-las emRuntimeException
vez de registrá-las lá, tentar continuar e encontrar mais erros ou até vulnerabilidades.Você precisa fazer a diferença entre bibliotecas e aplicativos.
As bibliotecas podem lançar exceções não capturadas livremente
Quando você cria uma biblioteca, em algum momento você precisa pensar no que pode dar errado. Os parâmetros podem estar no intervalo errado ou
null
, recursos externos podem estar indisponíveis etc.Sua biblioteca geralmente não tem como lidar com eles de maneira sensata . A única solução sensata é lançar uma exceção apropriada e deixar que o desenvolvedor do aplicativo lide com ela.
Os aplicativos sempre devem, em algum momento, capturar exceções
Quando uma exceção é capturada, gosto de categorizá-las como erros ou erros fatais . Um erro regular significa que uma única operação no meu aplicativo falhou. Por exemplo, um documento aberto não pôde ser salvo, porque o destino não era gravável. O único pensamento sensato para o Aplicativo é informar ao usuário que a operação não pôde ser concluída com êxito, fornecer informações legíveis por humanos em relação ao problema e deixar o usuário decidir o que fazer em seguida.
Um erro fatal é um erro do qual a lógica principal do aplicativo não pode se recuperar. Por exemplo, se o driver do dispositivo gráfico travar em um videogame, o Aplicativo não poderá "graciosamente" informar o usuário. Nesse caso, um arquivo de log deve ser gravado e, se possível, o usuário deve ser informado de uma maneira ou de outra.
Mesmo em um caso tão grave, o Aplicativo deve lidar com essa exceção de maneira significativa. Isso pode incluir a gravação de um arquivo de log, o envio de um relatório de falha etc. Não há motivo para o aplicativo não responder à exceção de alguma forma.
fonte
HDDPluggedOutDuringWritingException
possa ser tratado e não seja fatal para o aplicativo. O programa pode decidir o que fazer com isso.O que há de errado com o padrão que você descreve é que o método A não tem como distinguir entre três cenários:
O método B falhou de maneira antecipada.
O método C falhou de maneira não prevista pelo método B, mas enquanto o método B estava executando uma operação que poderia ser abandonada com segurança.
O método C falhou de maneira não prevista pelo método B, mas enquanto o método B estava executando uma operação que colocava as coisas em um estado incoerente supostamente temporário, que B não conseguiu limpar devido à falha de C.
A única maneira de o método A conseguir distinguir esses cenários será se a exceção lançada de B incluir informações suficientes para esse fim ou se a pilha que se desenrola para o método B fizer com que o objeto seja deixado em um estado explicitamente inválido . Infelizmente, a maioria das estruturas de exceção torna os dois padrões desajeitados, forçando os programadores a tomar decisões de design "menos graves".
fonte