Está en la página 1de 25

Sugerencias para mejorar el

lenguaje GeneXus

Marcos Crispino
http://blog.marcoscrispino.com
marcos.crispino@gmail.com
Descargo de responsabilidad
(disclaimer)
• Son sugerencias, no hay garantía Artech las vaya a tener
en cuenta.
• Ideas tomadas (en su mayoría) de otros lenguajes de
programación.
• Publicadas originalmente en
http://blog.marcoscrispino.com/search/label/sugerencias
Bloques de reglas en transacciones

Es común tener conjuntos de reglas relacionadas.

Ejemplo:
 
&valor = udp(MyProc)
  if SomeAttribute = 1 on AfterValidate;
error('&valor cannot be empty') if &valor.IsEmpty()
     and SomeAttribute = 1 on AfterValidate;
Bloques de reglas en transacciones

Sugerencia:
 
{
&valor = udp(MyProc);
error('&valor cannot be empty') if &valor.IsEmpty();
}
if SomeAttribute = 1 on AfterValidate;
Valor "empty" para atributos con value
range
Dominio ESTADO con valores {'ING', 'ABI', 'CER'}

Atributo AttEstado basado en dominio ESTADO

AttEstado.SetEmpty() vale '' (el string vacío)

Debería valer alguno de los valores válidos para el dominio.


Mensajes y formato de strings
Para dar formato a un string:
 
Format('El pedido número %1 fue confirmado', 
       PedidoId.ToString())
 
Hoy, para mostrar un mensaje con formato:

msg( Format('El pedido número %1 fue confirmado', 


            PedidoId.ToString()) )
 
Sugerencia: combinar las funciones msg() y error() con la
función Format().
msg('El pedido número %1 fue confirmado', 
    PedidoId.ToString())
Comando "do case"

Las condiciones son independientes. El siguiente ejemplo es


válido:

do case
    case &variable = 1
        // código para el valor 1 de &variable
    case &otra_variable = 2
        // código para el valor 2 de &otra_variable
    otherwise
        // hago algo para los demás valores
endcase
Comando "do case"

Sugerencia: implementar un comando "elseif"

if &variable = 1
    // código para el valor 1 de &variable
elseif &otra_variable = 2
    // código para el valor 2 de &otra_variable
else
    // hago algo para los demás valores
endif
Comando "do case"

Sugerencia: cambiar el comando "do case" para que se


comporte con el "switch" de C# y Java

do case (&variable)
    case 1
        // código para el valor 1 de &variable
    case 2
        // código para el valor 2 de &variable
    otherwise
        // hago algo para los demás valores
endcase
When duplicate para índices unique
Se tiene una tabla con campos [A, B, C, D] con los siguientes
índices:
• primary key [A]
• índices unique [B] y [C, D]
 
Se tiene un for each que actualiza la tabla:
for each
    where A = &A
    B = &B
    C = &C
    D = &D
endfor
¿Qué pasa si falla por índice duplicado? Hoy da un warning
"spc0070: No When duplicate code found to handle possible
duplicate condition when updating [Atributo]"
When duplicate para índices unique

Sugerencia:

for each
    where A = &A
 
    B = &B
    C = &C
    D = &D
when duplicate B
    // código para manejar el valor duplicado en B
when duplicate C, D
    // código para manejar duplicados en C, D
endfor
Parámetros opcionales

Cuando se agrega un nuevo parámetro a un objeto, hay que


cambiar todos los llamadores.

Sugerencia: parámetros opcionales

Ejemplo:

parm(in:&par1, in:&par2 = 0);

Invocación:

call(MiObjeto, &valor1, &valor2)


call(MiObjeto, &valor1) //equivalente a 
                        //call(MiObjeto, &valor1, 0)
Parámetros nominados

Los parámetros en GeneXus son posicionales.

parm(in:&par1, in:&par2, in:&par3);

call(MiObjeto, &val1, &val2, &val3)

Entonces:
• &par1 = &val1
• &par2 = &val2
• &par3 = &val3
Parámetros nominados

Sugerencia: poder asignar un nombre a cada uno de los


parámetros para poder invocarlos en cualquier orden.
 
parm(in:&par1, in:&par2=1, in:&par3=0);

call(MiObjeto, &val1, @par3 = &val3)


 
Entonces:
• &par1 = &val1
• &par2 = 1 (valor por defecto en la regla parm)
• &par3 = &val3
Objetos que devuelven más de un valor

Para objetos que devuelven un solo valor:


 
&valor = MiObjeto.udp(...)
 
o
 
MiObjeto.call(..., &valor)

Se lee mejor el udp, porque deja claro que la intensión es


cargar el valor en la variable.

¿Y para objetos que devuelven varios valores?


Objetos que devuelven más de un valor

Para objetos que devuelven más de un valor, la única


alternativa es un call:
 
MiObjeto.call(..., &valor1, &valor2)
 
Sugerencia:

&valor1, &valor2 = MiObjeto.udp(...)

con regla parm:

parm(in:..., out:&valor1, out:&valor2);


Subrutinas con parámetros

Stubs, agregados en GeneXus X Ev1 U2.


Ver: http://wiki.gxtechnical.com/commwiki/servlet/hwikibypageid?13516

Solo disponibles para web services.

Ejemplo:
 
Stub FirstMethod(&parm1, &parm2)
    &parm1 = 1
    &parm2 = 'HOLA' 
EndStub

Sugerencia: implementar los stubs para todos los objetos


 
Pasaje de controles por parámetro

Ejemplo:

Sugerencia: poder hacerlo en una subrutina con parámetros.


Herencia entre objetos

Hoy existen los styles que definen herencia al momento de


crear el objeto.
 
Se copia el código al objeto nuevo y hay que mantenerlo en los
dos lugares.

Ejemplo: pattern WorkWith => todos los objetos tienen el


código de paginado.
 
Sugerencia: poder definir herencia y que se herede el
comportamiento.
Definición dinámica de variables

En GeneXus hay que definir todas las variables que se van a


usar.

En las últimas versiones ha mejorado la inferencia de tipos


para las variables no definidas.
 
Hay lenguajes para los cuales no ese necesario saber el tipo
de la variable (de los que genera GeneXus: Ruby)

Sugerencia: que no sea necesario declarar las variables, que


siempre se infiera el tipo.
SDTs: buscar un elemento en la
colección
Ejemplo:

&esta = Boolean.False
for &item in &coleccion
    if &item.Campo1 = &Var1 and &item.Campo2 = &Var2
        &esta = Boolean.True
        exit
    endif
endfor
SDTs: buscar un elemento en la
colección
Sugerencia:

&esta = &coleccion.Exists(d => d.Campo1 = &Var1


                           and d.Campo2 = &Var2)

Se lee como "existe un elemento d en la colección que cumple


que d.Campo1 = &Var1 y d.Campo2 = &Var2"
 
Otras funciones:
• First: devuelve el primer elemento que cumple la condición
• Where: devuelve otra colección con los elementos que
cumplen con la condición
• Select: permite hacer una proyección, devuelve otra
colección pero de otro tipo
SDTs: buscar un elemento en la
colección
Otra posibilidad:

&esta = Boolean.False
for &item in &coleccion
    where &item.Campo1 = &Var1
    where &item.Campo2 = &Var2

    &esta = Boolean.True


    exit
endfor
SDTs: algoritmos

Problema: no hay posibilidad de reutilizar algoritmos entre


distintos SDTs

Sugerencia: Poder tener algoritmos genéricos.

Se necesita:
• SDTCollection, genérico, que se pueda usar en lugar de
cualquier SDT que sea colección
• SDTItem, genérico, que se pueda usar en lugar de cualquier
SDT de un nivel, por ej. items de SDTCollection
• Acceder dinámicamente a los elementos del SDT
¡Gracias!

Marcos Crispino
http://blog.marcoscrispino.com
marcos.crispino@gmail.com

También podría gustarte