Una nueva forma de gestionar los errores

Recientemente introducimos un nuevo mecanismo de gestión de errores mediante el nuevo comando throw().
Esto marcó el primer paso hacia un nuevo sistema de gestión de errores, situado lo más cerca posible del código que los genera.
En la siguiente fase con 4D v20 R4, estamos ampliando este enfoque para interceptar errores durante la ejecución de expresiones.
Profundicemos en los detalles.

try(), una nueva palabra clave útil

Con la introducción de 4D v20 R4, los desarrolladores pueden ahora acceder a una nueva y útil palabra clave: Try(Expression). La palabra clave Try() permite a los desarrolladores ejecutar una expresión encerrada entre paréntesis e interceptar sin problemas cualquier error lanzado durante su ejecución. Estos errores pueden gestionarse mediante el comando Last errors inmediatamente después de la ejecución de la expresión. Esto permite definir la gestión de errores lo más cerca posible del código que los ha generado y, eventualmente, utilizar variables locales.

Escenarios de ejemplo antes de las explicaciones detalladas

División por cero

Consideremos un escenario sencillo: la división por cero. El siguiente ejemplo muestra un método de división euclidiana que lanza un error y devuelve arbitrariamente cero si el divisor es cero. Con Try(), los desarrolladores pueden gestionar los errores de manera más elegante:

#DECLARE($dividend: Real; $divisor: Real)->$result: Real
If ($divisor=0)
$result :=0
throw (-12345; "¡División por cero!")
Else
$result :=($dividend/$divisor)
End if

$result:=Try(division($dividend; $divisor))
If (Last errors#Null)
// Error management
logErrors (Last errors)
End if

ACCEDER a un documento

La gestión de los errores de acceso a un documento es más sencilla si el documento no existe.
Para evitar que se muestre el diálogo de error de 4D, es necesario instalar un gestor de errores, y escribir el código de gestión de errores dentro de este manejador de errores:

$previousErrorHandler:=Method called on error
ON ERR CALL ("errorOpenDoc")
var $fileHandle : 4D.FileHandle:=File($path).open()
If ($fileHandle#Null)
ON ERR CALL ("errorReadDoc")
$text :=$fileHandle.readText()
If (Last errors#Null)
$text :="Error leyendo el archivo"
End if
End if
ON ERR CALL ($previousErrorHandler)

Con la palabra clave Try() se puede escribir todo en la misma sección de código, accediendo a variables locales y simplificando así la legibilidad:

var $fileHandle : 4D.FileHandle:=Try(File($path).open())
If ($fileHandle#Null)
$text :=Try($fileHandle.readText()) || "Error al leer el archivo"
End if

Función de guardado ORDA

Otro caso de uso robusto involucra la función ORDA save (), que puede generar errores predecibles e impredecibles.
Los errores previsibles, como el bloqueo de la entidad, pueden ser manejados directamente a través del atributo success del objeto resultante. Sin embargo, los errores impredecibles, como los duplicados de llave primaria, requieren un manejador de errores instalado con el comando ON ERR CALL de lo contrario, se mostraría el diálogo de error de 4D:

var $customer : cs.CustomerEntity
// Do something with the $customer entity
$previousErrorHandler :=Method called on error
ON ERR CALL ("errorSaveManagement")
$result :=$customer.save()
ON ERR CALL ($previousErrorHandler)
If (Not($result.success))
Case of
: ($result.status=3)
// Locked entity management
: ($result.status=4)
// Other error management
End case
End if

Pero ahora, la palabra clave Try() se convierte en un valioso aliado para manejar errores tanto predecibles como impredecibles sin mostrar el diálogo de error de 4D:

var $customer : cs.CustomerEntity
// Do something with the $customer entity
$result :=Try($customer.save())
If (Not($result.success))
Case of
: ($result.status=3)
// Locked entity management
: ($result.status=4)
// Other error management
End case
End if

Ejecución de expresiones

La palabra clave Try() acepta toda expresión 4D entre paréntesis, ya sean variables, asignaciones, métodos, funciones, etc. En caso de error, el flujo de ejecución se detiene y vuelve a la última palabra clave Try() encontrada (la primera encontrada en la pila de llamadas). Como resultado, sólo tiene que comprobar la pila de errores después de la ejecución de la expresión para saber si se han producido errores.
Tenga en cuenta que si se genera un error utilizando el comando throw() en modo diferido, el flujo de ejecución continúa hasta el final de la ejecución del método/función actual, ofreciendo una forma sencilla de gestionar la propagación de errores.

Resultados

Si la ejecución tiene éxito, Try() devuelve el resultado de la expresión.
En caso de error, devuelve el último resultado de la expresión o ‘undefined’ si no está disponible.
Si la expresión no define ningún resultado (por ejemplo, un método o comando sin resultado), la palabra clave try() devuelve ‘undefined’.

Acerca de la pila de errores

La pila de errores actual se borra antes de que se ejecute la expresión, ofreciendo una pizarra limpia para la gestión de errores dentro del contexto de Try(). Los errores encontrados durante la ejecución de la expresión se añaden a la pila de errores, ofreciendo a los desarrolladores información completa para la depuración.

GESTIóN de errores

Si no se define ningún gestor de errores mediante el comando ON ERR CALL el diálogo de error no interrumpirá la experiencia del usuario al utilizar Try().
Los manejadores de errores globales y locales definidos antes de entrar en el bloque Try() no serán llamados, asegurando una separación limpia entre el contexto try y el resto del código.
Si la expresión define un gestor de errores global o local para la base de datos actual, se invocará cuando se produzca un error durante la ejecución.

ExplorAR nuevos horizontes en la gestión de errores

Esta nueva funcionalidad abre un mundo de posibilidades para la gestión de errores. Pero es sólo el segundo paso en la nueva era de la gestión de errores 4D, que abre el camino a los bloques try-catch multilínea.
Comparta sus opiniones y experiencias en nuestro foro y díganos qué le parece esta nueva funcionalidad.

¡Feliz programación!

Avatar
• Propietario de producto - Damien Fuzeau se ha unido al equipo de 4D Product en febrero de 2019. Como Propietario de producto, está a cargo de escribir historias de usuario, y luego traducirlas a especificaciones funcionales. Su trabajo también implica asegurarse de que las implementaciones de funcionalidades entregadas estén cumpliendo con las necesidades del cliente. Damien es licenciado en ingeniería de software por la Universidad de Nantes. Estuvo más de 23 años en su anterior empresa, primero como desarrollador (descubriendo 4D en 1997), y más tarde como gerente de ingeniería y arquitecto de software. Esta compañía es un Partner OEM de 4D y ha desplegado softwares empresariales basados en 4D para miles de usuarios, en cientos de servidores. Por lo tanto, Damien está acostumbrado al desarrollo y despliegue de 4D en un contexto multilingüe.