2009-03-05 12 views
9

Recientemente tuve que desarrollar un módulo adicional para un servicio existente desarrollado por un colega. Se había colocado un bloque try/catch en la función principal de trabajo para la captura de todas las excepciones unhadled que burbujeaban a este nivel, el registro de ellos, junto con información sobre seguimiento de la pila, etc:¿Cómo implementar el manejo de excepciones de nivel superior?

try 
{ 
    // do main work 
} 
catch(Exception ex) 
{ 
    // log exception info 
} 

bien esto hace que el programa sea muy estable (como se en 'improbable que se cuelgue'), lo odio porque cuando estoy probando mi código, no veo las excepciones causadas por él. Por supuesto, puedo mirar el registro de excepciones y ver si hay entradas nuevas, pero prefiero mucho la respuesta directa de obtener la excepción en el momento en que se lanza (con el cursor en la línea derecha del código, por favor).

Quité este try/catch de nivel superior al menos mientras todavía estaba codificando y probando. Pero ahora mi tarea está terminada y tengo que decidir si volver a ponerla para el lanzamiento, o no. Creo que debería hacerlo, porque hace que el servicio sea más estable, y el objetivo es que se ejecute en segundo plano sin necesidad de supervisión. Por otro lado, he leído que uno solo debe llamar a excepciones específicas (como en IoException), no genéricamente Exception.

¿Cuál es su consejo sobre este tema?

Por cierto, el proyecto está escrito en C#, pero también me interesan las respuestas para lenguajes que no sean .NET.

+0

Vea también http://stackoverflow.com/questions/576532/is-dying-is-awesome-preferred – Brian

Respuesta

10

Vuelva a colocarlo.

La excepción solo debe ser relevante durante la prueba. De lo contrario, no tiene sentido mostrarlo al usuario.

El registro está bien.

También puede utilizar el símbolo DEPURAR definido por Visual Studio para depurar construcciones como un indicador.

... 
    } catch(Exception e) { 
#if DEBUG 
      throw; 
#else 
      log as usual 
#endif 
    } 

Así que la próxima vez que se necesita una modificación del indicador de depuración se debe establecer en true y la excepción se abrirá.

+0

¡Hm, me gusta la bandera de depuración! – Treb

+0

¿No debería usar 'throw' no 'throw e'? De lo contrario, el seguimiento de la pila se borrará (o algo así, no muy seguro). – strager

+0

@strager: ¡Sí! El ejemplo anterior enmascarará la excepción original. Solo usa 'throw'. –

2

Lo ideal es que desee manejar una excepción lo más cerca posible de donde ocurrió, pero eso no significa que un controlador de excepción global sea una mala idea. Especialmente para un servicio que debe seguir funcionando a toda costa. Continuaría lo que has estado haciendo. Deshabilítelo mientras depura, pero déjelo en su lugar para la producción.

Tenga en cuenta que se debe utilizar como una red de seguridad. Aún así intente atrapar todas las excepciones antes de que lleguen tan lejos.

4

En cualquier aplicación Java, que casi siempre se desea definir un manejador de excepciones para las excepciones no capturadas con algo como esto:

Thread.setDefaultUncaughtExceptionHandler(...); 

donde el objeto que va a coger estas excepciones no capturadas será al menos registrar el fracaso hasta tienes la oportunidad de saberlo. De lo contrario, no hay garantía de que incluso se te notifique que un hilo ha recibido una excepción, a menos que sea tu hilo principal.

Además de hacer esto, la mayoría de mis hilos tienen un try/catch, donde voy a coger RunnableException (pero no Error) y log ... que algunos hilos morirán cuando esto sucede, los demás van a iniciar sesión y hacer caso omiso, otros mostrarán una queja al usuario y le permitirán al usuario decidir, dependiendo de las necesidades de la Aplicación.Este try/catch está en la raíz del Thread, en el método Runnable.run() o equivalente. Como el try/catch está en la raíz del Thread, no hay necesidad de deshabilitar a veces esta captura.

Cuando escribo en C#, código de manera similar. Pero todo esto depende de la necesidad de la aplicación. ¿Es la excepción una que dañará los datos? Bien, no lo atrape e ignórelo. SIEMPRE inicie sesión, pero luego deje que la aplicación muera. La mayoría de las excepciones no son de este tipo, sin embargo.

2

El impulso de atrapar todas las excepciones y hacer que el programa sea "estable" es muy fuerte y la idea parece muy atractiva para todos. El problema, como usted señala, es que esto es solo una estratagema y que el programa puede ser defectuoso y peor, sin indicaciones de fallas. Nadie monitorea los registros regularmente.
Mi consejo sería tratar de convencer al otro desarrollador para que realice pruebas exhaustivas y luego implementarlo en producción sin la captura externa.

+0

Entiendo de dónde vienes, pero hay una gran clase de excepciones donde tu programa puede ejecutarse en un estado degradado, pero aún ejecutarse, donde realmente deseas capturar y registrar excepciones. La estabilidad sí importa Solo tienes que saber dónde NO PUEDES hacer esto. – Eddie

+0

@Eddie - Es cierto que esta área siempre depende de la aplicación y de la expectativa del usuario. A todos nos gustaría hacer aplicaciones de rendimiento robustas que nunca fallan, pero luego las llamadas de realidad :). Nada es mejor que las pruebas iniciales exhaustivas, la cobertura de código y las versiones beta con clientes reales para obtener confianza. –

1

Si desea ver la excepción cuando ocurre, en Visual Studio puede ir al menú DEPURAR, seleccionar EXCEPCIONES y puede decirle al depurador que rompa tan pronto como se produzca una excepción. Incluso puede elegir qué tipo de Excepciones. :)

+0

¿Y cómo funciona eso cuando el programa en cuestión se está ejecutando como un SERVICIO? – Treb

+2

Si carga el servicio en la memoria y luego lo conecta, todo esto funciona como solía hacerlo. Si es remota (como en el caso de que el servicio esté en algún servidor), hay algo que tiene que instalar en el servidor para permitir la depuración remota. Si necesita hacer esto al INICIAR, puede agregar un "servicio ficticio" en su ejecutable, iniciar ESE uno (que carga el EXE en la memoria), adjuntarlo al proceso y luego iniciar su otro servicio (con capacidades completas de depuración). Funciona EXCELENTE. –