Os blocos catch devem ser usados para escrever lógica, por exemplo, controlar o controle de fluxo etc. Ou apenas por lançar exceções? Isso afeta a eficiência ou a manutenção do código?
Quais são os efeitos colaterais (se houver) da escrita lógica no bloco catch?
EDITAR:
Eu vi uma classe Java SDK na qual eles escreveram lógica dentro do bloco catch. Por exemplo (trecho retirado da java.lang.Integer
classe):
try {
result = Integer.valueOf(nm.substring(index), radix);
result = negative ? new Integer(-result.intValue()) : result;
} catch (NumberFormatException e) {
String constant = negative ? new String("-" + nm.substring(index))
: nm.substring(index);
result = Integer.valueOf(constant, radix);
}
EDIT2 :
Eu estava passando por um tutorial em que eles contam como uma vantagem de escrever a lógica de casos excepcionais dentro das exceções:
As exceções permitem que você escreva o fluxo principal do seu código e lide com casos excepcionais em outros lugares.
Alguma orientação específica quando escrever lógica no bloco catch e quando não?
java
programming-practices
exceptions
HashimR
fonte
fonte
Respostas:
O exemplo que você cita é devido ao mau design da API (não há uma maneira limpa de verificar se uma String é um número inteiro válido, exceto tentando analisá-la e capturar a exceção).
No nível técnico, throw e try / catch são construções de fluxo de controle que permitem aumentar a pilha de chamadas, nada mais e nada menos. O salto na pilha de chamadas conecta implicitamente o código que não está muito próximo na fonte, o que é ruim para a manutenção . Portanto, ele só deve ser usado quando você precisar fazer isso e as alternativas são ainda piores. O caso amplamente aceito em que as alternativas são piores é o tratamento de erros (códigos de retorno especiais que precisam ser verificados e transmitidos manualmente para cada nível da pilha de chamadas).
Se você tem um caso em que as alternativas são piores (e você realmente considerou todas elas com cuidado), então eu diria que usar o throw e try / catch para o fluxo de controle é bom. Dogma não é um bom substituto para o julgamento.
fonte
Isso é algo que tende a depender da linguagem e do paradigma.
A maior parte do meu trabalho é feita em Java (e às vezes em C ++). A tendência é usar exceções apenas para condições excepcionais. Há algumas perguntas no Stack Overflow sobre a sobrecarga de desempenho das exceções em Java e, como você pode ver, não é exatamente insignificante. Há também outras preocupações, como a legibilidade e a manutenção do código. Quando usadas corretamente, as exceções podem delegar a manipulação de erros nos componentes apropriados.
No entanto, em Python, a idéia de que é mais fácil pedir perdão do que a permissão reina. Na comunidade Python, isso é conhecido como EAFP , que é contrastado com a abordagem "olhar antes de pular" ( LBYL ) em linguagens no estilo C.
fonte
Essa não é a melhor maneira de pensar sobre blocos try / catch. A maneira de pensar sobre os blocos try / catch é: ocorreu uma falha, onde é o melhor lugar para lidar com ESTA falha específica. Essa pode ser a próxima linha de código, pode haver vinte níveis na cadeia de chamadas. Onde quer que seja, é onde deveria estar.
O que o bloco catch faz depende do erro e o que você pode fazer sobre isso. Às vezes, ele pode ser simplesmente ignorado (falha em excluir um arquivo de rascunho sem dados imortantes), outras vezes, é usado para definir um valor de retorno de funções como true ou false (método de análise int do java); às vezes, você sai do programa . Tudo isso depende do erro.
A parte importante a entender é: catch block == Eu sei como lidar com isso.
fonte
Os blocos de captura devem ser usados apenas para manipular exceções, nada mais e nunca para o controle de fluxo. Em qualquer situação em que você queira usar exceções para gerenciar o fluxo, é melhor verificar as pré-condições.
O tratamento do fluxo com exceções é lento e semanticamente incorreto.
fonte
Primeiro, esqueça a noção de que "as exceções devem ser usadas para condições excepcionais". Além disso, pare de se preocupar com a eficiência, até ter um código com desempenho inaceitável e medir para saber onde está o problema.
O código é mais fácil de entender quando as ações seguem em uma sequência simples, sem condicionais. As exceções aprimoram a capacidade de manutenção removendo a verificação de erros do fluxo normal. Não importa se a execução segue o fluxo normal 99,9% das vezes ou 50% das vezes ou 20% das vezes.
Lance uma exceção quando uma função não puder retornar um valor, quando um procedimento não puder concluir a ação esperada ou quando um construtor não puder produzir um objeto utilizável. Isso permite aos programadores assumir que uma função sempre retorna um resultado utilizável, um procedimento sempre conclui a ação solicitada, um objeto construído está sempre em um estado utilizável.
O maior problema que vejo no código de manipulação de exceções é que os programadores escrevem blocos try / catch quando não deveriam. Por exemplo, na maioria dos aplicativos da Web, se uma solicitação de banco de dados lança uma exceção, não há nada que possa ser feito no controlador. Uma cláusula de captura genérica no nível mais alto é suficiente. Em seguida, o código do controlador pode ignorar alegremente a possibilidade de o disco ter travado ou o banco de dados estar offline ou qualquer outra coisa.
fonte
Blocos de captura não devem ser usados para escrever lógica de código. Eles devem ser usados apenas para lidar com erros. Um exemplo é (1) limpar todos os recursos alocados, (2) imprimir uma mensagem útil e (3) sair normalmente.
É verdade que as exceções podem ser abusadas e causar
goto
efeitos indesejados . Mas isso não os torna inúteis. Quando usados corretamente , eles podem melhorar muitos aspectos do seu código.fonte