Antipatrones en el trabajo con excepciones (III)

Uno de los problemas habituales en el manejo de excepciones, no directamente relacionado con las mismas, es el registrar información sobre la excepción que se ha producido. El framework de .Net proporciona unas excelentes clases para el diagnostico y generación de un log para  nuestra aplicación en el namespace System.Diagnostics, conocido esto, el problema se resume en encontrar el balance justo de información que escribiremos en el log de nuestra aplicación. Este problema tiene difícil solución, y solo un adecuada y consistente política a nivel de proyecto nos permitirá alcanzar el equilibrio adecuado. Esta política, como cualquier otra relacionada con convenciones de codificación debe ser escrita y publicitarse entre los miembros del proyecto. Dicho esto, es importante conocer dos antipatrones habituales.


Log and throw: Logear y relanzar la exception


catch(ApplicationException ex)
{
 System.Diagnostics.Trace.WriteLine(«Bla bla bla»);
 throw ex;
}


o


catch(ApplicationException ex)
{
 System.Diagnostics.Trace.WriteLine(«Bla bla bla»);
 throw new MyException(«Bla bla bla», ex);
}


Ambos ejemplos son igual de dañinos y por el mismo motivo, encontraremos numerosas trazas para el mismo error, puesto que muy probablemente quien capture la excepción más arriba, también inserte una entrada en el log. La política aquí es clara o bien se logea la información sobre la excepción o bien se relanza pero nunca se deben hacer las dos cosas si queremos contar con un log de aplicación legible.


Multi-Line Messages: Mensajes de log relacionados en multiples lineas.


using System.Diagnotics;

Trace.WriteLine(«Error en acceso a fichero»);
WriteLine(«La ruta del fichero es muy larga»);


Siempre debemos agrupar los mensajes de logeo lo más posible. Los motivos son dos principalmente, por un lado el rendimiento, puesto que escribir en el archivo de log tiene un coste, y por otro la legibilidad, aunque este no es tan evidente. Viendo el código de ejemplo, se hace evidente que el programador espera que esas dos lineas aparezcan seguidas en archivo de log, pero en una aplicación multihilo (y casí todas las aplicaciones actuales lo son, explicita o implícitamente) , nada garantiza que las lineas se van a escribir seguidas. Podemos terminar encontrando que mensajes realacionados aparecen separados por muchas lineas dentro de nuestro log, lo que sin duda perjudicará gravemente a su legibilidad. Así lo correcto sería:


using System.Diagnotics;

Trace.WriteLine(«Error en acceso a ficheronLa ruta del fichero es muy larga»);

8 comentarios sobre “Antipatrones en el trabajo con excepciones (III)”

  1. Me encantan vuestros altículos, seguid así que aprendo mucho.

    tengo una duda sobre cómo gestionar las excepciones.

    Me explico, tengo una clase creada por mi que hereda de Exception la cual se compone de varias propiedades como prioridad, la excepcion, el tipo de excepcion y el mensaje.

    Además, en el constructor formateo el mensaje en base a estas propiedades que se las paso como parámetro al mismo constructor.

    En base a cómo sea la excepción y su prioridad, se registrará el error en la Bd, email o log.

    Mi duda aparece a la hora de donde usar la clase.

    En principio, la instanciaba en las capas de datos y negocio, pero no lo tengo muy claro.

    Imagino que deberé de usarla siempre que crea que se produzca un error o debo de hacerlo como pienso y instanciarla en las capas inferiores, dejando la de presentación con un mínimo throw ex.

    Por favor, decidme que opináis al respecto porque estoy liadillo

    Gracias a tod@s!!! y saludos!!!

  2. No es un antipatrón logar la excepción para luego relanzarla. Si su aplicación genera una excepción e importa mucho el logado, no puede asumir que manejadores externos logarán la excepción, o que incluso esos manejadores no fallarán.

    Una correcta gestión de excepciones debería permitir un logado inmediato en los casos que se considere necesario, y propagarla (que no es lo mismo que relanzarla), reemplazarla o encapsularla según políticas.

    Una excepción puede marcarse como Logada para evitar la duplicidad de registros de log. Para todas estas cuestiones lo mejor es diseñar o reutilizar un sistema de manejo de excepciones que vaya guiado por políticas; preferiblemente usado mediante técnicas de AOP (Programación orientada por Aspectos).

    Si quéis una visión más completa, investigad acerca del «Exception Handling Application Block» de Microsoft, o el «Policy Injection Application Block».

    Saludos.

  3. ¡Claro que es un antipatrón!.

    Básicamente la idea es que si dejas que una excepción salga de un componente de tu aplicación a otro, este último es el que debe logearla. Sino las trazas crecen hasta el infinito sin añadir información, solo ruido.

    Si quieres añadir información de contexto, añadela a la excepción o incluso envuelve la excepción en otro tipo, ok. Pero si esa excepción o la que la envuelve se va a seguir propagando, no logees nada.

    No entiendo lo que dices de que el logeador externo puede fallar. Tu debes logear toda excepción antes de que abandone tu dominio de aplicación, lógico. Pero toda excepción que se produzca y controle de manera interna a tu aplicación se debe logear en un único sitio, una sola vez. Todo lo demás es ruido añadido a tu traza, que no añade información. La información sobre lo ocurrido debe transportarla la excepción y solo el que en última instancia la controle debe logear la información contenida en la excepciónn.

    Sobre los application blocks que comentas, básicamente mi opinión y la de mucha gente más relevante que yo es que añaden mucha conplejidad en una parte de la aplicación en la que la simplicidad es un valor fundamental. Lo último que quieres cuando tu aplicación va mal es que los arboles no te dejen ver el bosque.

    Si usa EHAB y PIAB para controlar los problemas tienes muchísima flexibilidad de acuredo, pero en un tema donde la flexibilidad puede ser un serio problema. Cuando tienes un error lo mejor que puedes tener es un mecanismo facil, simple y eficiente de encontrarlo y tener que empezar a mirar como están configurados los bloques de aplicación es un pésimo comienzo. Lo mismo pasa con Log4Net, demasiada complejidad…

    Si quieres ver una librería que esta basada en los principios de diseño que yo comento aquí hechalé un vistazo a Live Labs Simple Logging Library (http://justrudd.org/2008/02/18/logging-in-net/, http://www.codeplex.com/LiveLabsLogging) y sobre todo lee sobre Simple Log Philosophy (http://justrudd.org/2008/02/28/logging-in-net-part-2/, http://justrudd.org/2008/03/03/logging-in-net-part-3/, https://simple-log.dev.java.net/nonav/userGuide/philosophy.html). Verás como tu visión de la gestión de excepciones se ha quedado un poco obsoleta, sobre todo desde un punto de vista ágil.

    ¡Un saludo y gracias por tu comentario!

Responder a anonymous Cancelar respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *