Todos aquellos que desarrollamos aplicaciones que son utilizadas en ambientes productivos convivimos con el siguiente hecho: tarde o temprano tu código será ejecutado y producirá un mensaje de error (y posiblemente una falla). Algunas veces es esperado que suceda, otras no.
Por @GerardoMCanedo
Entender qué fue lo que sucedió, y obtener la suficiente información para poder tomar acciones (que eventualmente pueden incluir recodificar), no es una tarea trivial. Al contrario, las normales restricciones de acceso a los ambientes de producción hacen que la resolución del problema sea una tarea imposible, si no consideramos recopilar información y gestionar los posibles errores de forma adecuada.
Además, no todo es código fuente. Un programa depende del ambiente en el que se ejecuta, también generando errores. éstos pueden ser entradas de datos inválidas, archivos inexistentes, permisos insuficientes, discos llenos, configuraciones incorrectas del software, entre otros.
No importa lo “bien” que programemos, tenemos que convivir con estos casos en los cuales las cosas no irán como quisiéramos, y los tendremos que gestionar. Siempre es mejor gestionar estos errores que continuar con el flujo normal, lo que generalmente lleva a problemas de inconsistencia de datos (campos vacíos), u otros comportamientos que nos darán dolores de cabeza en la ejecución del sistema.
Éstos son algunos consejos que pueden ser de utilidad para el desarrollador GeneXus a la hora de gestionar errores:
1 – Validar códigos de error de funciones GeneXus
Varias funciones GeneXus retornan códigos de error al ser invocadas. Luego de utilizarlas, siempre debemos consultar el código de Error.
Encontrar una de las siguientes funciones sin un IF validando su código de error, es un potencial riesgo:
DFRClose | DFRGDate() | DFRGNum |
DFRGTxt | DFRNext | DFROpen |
DFWClose | DFWPDate | DFWPNum |
DFWNext | DFWOpen | DFWPTxt |
OpenDocument | PrintDocument | SetCookie |
SetLanguage | SetTheme | SetUserId |
SetWrkSt | Shell | WriteRegKey |
2 – Web Services
Algo que puedo asegurar es que en producción, en algún momento, la invocación a un Web Service fallará. Los motivos pueden ser variados (red, el sistema que se encuentra del otro lado de la invocación, datos, formatos que se modificaron y no fueron actualizados, entre otros).
Si no gestionamos el error, nuestro usuario final verá un error en nuestro sistema, algo poco amigable que contribuye a la pérdida de confianza en el sistema. Peor aún, podemos finalizar con datos inconsistentes u otros problemas como conexiones abiertas. Incluso puede suceder que el otro sistema arrastre a nuestro sistema a un estado de error, magnificando el problema. Es imperativo tomar en cuenta estos casos a la hora de programar.
El manejo de errores de web services se hace a través del objeto Location, en particular de la propiedad CancelOnError. Si a esta propiedad se le asigna el valor 2, es posible utilizar las funciones GetSOAPErr y GetSOAPErrMsg.
El código para el consumo de un Web Service, tomando en cuenta los posibles errores, luce de la siguiente forma:
3 – Gestión de Errores en Procedimientos
Cuando nos encontramos escribiendo la lógica de negocios, normalmente utilizamos un conjunto de procedimientos. Muchas cosas pueden salir mal: falta de parametrización, errores propios de la lógica de negocio, los errores descriptos anteriormente, etc.
Una buena práctica de desarrollo es indicar en un parámetro el resultado de la operación. Este parámetro es un SDT en el que se indica un código de error, un mensaje y el resultado de la operación.
Este resultado de error de la operación debe ser devuelto hasta la frontera del sistema (Web Panel o servicio) como resultado de la propia operación. Gestionar los errores de esta forma también ayuda a programar de forma correcta las UTLs.
Rules
SDT
- Success: true si la operación tuvo éxito, false en caso contrario. Es intencional que el éxito de la operación sea representado por el valor true. Esto para evitar que el resultado sea positivo por omisión, favoreciendo el principio de seguridad de seguridad por defecto.
- Detalle: agrupa un código de error, una descripción (¡Amigable!) y eventualmente un tipo (error o advertencia). Una buena práctica de desarrollo es indicar un código único en toda la base de conocimiento para el error. De esta forma podemos utilizar la funcionalidad de Búsqueda de la IDE de GeneXus para determinar rápidamente el origen del error que eventualmente nos reporten.
Ejemplo de Uso
Conclusiones
Los errores son inevitables y deben ser gestionados. Cualquiera de ellos que no sea tomado en cuenta a la hora de desarrollar puede terminar en una falla en producción, generando un impacto. Es importante tenerlos en cuenta a la hora de codificar, no enmascararlos y generar la suficiente información para poder ser analizados una vez que ocurran.
Escrito por Gerardo Canedo, Gerente de Seguridad de GeneXus Consulting.
Buen artículo, falta mencionar el manejo de errores con BC y try catch (C# o Java)