Antipatrones en el trabajo con excepciones (II)

Un error en el que los programadores solemos caer es escribir manejadores de excepciones ‘genéricos’, por ejemplo, capturando todas las excepciones a través de un manejador de la clase base (System.Exception en .Net).


try
{
   f();
}
catch (Exception ex)
{
}


El problema con este enfoque es que se produce un enmascaramiento de todas las excepciones. Manejamos igual aquellas excepciones que sabemos que se pueden producir que aquella inesperadas. El problema reside que las excepciones inesperadas, que no sabemos en que condiciones se producen, son a menudo síntomas de mal funcionamiento de nuestra aplicación y por tanto son errores que debemos solucionar y en ningún caso enmascarar. Otro problema asociado es que perdemos información sobre donde se están produciendo los fallos, puesto que cualquier excepción producida en cualquiera de las funciones que se encuentre en la pila será recogida por ese manejador genérico, aunque la función se encuentre a muchos niveles del manejador. Existe un gran hueco entre donde se produce el fallo y se registra.


 


La solución a este problema es clara. Debemos capturar tipos de excepción concretos que se encuentren entre los que es previsible que se produzcan y evitar enmascarar el resto. Así, en el caso de que la función f(), acceda a disco, y puede que el archivo a acceder no exista lo lógico es captura solo la excepción que se produce cuando el archivo no existe.


 


try


{


f();


}


catch (System.IO.FileNotFoundException ex)


{


      //Operaciones a realizar cuando el archivo no existe


}


 


Aún así existen casos en los que capturar excepciones de manera genérica:


 


Cuando realizamos llamadas a recursos remotos, porque puede ser que la comunicación falle de maneras muy diversas y difícilmente predecible, o podemos recibir datos corruptos, o le recurso remoto no estar accesible, etc… existen tantos puntos de fallo posibles que el enfoque más simple es capturar todas las excepciones y tratar de extraer información concreta de la excepción una vez capturada.


 


Cuando llamamos a plugins de terceros que se pueden cargar  en nuestra aplicación, es una medida natural de protección y seguridad contra plugins maliciosos o mal programados capturar todas las excepciones provenientes de un plugin y si se produce alguna descargar el plugin.


 


try


{


      plugin.Load();


      plugin.DoSomeThing();


}


catch (Exception ex)


{


      plugin.Unload();


}


 


Otro caso en el que capturar todas las excepciones puede ser aceptable es para tratar de revertir el estado de la aplicación, por ejemplo si tenemos un usuarios con altos privilegios impersonado y se produce una excepción, es una buena practica revertir esa impersonación. Recordemos que una vez que se produce una excepción que no esperamos no debemos confiar en el comportamiento de  nuestra aplicación, y esto es especialmente cierto en lo que a seguridad y privilegios se refiere. Muchos errores relacionados con la elevación de privilegios tienen su base en caminos inesperados en el flujo de ejecución de la aplicación.


 


En la próxima entrega: Errores en el logeo de excepciones

4 comentarios sobre “Antipatrones en el trabajo con excepciones (II)”

Deja un comentario

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