¿Es más razonable registrar las excepciones en una clase de excepción general o en una clase de excepción base?

15

Estoy en el proceso de refactorizar una aplicación web bastante grande. Uno de los principales problemas es el manejo de errores inconsistente y estoy tratando de encontrar una estrategia sensata. He creado un controlador de errores personalizado, a través de set_error_handler que esencialmente se convierte en errores de PHP en ErrorExceptions y una clase de excepción base personalizada, que hereda directamente de Exception .

En producción, estoy usando una excepción genérica catch-all, a través de set_exception_handler , y estoy a punto de agregar el registro de excepciones * a la mezcla. Mi dilema es dónde hacer el registro real, en la clase de excepción base o en el catch-all.

He pensado en un par de razones para registrarlo en el catch-all:

  • Hay bastantes excepciones en el código que deben convertirse a algún hijo apropiado de la clase de excepción base. Hasta que eso suceda, no se registrarán todas las excepciones.
  • De alguna manera, parece más natural hacerlo en el catch-all, una clase de excepción base no debería hacer más que ser solo eso. (Puede ser un principio de responsabilidad única, pero podría ser un sentimiento equivocado)

y un motivo para iniciar sesión en la clase de excepción base:

  • Actualmente, el catch-all solo se utiliza en la producción. Sería fácil introducirlo en nuestros otros entornos (desarrollo, pruebas) pero eso requeriría algunos ajustes, ya que los errores se manejan de manera diferente según el entorno, ya que en producción se traducen a páginas de error 404/503.

¿Hay alguna práctica aceptable para dónde registrar excepciones?

* El registro implicará escribir en un archivo de texto al principio, y puede evolucionar hasta enviar correos para ciertos tipos de excepciones.

Algunas aclaraciones, solicitadas por respuesta de @ unholysampler :

Me enfrento a una base de código de 2 * 10 ^ 6 sloc, con muchas cosas de terceros sobre las que no tengo control, y parte del código que sí tengo control sobre las excepciones previas a las fechas en PHP. Y también hay algún código reciente de mierda, nos estamos recuperando de un largo período de intensa presión en la que virtualmente tuvimos que dejar de pensar y simplemente hackear.

Estamos refaccionando activamente para abordar todas las inconsistencias e introducir un enfoque de manejo de errores razonable, pero eso llevará algún tiempo. Estoy más interesado en qué hacer hasta que llegue al punto donde los errores se manejan de manera adecuada. Probablemente haré otra pregunta sobre una estrategia de excepción sensible en algún momento.

La principal motivación detrás del registro es recibir un correo electrónico en mi teléfono cada vez que algo malo sucede en la producción. No me importa si los volcados de datos se vuelven enormes, si lo hacen tendré un trabajo cron eliminando los antiguos de vez en cuando.

    
pregunta yannis 24.11.2011 - 05:11

2 respuestas

11

En resumen, la única vez que debería registrar la existencia de una excepción es cuando la está manejando.

Cuando lanza una excepción, es porque su código ha alcanzado un estado en el que no puede proceder correctamente. Al lanzar una excepción, está representando un mensaje específico para su programa sobre el error que ocurrió. No debe capturar una excepción hasta que se encuentre en un punto donde pueda manejarse adecuadamente.

El código que escribe como parte de su aplicación principal debe ser consciente de los tipos de excepciones que se pueden lanzar y cuándo se pueden lanzar. Si no puede hacer nada productivo con una excepción, no lo atrape. No registre una excepción hasta que se esté manejando. Solo el código de manejo sabe lo que significa la excepción en el contexto del flujo del programa y cómo responder a él. Escribir un mensaje de registro aquí puede tener sentido aquí. Si usa un marco de registro, puede establecer un nivel de registro para el mensaje y, potencialmente, filtrarlos. Esto funciona bien para las excepciones que pueden ocurrir, pero no son críticas y se pueden recuperar de forma limpia.

Su excepción atrapa todo, es su último esfuerzo para evitar que su código se caiga en una muerte fea. Si ha llegado hasta aquí, registra toda la información de estado y error que pueda. Luego haces todo lo posible para decirle al usuario que el programa se bloquea antes de que todo se detenga. Tu objetivo debería ser nunca ejecutar este código.

Incrustar el inicio de sesión en la clase base no sigue las pautas anteriores. La clase base no sabe nada sobre el estado del código. (Tener el seguimiento de la pila no cuenta porque no va a escribir código que tome decisiones basadas en analizarlo). La clase base no puede hacer nada para indicar la gravedad o cómo se puede manejar la excepción. No desea grandes volcados de datos y seguimientos de pila cada vez que haya una excepción simple que pueda manejar y recuperar de forma limpia.

    
respondido por el unholysampler 24.11.2011 - 05:50
3

Si su idioma / tiempo de ejecución no le permite determinar fácilmente el origen de la excepción, hay un caso para registrarlo en el lanzamiento. C ++ y algunos motores JS no exponen el archivo + línea o la pila de llamadas de la excepción en el momento en que la detectó / pero esta información está disponible en el momento en que construye la excepción.

Nuestra solución fue proporcionar un mecanismo que utilizara la configuración de tiempo de ejecución para permitir el registro del tipo de excepción junto con una pila barata al intentar diagnosticar estos problemas.

    
respondido por el JBRWilkinson 24.11.2011 - 09:37

Lea otras preguntas en las etiquetas