martes, 29 de diciembre de 2009

Buscar un elemento dentro de un SDT en GeneXus

En GeneXus, no hay una forma de buscar un elemento dentro de una colección (SDT), que no sea recorriendo toda la lista. Hay una función IndexOf, pero compara referencias y no el contenido de los elementos.

Ejemplo:
&esta = Boolean.False
for &depUbiItem in &depUbis
    if &depUbiItem.DepId = &DepId and &depUbiItem.CicUbiId = &CicUbiId
        &esta = Boolean.True
        exit
    endif
endfor

Esto no parece ser lo más elegante... No debería necesitar 7 líneas de código para saber si un elemento está en la colección, lo debería poder hacer en una sola línea.

El problema es que dado un SDT, GeneXus no tiene forma de saber cuales son los elementos que quiero comparar. En el ejemplo, estoy comparando DepId y CicUbiId, pero el SDT tiene varios campos más.

Una posibilidad sería poder definirle comportamiento a los SDTs, de forma de poder decirle cual es la función de comparación que tengo que usar. Esta función de comparación se definiría una vez para el SDT, y siempre que se quiera buscar un elemento se haría usando este comparador.

Otra opción que me gustaría más, es poder definir on-line la función de comparación. En C# por ejemplo, usando lambda expressions, quedaría algo así:
bool esta = depUbis.Exists(d => ((d.DepId = depId) && (d.CicUbiId = cicUbiId)));

O escribiendolo como me gustaría verlo en GeneXus:
&esta = &depUbis.Exists(d => d.DepId = &DepId and d.CicUbiId = &CicUbiId)
 Esto se lee "existe un elemento d en la colección &depUbis que cumple que d.DepId = &DepId y d.CicUbiId = &CicUbiId".

Las colecciones en C# definen otras funciones que también sería intereante tener, como ser:
  • First: devuelve el primer elemento que cumple con 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

lunes, 28 de diciembre de 2009

Atributos y controles como parámetro en GeneXus

Capaz que el título no dice mucho, es dificil explicar lo que quiero en una línea...

Todos sabemos que es una buena práctica de programación, reutilizar código siempre que sea posible. En GeneXus X con los data selectors se dio un gran paso, pero hay cosas que me siguen faltando.

Por ejemplo, tengo el siguiente código que borra los datos de tablas referenciadas, cuando borro una determinada entidad (sí, seguro que es más prolijo hacer un Business Component y borrar con eso, pero no es el punto).



¿Se ve el patrón de código repetido? El problema es que no tengo forma de unificar el código en un procedimiento o subrutina, de forma de pasarle solamente el atributo que va en el defined by.

Seguramente no es fácil de implementar, pero sería interesante.

Otro caso donde pasa algo similar, es con los controles en pantalla.

Por ejemplo, recibo unas variables por parámetro, si vienen cargadas las muestro en el form deshabilitadas, y si no las muestro habilitadas.

El código es el siguiente:



Otra vez, creo que es fácil ver el patrón en el código, y otra vez no tengo forma de hacer algo genérico, que reciba dos variables (el parámetro y la variable que tengo en el form), y le aplique la lógica...

Capaz que este caso es más sencillo de implementar que el otro, porque no cambia la forma en que navega el programa.

jueves, 24 de diciembre de 2009

Lo que le falta al Chrome OS

Primero que nada, quiero aclarar que no he usado Chrome OS... lo que sigue es más bien una reflexión.

Y no lo he probado, porque creo que no aporta nada nuevo. Es decir muchas de las cosas que hago con un PC, las podría hacer con aplicaciones Web corriendo en Chrome OS, pero hay una actividad que hoy (creo) no se puede hacer: desarrollar software.

El problema es que mientras que los desarrolladores no se sientan atraidos a la nueva plataforma, no van a surgir desarrollos optimizados para Chromes OS, lo que se transforma en un círculo vicioso porque los usuarios no van a ver el valor de cambiar a un sistema operativo que no les aporta nada nuevo.

Claro que tiene sus ventajas (levanta mucho más rápido que cualquier otro PC, está enfocado a la Web que hoy por hoy es lo que más usan los usuarios, los equipos pueden ser más baratos, etc.), pero todavía está por verse que adopción va a tener.

Creo que en algún momento Google va a tener que liberar un conjunto de herramientas Web para desarrollar software, para que los desarrolladores puedan usar la plataforma a la que estarían apuntando. Tal vez algo como Bespin de Mozilla Labs, aunque seguramente debería ser algo un poco más avanzado, no solo un editor de texto.

Va a ser interesante de ver...

jueves, 10 de diciembre de 2009

Great programming quotes

Leo en el blog de Sebastián Gomez sobre great programming quotes, de una pregunta en Stack Overflow.

A mi también me pareció interesante para compartir :), así que acá van algunas de las que me gustaron:
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. (Rick Osborne)
Some people, when confronted with a problem, think "I know, I’ll use regular expressions." Now they have two problems.
In order to understand recursion, one must first understand recursion (un clásico)
It works on my machine.
If debugging is the process of removing software bugs, then programming must be the process of putting them in. (Edsger Dijkstra, otro clásico...)
Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. (Antoine de Saint Exupéry, no creo que fuera programador, pero igual cuenta...)
Debuggers don't remove bugs. They only show them in slow motion.
Never trust a programmer in a suit.
Measuring programming progress by lines of code is like measuring aircraft building progress by weight. (Bill Gates)

martes, 8 de diciembre de 2009

Compilación GeneXus 9.0/Java: problemas de performance

En una KB GeneXus 9.0 grande (en nuestro caso unos 8.100 objetos), ubicada en la red y de uso compartido, la compilación puede tener algunos serios problemas de performance.

Existen dos formas de compilar, y las dos presentan dificultades:
  • usando NMake, la compilación es rápida, pero demora mucho cuando tiene que generar algún .mak porque cambió el árbol de llamadas
  • usando GXJMake, la generación es rápida, pero la compilación nos demoraba en algunos casos más de 2 minutos.
En particular el GXJMake, tiene un algoritmo que dista mucho de ser óptimo. Enrique estuvo analizando por que demoraba tanto, y llegó a que lo que hace es recorrer todo el árbol de llamadas (lo lee de los archivos .ari) y por cada objeto, compara la fecha del .java con la del .class. El tema es que lo hace una vez por cada aparición del objeto en el árbol.

En el caso que analizamos, había un objeto que estaba comparando las fechas más de 1.400 veces... ¡Y ni siquiera era el objeto que había modificado!

Una demora de 2 minutos como teníamos, para compilar un solo objeto modificado baja muchísimo la productividad, no solo por la demora en sí de la compilación, sino también porque la persona que tiene que esperar esos dos minutos casi seguro que se distrae y se pone a hacer alguna otra cosa.

Este problema es conocido, y está reportado en al menos dos SACs:
La solución, fue desarrollar nuestro propio programa de Make: COJMake.

Este programa ejecuta en el servidor donde está ubicada la KB, y queda monitoreando si hay algún .java modificado. Cuando detecta un .java modificado, lo manda a compilar(1). El programa graba un log que permite monitorear lo que está haciendo y detectar si se produjo algún error en la compilación.

Con esto, el programa ni siquiera necesita que se termine de generar para poder empezar a compilar. Si se están generando varios objetos, a medida que se va terminando de generar uno ya queda listo para compilar.

El efecto es que ahora la compilación es prácticamente instantanea. En condiciones normales (cuando se manda a generar unos pocos objetos), cuando se termina de generar demora menos de dos segundos en terminar de compilar.

(1) En realidad lo que hace es ir guardando los archivos modificados en una cola, y hay otro hilo que va compilando lo que aparece en la cola. Esto permite limitar el número de procesos que se largan a compilar, sin perder ningún archivo en el medio.

martes, 1 de diciembre de 2009

Primer Pattern generado por el Automatic Pattern Generator

Es un gusto anunciar que el Automatic Pattern Generator ya está generando su primer Pattern.

Claro, por el momento no es demasiado útil, porque genera un solo Pattern, que es fijo, pero al menos nos permite saber que vamos por el buen camino.

Todavía queda mucho por hacer, a quien le interese participar del proyecto, será bienvenido.

El pattern que genera consiste de un solo procedimiento que devuelve el valor de un objeto.

En este momento no estamos liberando binarios, porque no tiene demasiado sentido. Si alguien quiere ver el código del proyecto, o bajarlo, o hacer algún aporte, lo puede hacer en el sitio de Assembla.

Dejo algunas fotos de pantalla de la aplicación.


Figura 1: Acceso a la aplicación

Figura 2: Proyecto Visual Studio Generado


Figura 3: Proyecto Visual Studio



Figura 4: Aplicando el Pattern a un atributo y las propiedades


Figura 5: Procedure generado