viernes, 13 de febrero de 2009

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
case &Digitos = 0
    &vLinImpTot = round( PedPreNet * &PedCntSdo , 0 )
case &Digitos = 1
    &vLinImpTot = round( PedPreNet * &PedCntSdo , 1 )
case &Digitos = 2
    &vLinImpTot = round( PedPreNet * &PedCntSdo , 2 )
Otherwise
    &vLinImpTot = PedPreNet * &PedCntSdo
endcase
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:
&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.

3 comentarios:

  1. Una vez en mi trabajo cree un Evento de Usuario que se llamaba TBCargarDatosPlanillaExcelDeReingenieria.Click y todavia me estan tomando el pelo por eso.

    ResponderEliminar
  2. No estoy de acuerdo con el punto de vista del artículo, escribir una función en vez de repetir el mismo código varias veces es algo básico en programación, se llama modularización y se enseña (o debería enseñarse) en los cursos introductorios a la programación. En la UdelaR se enseña en programación 1, si no me equivoco. Por lo que lo veo más como una carencia como programador que como un problema de legibilidad.
    Por otro lado, tener que hacer un case para pasar un parámetro en genexus es realmente tristísimo. Esperemos que lo corrijan en algún momento.
    Saludos!

    ResponderEliminar
  3. Gastón: Estoy (casi) de acuerdo con las dos cosas que decís.

    Pero con respecto al primer punto, la realidad es que se da que encuentro código repetido, y más allá que en su momento fue una carencia del desarrollador, una vez que lo encuentra el siguiente pasa a ser un problema de legibilidad...

    ResponderEliminar