Una técnica que hasta ahora me ha gustado mucho a la hora de programar es utilizar arrays para almacenar en ellos los datos de un registro, utilizándolos de forma cómoda en los formularios de interacción con el usuario. Si un usuario abre la ficha de modificación de un registro, éste siempre tiene la opción de validar los cambios que haga (botón aceptar) o bien de deshacerlos (botón cancelar). Y por esta razón es necesario utilizar una "copia" de los datos del registro sin actuar diréctamente en la tabla, sobreescribiendo los datos más tarde si el usuario ha decidido guardar los cambios, o dejando la tabla tal cual estaba en caso contrario.
Con la técnica de los arrays me refiero a crear uno con tantos elementos como campos tenga la tabla. De esta forma, fácilmente se pueden leer los datos del registro a modificar (en este ejemplo una tabla de clientes):
DbfRead( "clientes", aDatos )
FUNCTION DbfRead( cAlias, aDatos )
LOCAL nI := 0
FOR nI := 1 TO ( cAlias )->( fCount() )
aDatos[ nI ] := ( cAlias )->( fieldGet( nI ) )
NEXT
RETURN nil
Después, a la definición de cada cuadro de texto en el que se muestren los datos del cliente, se le asigna un elemento del array; más tarde, si el usuario decide guardar los cambios, de nuevo muy fácilmente se pueden sobreescribir los valores de los campos por los del array:
DbfSave( "clientes", aDatos )
FUNCTION DbfSave( cAlias, aDatos )
LOCAL nI := 0
FOR nI := 1 TO ( cAlias )->( fCount() )
( cAlias )->( fieldPut( nI, aDatos[ nI ] ) )
NEXT
RETURN nil
Si bien esto facilita mucho las cosas, permitiendo mantener un código muy limpio y legible, se convierte en un problema a largo plazo por dos razones: La primera y menos importante, que esta técnica te obliga a definir los cuadros de texto en el mismo orden en el que estén situados los campos en la tabla, o por lo menos a estar atento a corresponder cada número de elemento del array con su campo correspondiente, ya que el array recorre los campos de la tabla de principio a fin; y la segunda y más importante, que si se da el caso de que haya que añadir o suprimir un campo de la tabla en medio de ésta, habrá que renumerar de nuevo la definición de los cuadros de texto uno a uno.
Por eso yo he decidido que a menos que encuentre otra solución, a partir de ahora voy a utilizar una variable para cada campo, cosa que puede requerir más trabajo al principio (para guardar los datos en la tabla hay que asignar a cada campo su variable por separado), pero que sin duda no acarreará problemas de este tipo en un futuro; además, también se gana legibilidad del código, puesto que, por ejemplo, una variable para el teléfono de un cliente pasa a llamarse cTelefono, y no aDatos[05].
comentarios (7) |
No hace mucho que te sigo, pero estaria bien que indicaras que lenguage usas en los codigos de ejemplo que pones.
Sobre lo que comentas sobre los arrays quizas sea una buena solución crear una classe para cada tipo de registro con el que tengas que trabajar.
Podrias hacer una superclasse con dos metodos, uno para recuperar los datos de la tabla y otro para escribir en ella.
No te fies mucho de lo que pongo qe son las 5 am...
Un saludo!
El tema de los arrays que comentas es algo con lo que más de uno hemos jugado... y como bien dices tienen sus ventajas y desventajas segun el lenguaje que emplees.
Yo que suelo programar en PHP me encuentro con que tengo arrays asociativos, con lo que puedo recuperar de una BBDD (MySQL sobre todo) los registros en un array cuyo índice es el nómbre de la columna.
Es más, las maravillosas funciones de arrays que tiene PHP hacen que sea más fácil trabajar con arrays que con otro tipo de variables... ;-)
Monitotxi,
Los ejemplos están escritos en xbase, es decir, en Clipper (aunque este es el nombre de uno de los compiladores compatibles). Sobre lo de la clase, tienes razón, de hecho las hay preparadas para esto, como tDbf de Manu Expósito, pero si no quieres utilizarlas (como es el caso), el problema surge :)
Fernando,
Esa es una de las cosas que me encantaron los días que experimenté con PHP, llamar al elemento de un array por el nombre... ¡qué pasada!
Jaime
Dos cosas: Quizá deberías replantearte el tema de los arrays. ¿Has pensado que en lugar de definir variables para cada campo y perder la funcionalidad de los arrays podrías definir etiquetas para cada campo y tener las ventajas de los dos enfoques?
Por ejemplo:
#define FLD_CLITELEFONO 1
aReg[ FLD_CLITELEFONO ] := FieldGet( FLD_CLITELEFONO )
etc, etc. Así cuando cambies la estructura del fichero DBF solo tienes que cambiar la etiqueta y todo sigue igual. Incluso yo llegue a crearme una utilidad que leía todos los ficheros DBF y creaba un fichero .ch con todas las definiciones de campos y luego en los programas solo tenía que hacer #include's a discreción. :)
Por cierto, no se si sabeis que en xHarbour tambien tienen arrays asociativos aunque creo que luego han sido implementados como tablas Hash, lo que te daría otro posible enfoque.
Espero haber sido de ayuda. Saludos.
Juan Luis
Jaime:
Con xHarbour, (compilador xBase Open Source), tenes la posibilidad de usar los arrays asociativos como en PHP.
De esta forma podras acceder a los datos de 3 formas distintas.
1) Como array. aDatos[ n ]
2) Como objeto. aDatos:Nombre
3) Como array asociativo. aDatos[ "NOMBRE" ]
Como veras con esto tienes toda la flxibilidad para usar cualquier forma en cualquier momento.
Ej: Deberias usar la 3 forma para crear el array asociado con los nombres.
Podrias usar la segunda al crear los Gets.
Y podrias usar la primera para guardar nuevamente los datos en la tabla y para realizar el control de cambios ya que van a estar en el mismo orden que los campos de la tabla.
Juan Luis y Walter,
Muchas gracias por los consejos. La verdad es que esa nueva funcionalidad de xHarbour (que desconocía), es una mejora muy muy buena para el compilador. Yo soy un total partidario de xHarbour, me parece estupendo que no nos quedemos con la funcionalidad de Clipper, sino que lo mejoremos. Bueno, el caso es que si estoy dispuesto a perder compatibilidad con Clipper, esa puede ser una solución muy buena. Y en caso de no querer hacerlo, la de José Luis es otra opción a la que podría optar. Lo pensaré, gracias.
Yo uso la tecnica de Juan Luis en mis programas clipper, y funciona perfectamente.
Genera un código muy limpio , y evita el uso de de objetos reales.
Aun más ,el codigo se puede mejorar con:
FUNCTION DbfRead( cAlias )
local aDatos[(cAlias)->(fcount())]
aeval(aDatos,{|ele,npos| aDatos[npos]:=(calias)->(FieldGet(npos)) })
Return aDatos
y si te gusta el estilo objetos , puedes simularlo con el procesador :
#translate :codigo => \[1\]
#translate :nombre => \[2\]
y hacer referencia a ellos como :
aDatos:codigo
aDatos:nombre
Saludos .
Manuel.