try practices practice management handling good exceptions errors catch business best logging exception-handling anti-patterns

logging - practices - ¿Por qué "log and throw" se considera un antipatrón?



java rethrow exception best practice (4)

Esta pregunta fue provocada por una discusión en torno a este artículo , donde no recibí ninguna buena respuesta.

¿Por qué registrar tu excepción y luego volver a lanzarla (preservando el rastro original de la pila, por supuesto) sería una mala idea si no puedes manejarla de otra forma?


El registro y lanzamiento de IMO es una clara violación del Principio de Menos Sorpresa.

Si la excepción se maneja adecuadamente en la pila de llamadas, puede que no valga la pena ingresar en el registro de errores. Y luego es confuso encontrar una entrada de registro de error.


Log-and-throw es un buen patrón si la entidad que atrapa y vuelve a lanzar la excepción tiene motivos para creer que contiene información que no se registrará más allá de la pila de llamadas, al menos no de la manera más deseada. Un par de razones por las cuales esto puede ocurrir:

  1. La excepción puede capturarse y redistribuirse en un límite de capa de aplicación, y puede contener información privilegiada. Sería malo para una capa de base de datos permitir una excepción diciendo, por ejemplo, "Intentar agregar la clave duplicada ''fnord'' al campo ''usuarios''" para llegar a la capa de aplicación externa (que a su vez podría exponerlo a un usuario), pero podría ser útil para porciones internas de la base de datos para lanzar una excepción y la interfaz de la aplicación para atraparlo, registrarlo de forma segura y volver a lanzar una excepción algo menos descriptiva.
  2. La excepción puede ser una que la capa externa probablemente esperaría manejar sin iniciar sesión, pero la capa interna puede saber algo que la capa externa no indica, lo que sugeriría que el registro puede ser útil. Como un ejemplo crudo, una capa de aplicación intermedia podría estar programada para intentar conectarse a un servidor y, si eso no funciona, pruebe con otra. Inundar el registro de la aplicación con mensajes de "conexión fallida" mientras un servidor está inactivo para el mantenimiento puede no ser útil, especialmente dado que, desde la perspectiva de la aplicación, todo funcionó bien. Puede ser útil reenviar información sobre la falla de conexión a un recurso de registro asociado con servidores, que luego podría filtrar los registros para generar un informe de cuándo subió y bajó el servidor, en oposición a un registro de cada intento de conexión. .

Supongo que la razón más simple es que normalmente tendrías un solo manejador de alto nivel haciendo esto por ti, así que no hay necesidad de contaminar el código con este manejo de excepciones.

El argumento de las preocupaciones transversales es básicamente que es una pérdida de tiempo manejar errores que no le conciernen. Es mucho mejor dejar que el error burbujee en la pila de llamadas hasta que se encuentre un controlador apropiado.

En mi opinión, la única vez que debe atrapar una excepción es cuando puede hacer algo útil con los resultados. Capturar simplemente para iniciar sesión no es útil, porque podría centralizar ese trabajo más adelante.


Supongo que la respuesta es en gran parte porque ¿por qué lo atrapa si no puede manejarlo? ¿Por qué no dejar que quienquiera que pueda manejarlo (o a quien no le quede más remedio que manejarlo) lo registre, si sienten que es digno de registro?

Si lo detecta, lo registra y lo vuelve a lanzar, entonces no hay forma de que el código en sentido ascendente sepa que ya ha registrado la excepción, por lo que la misma excepción podría registrarse dos veces. O, lo que es peor, si todo el código ascendente sigue este mismo patrón, la excepción se puede registrar un número arbitrario de veces, una para cada nivel del código que decida capturarla, registrarla y luego volver a lanzarla.

También algunos podrían argumentar que, dado que lanzar y atrapar excepciones son operaciones relativamente costosas, toda esta captura y reinicio no está ayudando a su rendimiento en el tiempo de ejecución. Tampoco está ayudando a su código en términos de concisión o facilidad de mantenimiento.