Uso excepcional de las excepciones, que significa: “use exceptions for exceptional problems”.

Parche

Los errores en un sistema son parte del día a día en la vida de un programador. Ocurrirán, sin excepción, en algún momento cualquier sistema producirá un estado no esperado. Este estado se conoce como error o bug (no son lo mismo pero se suelen usar como sinónimos)La sola mención de la existencia de un bug/error puede causar incomodidad a mas de una persona en  el área de trabajo. Nadie quiere errores en su sistema, los sistemas no deberían tener errores, si un sistema arroja un error solo significa que el sistema es de mala calidad. Sumado a esto, muchos programadores pecan de positivos diseñando programas optimistas  que no contemplan estados erróneos o excepciones. Bajo el argumento de que “las excepciones deben ser excepcionales”  se omite el diseño de un sistema que te permita dar seguimiento  a los flujos no esperados de tu aplicación. Tampoco es que la frase sea incorrecta, solo es incompleta. A continuación te explico el porque.

El origen de “use exceptions for exceptional problems”.

En el libro The Pragmatic Programmer , Capitulo 4, Sección: When To Use Exceptions. Los autores hacen énfasis en que un programa debe poder verificar cada posible error. Esto acarrea dos problemas:

  • ¿Como se deben de manejar los errores?
  • ¿Que se considera una excepción?.

La respuesta para estos dos caso es: depende. No hay una regla escrita que te permita definir cuando un estado en el programa debe convertirse en excepción o en un error. Tampoco hay un método que te permita tratar con los errores dentro de la aplicación. Por ejemplo, en el siguiente caso:

Una aplicación lee un archivo, el archivo no existe en la ruta especificada, ¿debería arrojarse una excepción?. Si el archivo es un recurso del sistema, el cual debería existir en todo momento. Entonces, es correcto que el sistema arroje una excepción determinada, el sistema no debería poder manejar el caso excepcional de que un archivo critico haya desparecido. Pero que tal si el archivo que debe ser leído es un archivo temporal de poca importancia, ¿debería manejarse una excepción?, la respuesta es no, es un error conocido. Este caso es un estado esperado, los archivos temporales pueden ser borrados sin previo aviso, la aplicación debe de tener un flujo que maneje este escenario.

No todos los errores son iguales.

Nadie puede hacer un programa que maneje todos los errores, la mayoría de las salidas incorrectas tus programas aun no las conoces. Entonces, ¿como puedes hacer un  programa que sepa manejar esto?. La respuesta es: una excepción desconocida debe convertirse en un error conocido siempre que sea posible. En el ciclo de vida de tu software van a aparecer errores recurrentes de operaciones conocidas: un timeout en tu base de datos,  error de conexión con web services, divisiones entre ceros, overflow de tipo de datos, etc. Viejos conocidos que deben de ser clasificados en el menor tiempo posible. En este punto me vas a preguntar: ¿si, y como los clasifico?. Lamento decirte que el sistema de identificación y seguimiento  para poder filtrar los errores va a depender de ti. No hay respuesta correcta o incorrecta, códigos de error, strings de seguimiento, objetos tipados, GUIDs, o cualquier otra opción es valida siempre y cuando sea consistente.

Las excepciones y la encapsulación.

Capturar una excepción en especifico implica que se conoce el tipo de esta. El programa cede el control a través de un objeto de tipo Exception y solo aquel componente que pueda atraparla tendrá el control del flujo de programa, una especie de GOTO. Este brinco entre niveles de componentes trae la  problemática de violar la encapsulación. Un método en un nivel inferior arroja una excepción, otro método algunos niveles mas arriba, para poder atrapar la excepción debe saber como se comporta otro componente. Tenemos una clase que sabe demasiado acerca de  como funciona otra clase, estamos violando el principio de la encapsulación.  ¿Que hacer en estos casos?, tu sistema debe de tener mecanismos que permitan a todos los componentes saber cuando un error es conocido o cuando es una excepción excepcional que debe permitirse pasar. Osea, un lenguaje común entre componentes mediante las reglas o políticas del sistema. Capturar excepciones por su tipo en varios niveles del sistema solo va a generar confusión.

Conclusiones.

El significado de la frase una excepción debe ser excepcional bajo ningún caso debe entenderse como un permiso para no manejar los estados desconocidos de un programa. Al contrario, significa que cualquier error que este en posibilidad de ser manejado debe de tratarse. Solo aquellos errores que van mas allá de la lógica del sistema, hacen el programa inoperable o lo dejan seriamente lisiado deben de tratarse como excepciones excepcionales. Y tu, ¿como manejas tus errores?, ¿que estrategias ocupas?  ¿tienes algún sistema que te funcione?

 

 

 

Gustavo Sánchez