¿Deberían usarse los bloques catch para escribir la lógica, es decir, manejar el control de flujo, etc.? ¿O solo por lanzar excepciones? ¿Tiene efecto en la eficiencia o mantenibilidad del código?
¿Cuáles son los efectos secundarios (si los hay) de la lógica de escritura en el bloque catch?
EDITAR:
He visto una clase Java SDK en la que han escrito lógica dentro del bloque catch. Por ejemplo (fragmento tomado de la java.lang.Integer
clase):
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 :
Estaba pasando por un tutorial donde lo cuentan como una ventaja de escribir la lógica de casos excepcionales dentro de las excepciones:
Las excepciones le permiten escribir el flujo principal de su código y tratar los casos excepcionales en otros lugares.
¿Alguna pauta específica sobre cuándo escribir lógica en el bloque catch y cuándo no?
fuente
Respuestas:
El ejemplo que cita se debe al diseño deficiente de la API (no hay una forma limpia de verificar si un String es un número entero válido, excepto tratar de analizarlo y detectar la excepción).
A nivel técnico, lanzar e intentar / atrapar son construcciones de flujo de control que le permiten saltar la pila de llamadas, nada más y nada menos. Saltar la pila de llamadas conecta implícitamente el código que no está muy cerca en la fuente, lo que es malo para el mantenimiento . Por lo tanto, solo debe usarse cuando necesite hacer eso y las alternativas sean aún peores. El caso ampliamente aceptado donde las alternativas son peores es el manejo de errores (códigos de retorno especiales que deben verificarse y pasar manualmente cada nivel de la pila de llamadas).
Si tiene un caso en el que las alternativas son peores (y realmente las ha considerado cuidadosamente), entonces diría que usar tirar e intentar / atrapar para controlar el flujo está bien. El dogma no es un buen sustituto del juicio.
fuente
Esto es algo que tiende a depender del lenguaje y el paradigma.
La mayor parte de mi trabajo se realiza en Java (y a veces en C ++). La tendencia es utilizar excepciones solo para condiciones excepcionales. Hay algunas preguntas en Stack Overflow sobre la sobrecarga de rendimiento de las excepciones en Java , y como puede ver, no es exactamente insignificante. También hay otras preocupaciones, como la legibilidad y la facilidad de mantenimiento del código. Cuando se usa correctamente, las excepciones pueden delegar el manejo de errores a los componentes apropiados.
Sin embargo, en Python, reina la idea de que es más fácil pedir perdón que permiso. En la comunidad de Python, esto se conoce como EAFP , que contrasta con el enfoque "mirar antes de saltar" ( LBYL ) en lenguajes de estilo C.
fuente
Esa no es la mejor manera de pensar en bloques try / catch. La forma de pensar acerca de los bloques try / catch es la siguiente: ha ocurrido una falla, ¿cuál es el mejor lugar para lidiar con ESTA falla específica? Esa puede ser la siguiente línea de código, puede tener veinte niveles en la cadena de llamadas. Donde sea que esté, ahí es donde debería estar.
Lo que hace el bloque catch depende del error y de lo que puede hacer al respecto. A veces simplemente se puede ignorar (falla al eliminar un archivo de memoria virtual sin datos importantes), a veces se usará para establecer el valor de retorno de las funciones en verdadero o falso (método de análisis int de java), a veces saldrá del programa . Todo eso depende del error.
La parte importante a comprender es: catch block == Sé cómo lidiar con esto.
fuente
Los bloques de captura solo deben usarse para manejar excepciones, nada más y nunca para controlar el flujo. En cualquier situación en la que desee utilizar excepciones para administrar el flujo, será mejor que verifique las condiciones previas.
El flujo de manejo con excepciones es lento y semánticamente incorrecto.
fuente
Primero, olvide la noción de que "las excepciones deben usarse para condiciones excepcionales". También deje de preocuparse por la eficiencia, hasta que tenga un código que funcione de manera inaceptable y haya medido para saber dónde radica el problema.
El código es más fácil de entender cuando las acciones siguen en una secuencia simple, sin condicionales. Las excepciones mejoran la capacidad de mantenimiento al eliminar la comprobación de errores del flujo normal. No importa si la ejecución sigue el flujo normal el 99.9% del tiempo o el 50% del tiempo o el 20% del tiempo.
Lanza una excepción cuando una función no puede devolver un valor, cuando un procedimiento no puede completar la acción esperada o cuando un constructor no puede producir un objeto utilizable. Esto permite a los programadores suponer que una función siempre devuelve un resultado utilizable, un procedimiento siempre completa la acción solicitada, un objeto construido siempre está en un estado utilizable.
El mayor problema que veo con el código de manejo de excepciones es que los programadores escriben bloques try / catch cuando no deberían. Por ejemplo, en la mayoría de las aplicaciones web, si una solicitud de base de datos arroja una excepción, no se puede hacer nada en el controlador. Una cláusula genérica de captura en el nivel más alto es suficiente. Entonces el código del controlador puede ignorar felizmente la posibilidad de que el disco se haya bloqueado o que la base de datos esté fuera de línea o lo que sea.
fuente
Los bloques de captura no deben usarse para escribir lógica de código. Deben usarse solo para manejar errores. Un ejemplo es (1) limpiar los recursos asignados, (2) imprimir un mensaje útil y (3) salir con gracia.
Es cierto que las excepciones pueden ser objeto de abuso y causar
goto
efectos no deseados . Pero eso no los hace inútiles. Cuando se usan correctamente , pueden mejorar muchos aspectos de su código.fuente