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
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:
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:
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:
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.
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 |
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.