Refactorizando con arrays de controles

La refactorización en Programación Extrema consiste en la revisión continua del código para mejorar su legibilidad, evitar duplicaciones, hacerlo más eficiente y más facilmente modificable. Para una introducción a la Programación Extrema ver el post de 30.ago.2002 de este weblog.

Estos dias estoy migrando Guardian a Harbour y mi buen amigo Manuel Calero me explicó la técnica del uso de arrays de controles en dialogos de edición de datos. La idea es que en vez de tener un montón de objetos GET, meterlos todos dentro de un array de get’s de manera que sea más fácil su manipulación.

código a refactorizar

En mis programas uso una indicación de que el registro que está en edición se ha modificado. Esta indicación se realiza mediante un bitmap colocado en el extremo inferior del dialogo que cambia de color cuando se modifica cualquier campo del dialogo. Al entrar a editar el dialogo el bitmap se encuentra atenuado y en cuanto se modifica cualquier campo el bitmap cambia y muestra un color más vivo.

Para ello, en cada GET tenía definida el evento bChange de manera que llamaba a una función que cambiaba el bitmap a mostrar. Algo asi:

REDEFINE GET oGet05 VAR cClUsuario ID 105 OF oDlg
oGet05:bChange := { || HaCambiado( oBmp ) }

y luego la función que cambiada el bitmap:

Function HaCambiado(oBmp)
   oBmp:Reload( 'CLIP_ON' )
   oBmp:refresh()
Return NIL

El problema de esto era que si el dialogo tenía 20 gets, tenía que tener 20 veces el dichoso oGet:bChange definido.

Refactorización

Lo primero que hice para refactorizar fue definir un array vacio de 20 elementos, tantos como GET tenía mi dialogo. Después redefiní los get a la manera habitual, pero cada get no era un objeto sino un elemento del array de GET:

LOCAL aGet [20]
...
REDEFINE GET aGet[02] VAR cClUsuario ID 102 OF oDlg

La gracia está en la manera de hacer el cambio del bitmap cuando cualquier objeto GET cambia. Ahora esto se hace en una sola linea de código usando AEVAL:

AEval(aGet,{|oGet| oGet:bChange:={||(oBmp:Reload('CLIP_ON'),oBmp:refresh())}})

Con esto he conseguido:

  • Reducir el tamaño de mi código fuente – he quitado todas las sentencias oGet:bChange y he puesto un sólo AEVAL.
  • Suprimir una función, con lo que mejoro el acoplamiento del programa.
  • Hacer el código más legible y más fácil de mantener.

Gracias, Manuel.