Sugerencias para el lenguaje GeneXus by Marcos Crispino en #GUG Montevideo

Post on 19-Jun-2015

2.547 views 6 download

description

La charla propuesta por Marcos Crispino fue una instancia para reflexionar y aportar sugerencias en torno a GeneXus.

Transcript of Sugerencias para el lenguaje GeneXus by Marcos Crispino en #GUG Montevideo

Sugerencias para mejorar el lenguaje GeneXus

Marcos Crispinohttp://blog.marcoscrispino.commarcos.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 rangeDominio 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 valoresendcase

Comando "do case"

Sugerencia: implementar un comando "elseif"

if &variable = 1    // código para el valor 1 de &variableelseif &otra_variable = 2    // código para el valor 2 de &otra_variableelse    // hago algo para los demás valoresendif

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 valoresendcase

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 = &Dendfor¿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 = &Dwhen duplicate B    // código para manejar el valor duplicado en Bwhen duplicate C, D    // código para manejar duplicados en C, Dendfor

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ónEjemplo:

&esta = Boolean.Falsefor &item in &coleccion    if &item.Campo1 = &Var1 and &item.Campo2 = &Var2        &esta = Boolean.True        exit    endifendfor

SDTs: buscar un elemento en la colecciónSugerencia:

&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ónOtra posibilidad:

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

    &esta = Boolean.True    exitendfor

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 Crispinohttp://blog.marcoscrispino.commarcos.crispino@gmail.com