Tutorial de Ruby – Parte 27 – Procesamiento de excepciones: rescue

Un programa en ejecución puede encontrarse con problemas inesperados. Podría no existir un fichero que desea leer, al salvar algunos datos se podría llenar un disco, un usuario podría introducir algún tipo de datos de entrada poco adecuados.

 

ruby> file = open(«algun_fichero»)

ERR: (eval):1:in ‘open’: No such file or directory – «algun_fichero»

 

Un programa robusto manejará estas situaciones prudente y elegantemente. Satisfacer estas expectativas puede ser una tarea exasperante. Los programadores en C se supone que deben verificar toda llamada al sistema que pudiese fallar y decidir inmediatamente que hacer.

 

FILE *file = fopen(«algun_fichero»,»r»);

if (file == NULL) {

fprintf(stderr, «No existe el fichero\n»);

exit(1);

}

bytes_read = fread(buf,1,bytes_desired,file);

if (bytes_read != bytes_desired) {

/* aquí, más gestión de errores … */

}

 

Con esta práctica tan aburrida los programadores tienden a ser descuidados y la incumplen siendo el resultado un programa que no gestiona adecuadamente las excepciones. Por otro lado, si se realiza adecuadamente, los programas se vuelven ilegibles debido a que hay mucha gestión de errores que embrolla el código significativo.

En Ruby, como en muchos lenguajes modernos, se pueden gestionar las excepciones para bloques de código de una forma compartimentalizada, lo que permite tratar los imprevistos de forma efectiva sin cargar excesivamente ni al programador ni a cualquier otra persona que intente leer el código posteriormente. El bloque de código marcado con

begin se ejecutará hasta que haya una excepción, lo que provoca que el control se transfiera a un bloque con el código de gestión de errores, aquel marcado con rescue. Si no hay excepciones, el código de rescue no se usa. El siguiente método devuelve la primera línea de un fichero de texto o nil si hay una excepción.

 

def first_line( filename )

begin

file = open(filename)

info = file.gets

file.close

info # Lo último que se evalúa es el valor devuelto

rescue

nil # No puedo leer el fichero, luego no devuelvo una cadena

end

end

 

A veces nos gustaría evitar con creatividad un problema. A continuación, si el fichero no existe, se prueba a utilizar la entrada estándar:

 

begin

file = open(«algun_fichero»)

rescue

file = STDIN

end

begin

# … procesamos la entrada …

rescue

# … aquí tratamos cualquier otra excepción

end

 

Dentro del código de rescue se puede utilizar retry para intentar de nuevo el código en begin. Esto nos permite reescribir el ejemplo anterior de una forma más compacta:

 

fname = «algun_fichero»

begin

file = open(fname)

# … procesamos la entrada …

rescue

fname = «STDIN»

retry

end

 

Sin embargo, este ejemplo tiene un punto débil. Si el fichero no existe este reintento entrará en un bucle infinito. Es necesario estar atento a estos escollos cuando se usa retry en el procesamiento de excepciones.

 

Toda biblioteca Ruby genera una excepción si ocurre un error y se pueden lanzar excepciones explícitamente dentro del código. Para lanzar una excepción utilizamos raise. Tiene un argumento, la cadena que describe la excepción. El argumento es opcional pero no se debería omitir. Se puede acceder a él posteriormente a través de la variable global especial $!.

 

ruby> begin

ruby| raise «error»

ruby| rescue

ruby| print «Ha ocurrido un error: «, $!, «\n»

ruby| end

Ha ocurrido un error: error

nil

 

Gus Terrera

Apasionado por el agile testing y la ia.

Deja una respuesta