¿Por qué la Captura (Excepción) casi siempre es una Idea mala?

¿Por qué la catch(Exception) casi siempre es una Idea mala?

Porque cuando atrapas una excepción se supone que debes manejarla correctamente . Y no puede esperar manejar todo tipo de excepciones en su código. Además, cuando detecta todas las excepciones, puede obtener una excepción que no puede tratar y evitar que el código que está en la parte superior de la stack lo maneje correctamente.

El principal general es captar el tipo más específico que puedas.

Cuento corto: se llama enmascaramiento de errores. Si tienes un código que no funciona bien y lanzas excepciones (o pasas una entrada mal formada a ese fragmento de código) y simplemente te ciegas mirando todas las excepciones posibles, nunca descubrirás el error y lo arreglarás.

Solo debe detectar excepciones si puede manejarlas adecuadamente. Como no puedes manejar todas las excepciones posibles, no debes atraparlas 🙂

Porque realmente no sabe por qué ocurrió una excepción, y varias excepciones exigen que el automóvil muy especial se maneje correctamente (si es posible), como por ejemplo OutOfMemoryException y excepciones de sistema de bajo nivel similares.

Por lo tanto, solo debes detectar excepciones:

  • que sabes exactamente cómo manejarlo (por ejemplo, FileNotFoundException o algo así)
  • cuando los volverá a plantear después (por ejemplo, para realizar una limpieza posterior a la falla)
  • cuando necesita transportar la excepción a otro hilo

Depende de lo que necesites Si necesita manejar diferentes tipos de excepciones de diferentes maneras, entonces debe usar múltiples bloques catch y atrapar tantas excepciones específicas como pueda.

Pero a veces puede necesitar manejar todas las excepciones de la misma manera. En tales casos, catch (Exception) puede estar bien. Por ejemplo:

  try { DoSomething(); } catch (Exception e) { LogError(e); ShowErrorMessage(e); // Show "unexpected error ocurred" error message for user. } 

Esto puede ser específico de Java:

En ocasiones, deberá llamar a métodos que arrojen excepciones controladas. Si esto está en su capa EJB / lógica de negocios, tiene 2 opciones: tomarlas o volver a lanzarlas.

La captura de clases de excepciones específicas significa que tendrá que volver a analizar sus acciones para las cuales se pueden lanzar excepciones cuando observe cómo este código maneja las excepciones. A menudo te meterás en una situación de “y si …” y puede que te cueste un montón de esfuerzo si las excepciones se manejan correctamente.

Volver a lanzar significa que el código que llama a los EJB estará plagado de código de captura que normalmente no significará nada para la clase llamante. nb arrojar excepciones comprobadas de los métodos EJB significará que usted es responsable de anular manualmente cualquier transacción.

Además de lo que todavía respondió @anthares:

Porque cuando atrapas una excepción se supone que debes manejarla correctamente . Y no puede esperar manejar todo tipo de excepciones en su código. Además, cuando detecta todas las excepciones, puede obtener una excepción que no puede tratar y evitar que el código que está en la parte superior de la stack lo maneje correctamente.

El principal general es captar el tipo más específico que puedas.

catch(Exception) es una mala práctica porque también atrapa todas las RuntimeException (excepción no verificada).

¡Pero a veces está bien! Por ejemplo, si tienes un código que hace algo ‘extra’, que realmente no te importa, y no quieres que explote tu aplicación. Por ejemplo, trabajé recientemente en una gran aplicación en la que nuestros socios comerciales querían que una determinada transacción diaria se resumiera en un nuevo archivo de registro. Explicaron que el registro no era tan importante para ellos, y que no calificaba como un requisito. Era algo extra que les ayudaría a entender los datos que se procesaban. No lo necesitaban, porque podían obtener la información en otro lugar. Así que ese es un caso raro en el que está perfectamente bien atrapar y tragar excepciones.

También trabajé en una empresa donde todos los Throwables fueron capturados, y luego vueltos a montar dentro de una RuntimeException personalizada. No recomendaría este enfoque, solo señalaría que ya está hecho.

Encuentro dos usos aceptables de captura (Excepción): – En el nivel superior de la aplicación (justo antes de regresar al usuario). De esa manera puede proporcionar un mensaje adecuado. – Utilizándolo para enmascarar las excepciones de bajo nivel a las de negocios.

El primer caso es autoexplicativo, pero déjame desarrollar el segundo:

Obra:

 try { xxxx } catch(Exception e) { logger.error("Error XXX",e) } 

es un enmascaramiento de errores como dijo @dimitarvp.

Pero

 try { xxxx } catch(Exception e) { throw new BussinessException("Error doing operation XXX",e) } 

Es una cosa diferente. De esta forma, no ignorarás los errores y te esconderás debajo de la alfombra. Está proporcionando una excepción de alto nivel con un mensaje más explicativo para capas de aplicaciones más altas.

Siempre es importante que dos administren la excepción en su capa correcta. Si deja escalar una excepción de bajo nivel a una capa empresarial alta, es prácticamente imposible que la capa superior pueda administrarla bien. En esos casos, prefiero enmascarar las excepciones de niveles bajos con una de negocios que proporciona un mejor contexto y mensaje y que también tiene la excepción original para poder ir a los detalles.

Aun así, si puede detectar excepciones más concretas y puede proporcionar un mejor tratamiento para ellas, debe hacerlo.

Si en un bloque de código puede obtener una SQLException y una NetworkException, debe atraparlas y proporcionar los mensajes y el tratamiento adecuados para cada una de ellas. Pero si al final del bloque try / catch tienes un mapeo de excepción con una BussinessException, está bien para mí. De hecho, considero adecuado que las capas de servicio superiores solo arrojen excepciones comerciales (con detalles dentro).

¿No es otro escenario válido para garantizar que un hilo se mantenga vivo atrapando la excepción dentro de él?

 Thread shouldRunWhenApplicationRuns = new Thread() { @Override public void run() { try { // do something that should never end } catch (Exception ex) { // log it } }; shouldRunWhenApplicationRuns.start();