viernes, 28 de marzo de 2008

Más control sobre los LOOPS en 11g

En PL/SQL podemos salir de un LOOP con la cláusula EXIT. Típicamente la usamos para la condición de salida de un loop:
 BEGIN
LOOP
...
EXIT WHEN condición ;
END LOOP;
-- el control sigue aquí
...
END;
Ahora la versión 11g agrega un nivel intermedio: CONTINUE. Con esta sentencia, podemos cancelar la iteración del loop actual y pasar a la siguiente, sin abortar el loop. Puede usarse simplemente CONTINUE o CONTINUE WHEN. En este último caso podremos evitar el uso de la sentencia IF para controlar la condición de salida de la iteración.
 BEGIN
LOOP
...
CONTINUE WHEN condicion; --vuelve al comienzo del loop

-- si condicion=true, esta parte no se ejecuta
...
END LOOP;
END;
Los programadores conservadores se preguntarán para que necesitamos esta sentencia, despues de todo siempre nos hemos arreglado con la cláusula IF-THEN-ELSE de modo de avanzar a la siguiente iteración. Es cierto, no lo necesitamos para hacer cosas que antes no podíamos, pero sí para simplificar el código y facilitar la lectura.

Un ejemplo con CONTINUE

Hay un caso típico donde CONTINUE puede beneficiarnos en la claridad de código para el seguimiento de la lógica: cuando tenemos que hacer múltiples validaciones antes de procesar un registro.

Imaginemos nuestro loop actual (muy simplificado), en donde para cada registro hacemos una serie de validaciones antes de procesarlo. Si una validación falla, debemos pasar al siguiente registro. Para resolver esta lógica, debemos crear una estructura anidada de IFs, ya que debo evitar que se ejecute el resto del loop si una de las validaciones falla.
LOOP
EXIT WHEN condicion;
i:=i+1;

a := valida_1(T(i));
IF (a) THEN
b := valida_2(a);
IF (b) THEN
....
IF (c) THEN

.....
procesoRegistro(T(i));
.....
END IF;
ELSE
....
END IF;
END IF;

END LOOP;
Notemos como los múltiples IF anidados complican el seguimiento del flujo. Muchas veces nos hemos visto complicados al tener que agregar una nueva validación, ya que hay que agregar un nuevo IF al loop, y debo mantener consistentes los correspondientes END IF que deshacen el nivel de anidación.

Ahora veamos como puede verse mejorado con CONTINUE-WHEN:
LOOP
EXIT WHEN condicion;
i:=i+1;

a := valida_1(T(i));
CONTINUE WHEN NOT a;

b := valida_2(a);
CONTINUE WHEN NOT b;

....

procesoRegistro(T(i));

END LOOP;
La mejoría es evidente, conseguimos disminuir la anidación (a 1) y evitar el uso repetitivo de IF/END-IF, reduciendo la posibilidad de cometer errores de lógica al momento de modificar.

CONTINUE es un recurso que evidentemente solo puede utilizarse en Oracle 11g, sin embargo, siendo conscientes que nuestro código no va a compilar en versiones anteriores, es una práctica que contribuye a la legibilidad del código, con todos los beneficios que eso trae aparejado.

Ver también sobre 11g
11g y sus índices invisibles

1 comentario:

Play Baccarat dijo...

Should you tell it ??” a gross blunder.