Mejorando la legibilidad del código con GeneXus en el blog de Marcos Crispino
En el siguiente post se comparan las invocaciones con call o udp en GeneXus.
Mejorando la legibilidad del código
En GeneXus, cuando invocamos un objeto tenemos la posibilidad de hacerlo con un call o con un udp.
Supongamos que tenemos un procedimiento que realiza alguna operación y devuelve un valor. Solo para el ejemplo, supongamos que tenemos un procedimiento Suma que recibe dos valores, &a y &b, y devuelve su suma.
¿Cuál es la diferencia entre invocar dicho procedimiento con call o con udp? Las invocaciones serían así:
Supongamos que tenemos un procedimiento que realiza alguna operación y devuelve un valor. Solo para el ejemplo, supongamos que tenemos un procedimiento Suma que recibe dos valores, &a y &b, y devuelve su suma.
¿Cuál es la diferencia entre invocar dicho procedimiento con call o con udp? Las invocaciones serían así:
call(PSuma, &a, &b, &result) o &result = udp(PSuma, &a, &b) |
¿Cuál de las dos es mejor?
Desde el punto de vista del código generado, son casi idénticos. En realidad no tiene por qué haber diferencia, porque el resultado debe ser exactamente el mismo.
Pero desde el punto de vista de la legibilidad del código, el udp es mucho mejor que el call, porque nos dice cual fue la intensión de la invocación: cargar la variable &result con lo que devuelve el procedimiento.
Citando el blog Coding Horror (que a su vez cita una frase de un libro):
Programs must be written for people to read, and only incidentally for machines to execute.
PD: la palabra legibilidad existe, me quedaban dudas por eso la busqué en el diccionario de la Real Academia Española...
Mejorando la legibilidad del código II
Muchas veces cuando programamos, mezclamos el código de la función que resuelve un determinado problema con código auxiliar, lo cual entorpece mucho la lectura del código, sobre todo cuando se trata de programas grandes.
Un par de ejemplos...
En GeneXus la función round() recibe el número a redondear y la cantidad de decimales, pero la cantidad de decimales no puede ser una variable, tiene que ser una constante (yo me pregunto, ¿por qué será así?, con GX9u4 al menos es así). Entonces si queremos redondear un valor a una cantidad variable de dígitos decimales, hay que hacerlo "a mano".
El código que usamos habitualmente es como el que sigue:
El problema con esto, es que estamos escribiendo 10 líneas de código que no hacen al problema, y que distraen la atención, ¡cada vez que queremos asignar un importe!. Si esto aparece una sola vez en el programa, entonces no hay problema, pero cuando en un mismo procedimiento aparece 8 veces, tenemos 80 líneas de código innecesarias, casi 2 página en mi monitor...
Además esto tiene otro problema, que el código no es reutilizable... pero ese es tema para otra nota.
El código de arriba se puede escribir mucho más claro, por ejemplo con:
Otro ejemplo.
Hay casos en los cuales tenemos un programa que hace algo, y que además genera un listado o una planilla Excel, que no hace al problema que se quiere resolver, pero que es necesario generar.
Siendo más concreto, tengo un programa que genera un asiento contable, que además crea una planilla Excel con la información que usó para generar el asiento. El programa en cuestión tiene unas 1.200 líneas, y la generación del Excel está mezclada con el programa.
Como tenía que cambiar bastante este programa, lo primero que hice fue sacar la generación del Excel a subrutinas, con lo cual en el código del programa, en vez de quedar 50 o 60 líneas con &excelDoc.Cells(...), quedó una sola línea con do 'Excel: Graba línea'
¿Más claro, no?
Las otras tres subrutinas que cree fueron:
Como comentario adicional, cada vez me gusta más el uso de las subrutinas... Si se usa un nombre realmente descriptivo como en los casos anteriores, entonces mejora muchísimo la legibilidad del código. Es importante usar un nombre adecuado, por ejemplo en el caso anterior no sirve tener rutinas con nombre Excel1, Excel2 y Excel3.
* Publicado por Marcos Crispino en Blog De Marcos Crispino.
Desde el punto de vista del código generado, son casi idénticos. En realidad no tiene por qué haber diferencia, porque el resultado debe ser exactamente el mismo.
Pero desde el punto de vista de la legibilidad del código, el udp es mucho mejor que el call, porque nos dice cual fue la intensión de la invocación: cargar la variable &result con lo que devuelve el procedimiento.
Citando el blog Coding Horror (que a su vez cita una frase de un libro):
Programs must be written for people to read, and only incidentally for machines to execute.
PD: la palabra legibilidad existe, me quedaban dudas por eso la busqué en el diccionario de la Real Academia Española...
Mejorando la legibilidad del código II
Muchas veces cuando programamos, mezclamos el código de la función que resuelve un determinado problema con código auxiliar, lo cual entorpece mucho la lectura del código, sobre todo cuando se trata de programas grandes.
Un par de ejemplos...
En GeneXus la función round() recibe el número a redondear y la cantidad de decimales, pero la cantidad de decimales no puede ser una variable, tiene que ser una constante (yo me pregunto, ¿por qué será así?, con GX9u4 al menos es así). Entonces si queremos redondear un valor a una cantidad variable de dígitos decimales, hay que hacerlo "a mano".
El código que usamos habitualmente es como el que sigue:
Do case |
Además esto tiene otro problema, que el código no es reutilizable... pero ese es tema para otra nota.
El código de arriba se puede escribir mucho más claro, por ejemplo con:
&vLinImpTot = PedPreNet * &PedCntSdo &vLinImpTot = udp(PFRedondeaADigitosN132, &vLinImpTot, &Digitos) |
Otro ejemplo.
Hay casos en los cuales tenemos un programa que hace algo, y que además genera un listado o una planilla Excel, que no hace al problema que se quiere resolver, pero que es necesario generar.
Siendo más concreto, tengo un programa que genera un asiento contable, que además crea una planilla Excel con la información que usó para generar el asiento. El programa en cuestión tiene unas 1.200 líneas, y la generación del Excel está mezclada con el programa.
Como tenía que cambiar bastante este programa, lo primero que hice fue sacar la generación del Excel a subrutinas, con lo cual en el código del programa, en vez de quedar 50 o 60 líneas con &excelDoc.Cells(...), quedó una sola línea con do 'Excel: Graba línea'
¿Más claro, no?
Las otras tres subrutinas que cree fueron:
Sub 'Excel: Crea archivo y genera cabezal' Sub 'Excel: Graba subtotales' Sub 'Excel: Finaliza' |
Como comentario adicional, cada vez me gusta más el uso de las subrutinas... Si se usa un nombre realmente descriptivo como en los casos anteriores, entonces mejora muchísimo la legibilidad del código. Es importante usar un nombre adecuado, por ejemplo en el caso anterior no sirve tener rutinas con nombre Excel1, Excel2 y Excel3.
* Publicado por Marcos Crispino en Blog De Marcos Crispino.