exception - móviles - manual de programacion android pdf
¿Realmente es tan malo atrapar una excepción general? (13)
¡Sí! (excepto en la "parte superior" de su aplicación)
Al atrapar una excepción y permitir que la ejecución del código continúe, usted está afirmando que sabe cómo lidiar y eludir, o solucionar un problema en particular. Usted declara que esta es una situación recuperable . Catching Exception o SystemException significa que detectará problemas como errores IO, errores de red, errores de falta de memoria, errores de código faltante, desreferenciación de punteros nulos y "me gusta". Es una mentira decir que puedes lidiar con esto.
En una aplicación bien organizada, estos problemas irrecuperables deberían manejarse en la parte superior de la pila.
Además, a medida que evoluciona el código, no desea que su función capte una nueva excepción que se agrega en el futuro a un método llamado.
Mientras analizaba algún código heredado con FXCop, se me ocurrió que realmente es tan malo detectar un error de excepción general dentro de un bloque de prueba o si está buscando una excepción específica. Pensamientos en una postal por favor.
A menos que esté haciendo algún tipo de logging y código de limpieza en el frente de su aplicación, entonces creo que es malo capturar todas las excepciones.
Mi regla básica es detectar todas las excepciones que esperas y cualquier otra cosa es un error.
Si atrapas todo y continúas, es como poner un yeso sobre la luz de advertencia en el tablero de tu automóvil. Ya no puedes verlo, pero eso no significa que todo esté bien.
Bueno, no veo ninguna diferencia entre capturar una excepción general o una específica, excepto que al tener múltiples bloques de captura, puede reaccionar de manera diferente dependiendo de la excepción.
Capturará IOException y NullPointerException con una excepción genérica, pero la forma en que debería reaccionar el programa probablemente sea diferente.
Creo que es una excepción general, como sostener un cartucho de dinamita dentro de un edificio en llamas y apagar el fusible. Ayuda por un tiempo corto, pero la dinamita soplará de todos modos después de un tiempo.
De corse, puede haber situaciones en las que sea necesaria la captura de una excepción general, pero solo para fines de depuración. Los errores y los errores deben corregirse, no ocultarse.
Creo que una buena pauta es captar solo excepciones específicas dentro de un marco (para que la aplicación host pueda ocuparse de casos extremos como el disco llenándose, etc.), pero no veo por qué no deberíamos poder atrapar todo excepciones de nuestro código de aplicación. Simplemente, hay momentos en los que no desea que la aplicación se bloquee, sin importar lo que pueda salir mal.
El problema con la captura de todas las excepciones es que puede estar atrapando las que no espera, o las que no debería capturar. El hecho es que una excepción de cualquier tipo indica que algo salió mal, y usted tiene que resolverlo antes de continuar, de lo contrario, puede terminar con problemas de integridad de datos y otros errores que no son tan fáciles de rastrear.
Para dar un ejemplo, en un proyecto implementé un tipo de excepción llamado CriticalException. Esto indica una condición de error que requiere la intervención de los desarrolladores y / o del personal administrativo; de lo contrario, los clientes recibirán una factura incorrecta o podrían surgir otros problemas de integridad de datos. También se puede usar en otros casos similares cuando el simple registro de la excepción no es suficiente y se debe enviar una alerta por correo electrónico.
Otro desarrollador que no entendía correctamente el concepto de excepciones luego envolvió algún código que potencialmente podría arrojar esta excepción en un try genérico ... catch block que descartó todas las excepciones. Afortunadamente, lo vi, pero podría haber causado serios problemas, especialmente desde que el caso de la esquina "muy raro" que se suponía que debía atrapar resultó ser mucho más común de lo que esperaba.
Por lo tanto, en general, detectar excepciones genéricas es malo a menos que esté 100% seguro de saber exactamente qué tipo de excepciones se lanzarán y bajo qué circunstancias. En caso de duda, permita que pasen al manejador de excepción de nivel superior.
Una regla similar aquí nunca es arrojar excepciones de tipo System.Exception. Usted (u otro desarrollador) puede querer detectar su excepción específica más arriba en la pila de llamadas mientras deja que otros pasen.
(Sin embargo, hay un punto a tener en cuenta. En .NET 2.0, si un hilo encuentra excepciones no detectadas, descarga todo el dominio de la aplicación. Por lo tanto, debe ajustar el cuerpo principal de un hilo en un intento genérico ... atrapar bloque y pasar cualquier excepción detectada en su código global de manejo de excepciones).
El punto es doble, creo.
En primer lugar, si no sabe qué excepción ha ocurrido, ¿cómo puede esperar recuperarse de ella? Si espera que un usuario escriba un nombre de archivo incorrecto, entonces puede esperar una excepción FileNotFoundException y decirle al usuario que intente de nuevo. Si el mismo código generara una NullReferenceException y simplemente le dijera al usuario que intente de nuevo, no sabría lo que sucedió.
En segundo lugar, las directrices de FxCop se centran en el código de la Biblioteca / Framework: no todas sus reglas están diseñadas para ser aplicables a los sitios web EXE o ASP.Net. Por lo tanto, es bueno tener un controlador global de excepciones que registre todas las excepciones y salga de la aplicación correctamente.
En mi opinión, debería detectar todas las excepciones que espera , pero esta regla se aplica a cualquier cosa que no sea su lógica de interfaz. A lo largo de la pila de llamadas probablemente deberías crear una forma de detectar todas las excepciones, hacer un poco de registro / dar comentarios al usuario y, si es necesario y posible, cerrar con gracia.
Nada es peor que una aplicación que se cuelga con algún stacktrace desagradable de usuario descargado a la pantalla. No solo proporciona información (tal vez no deseada) sobre su código, sino que también confunde a su usuario final y, a veces, incluso los asusta a una aplicación competidora.
Ha habido muchas discusiones filosóficas (más como argumentos) sobre este tema. Personalmente, creo que lo peor que puedes hacer es tragar excepciones. El siguiente peor es permitir que una excepción burbujee hasta la superficie donde el usuario obtiene una desagradable pantalla llena de tonterías técnicas.
Hay dos casos de uso completamente diferentes. El primero es en el que la mayoría de la gente está pensando, poniendo un try / catch alrededor de alguna operación que requiera una excepción marcada. Esto no debería ser un catch-all de ninguna manera.
El segundo, sin embargo, es evitar que su programa se rompa cuando pueda continuar. Estos casos son:
- La parte superior de todos los hilos (por defecto, las excepciones desaparecerán sin dejar rastro)
- Dentro de un ciclo de procesamiento principal que espera que nunca salga
- Dentro de un Loop procesando una lista de objetos donde una falla no debería detener a otros
- Parte superior del hilo "principal": puede controlar un bloqueo aquí, como descargar un poco de datos a stdout cuando se quede sin memoria.
- Si tiene un "Corredor" que ejecuta el código (por ejemplo, si alguien le agrega un oyente y usted llama al oyente), cuando ejecuta el código debe atrapar Excepción para registrar el problema y permitirle continuar notificando a otros oyentes.
Estos casos SIEMPRE desea capturar Excepción (quizás incluso Throwable algunas veces) para detectar errores de programación / inesperados, registrarlos y continuar.
La mayoría de las veces no se necesita una excepción general. Por supuesto, hay situaciones en las que no puede elegir, pero en este caso creo que es mejor verificar por qué necesita atraparlo. Tal vez hay algo mal en su diseño.
Me gustaría hacer de abogado del diablo para capturar Exception y registrarla y volver a lanzarla. Esto puede ser necesario si, por ejemplo, se encuentra en algún lugar del código y ocurre una excepción inesperada, puede atraparlo, registrar información significativa del estado que no estaría disponible en un simple seguimiento de pila, y luego volver a lanzarlo a las capas superiores para tratar con.
Obviamente, esta es una de esas preguntas en las que la única respuesta real es "depende".
Lo principal de lo que depende es dónde está atrapando la excepción. En general, las bibliotecas deberían ser más conservadoras con excepciones de captura, mientras que en el nivel superior de su programa (por ejemplo, en su método principal o en la parte superior del método de acción en un controlador, etc.) puede ser más liberal con lo que capta.
La razón de esto es que, por ejemplo, no desea capturar todas las excepciones en una biblioteca porque puede enmascarar problemas que no tienen nada que ver con su biblioteca, como "OutOfMemoryException", en la que realmente preferiría burbujas para que el usuario pueda notificada, etc. Por otro lado, si está hablando de capturar excepciones dentro de su método main () que detecta la excepción, la muestra y luego sale ... bueno, probablemente sea seguro detectar casi cualquier excepción aquí.
La regla más importante sobre la captura de todas las excepciones es que nunca se debe tragar todas las excepciones en silencio ... por ejemplo, algo así en Java:
try {
something();
} catch (Exception ex) {}
o esto en Python:
try:
something()
except:
pass
Porque estos pueden ser algunos de los problemas más difíciles de rastrear.
Una buena regla empírica es que solo debe detectar excepciones que pueda tratar usted mismo. Si no puede manejar la excepción por completo, debe dejarla fluir hacia alguien que pueda.