Notícias

Melhorando a legalidade do código com o GeneXus no blog de Marcos Crispino

No seguinte post comparam-se as invocações com call ou udp no GeneXus.

Melhorando a legibilidade do código

No GeneXus, quando invocamos um objeto temos a possibilidade de fazê-lo com um call ou com um udp.

Suponhamos que temos um procedimento que realiza alguma operação e devolve um valor. Só a via de exemplo, suponhamos que temos um procedimento Soma que recebe dois valores, &a e &b, e devolve sua soma.

Qual é a diferença entre invocar o tal procedimento com call ou com udp? As invocações seriam assim
 
call(PSuma, &a, &b, &result)
o
&result = udp(PSuma, &a, &b)

Qual das duas é melhor?

Do ponto de vista do código gerado, são quase idênticos. Na realidade, não tem por que haver diferença, porque o resultado deve ser exatamente o mesmo.

Mas do ponto de vista da legalidade do código, o udp é muito melhor que o call, porque nos diz qual foi a intenção da invocação: carregar a variável &result com o que devolve o procedimento.

Citando o blog Coding Horror (que por sua vez cita uma frase de um livro):

"Programs must be written for people to read, and only incidentally for machines to execute".

PD: a palavra legalidade existe, eu tinha dúvidas, por isso procurei no dicionário da Real Academia Espanhola...


Melhorando a legibilidade do código II

Muitas vezes quando programamos, misturamos o código da função que resolve um determinado problema com código auxiliar, o que atrapalha muito a leitura do código, sobretudo no caso de programas grandes.

Um par de exemplos...

No GeneXus a função round() recebe o número a arredondar e a quantidade de decimais, mas a quantidade de decimais não pode ser uma variável, tem que ser uma constante (eu me pergunto, por que será assim?, com GX9u4 ao menos é assim). Então se quisermos arredondar um valor a uma quantidade variável de dígitos decimais, deverá ser feito "na mão".

O código que usamos habitualmente é como o que segue:
 

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

 
O problema com isto, é que estamos escrevendo 10 linhas de código que não fazem ao problema, e que distraem a atenção, cada vez que queremos atribuir uma importância!. Se isto aparecer uma vez apenas no programa, então não há problema, mas quando num mesmo procedimento aparece 8 vezes, temos 80 linhas de código desnecessárias, quase 2 página no meu monitor...

Além disso, há outro problema, que o código não é reutilizável... mas esse assunto fica para outra matéria.

O código precedente pode se escrever muito mais claro, por exemplo com:

&vLinImpTot = PedPreNet * &PedCntSdo
&vLinImpTot = udp(PFRedondeaADigitosN132, &vLinImpTot, &Digitos)

Outro exemplo.

Há casos nos quais temos um programa que faz algo, e que além disso gera uma lista ou um formulário Excel, independendo do problema que quero resolver, mas que é necessário gerar.

Sendo mais concreto, tenho um programa que gera um registro contábil, que além disso cria um formulário Excel com a informação que usou para gerar o registro. O programa em questão tem 1.200 linhas, e a geração do Excel está misturada ao programa.

Como tinha que mudar bastante este programa, o primeiro que fiz foi tirar a geração do Excel a subrotinas, com o qual no código do programa, em vez de ficar 50 ou 60 linhas com&excelDoc.Cells(...), ficou apenas uma linha com
do 'Excel: Graba línea'
Mais claro, não é?

As outras três subrotinas que criei foram:

Sub 'Excel: Crea archivo y genera cabezal'
Sub 'Excel: Graba subtotales'
Sub 'Excel: Finaliza'

Como comentário adicional, cada vez eu gosto mais do uso das subrotinas... Se for usado um nome realmente descritivo como nos casos anteriores, então melhora muitíssimo a legalidade do código. É importante usar um nome adequado, por exemplo no caso anterior não serve ter rotinas com nome Excel1, Excel2 e Excel3.


* Publicado por Marcos Crispino no Blog De Marcos Crispino.