Ir al contenido principal

Mini-procs: declarando, declarando el output vamos generando

La verdad que, como me suele pasar, no logré un título interesante para el post, así que quedó ese. Preciso una agencia de publicidad que le ponga más gancho a los mismos ;) en fin, vamos al tema.

Creo que la idea de los mini-procs será uno de los factores revolucionarios de la Rocha, es un concepto bastante “removedor” para quienes desarrollamos software hace años y va de la mano de los nuevos tipos de aplicaciones y sobre todo a la “GX’s way” de resolver el problema.

Este no es un documento fuertemente técnico sino que apunta a lo que entiendo como "la raíz conceptual del problema a resolver con los mini-procs". Si no se conceptualiza el problema que se intenta resolver no se entenderán los mini-procs y menos cómo sacar provecho de ellos.


Marco histórico de los “procedures”


Utilizo el término “procedures” en si para diferenciarlo de “procesos” que es un término más amplio y puede entenderse como “proceso de negocios” o “diagrama de actividades” o similares.

Un “procedure” es un objeto Genexus que permite acceder (comando “For Each/EndFor”) y eventualmente actualizar datos (comando New/EndNew o directamente asignando un atributo).

Hace muchos años que trabajo en Genexus y recuerdo que originalmente dichos “procedures” no existían, se tenían las transacciones (ABM interactivo en la base de datos) y los reportes (consultas a la base de datos).

Esto presentaba un problema grave a la hora de hacer algunas cosas “sencillas” como utilizar una tabla se numeradores o más “pesadas” como el cierre de un ejercicio contable.

Recuerdo haber estado desarrollando un Sistema de Control de Stock por esos años y coincidir con la implementación de los “procedures” en Genexus, sin los cuales hubiera sido directamente imposible desarrollar esa solución, al menos hacer 100% con Genexus.

Eran “un reporte con la posibilidad de hacer INSERT y UPDATE en la base de datos”. Aún recuerdo que los comandos debían empeza con “.” (punto) porque lo que no comenzara con punto era considerado “output” del objeto (herencia del editor de texto/código utilizado en ese momento si no recuerdo mal). Luego cambió la sintaxis y solo lo que comenzaba con “:” (dos puntos) era lo que se consideraba “output”. En fin, esa es otra historia.

Volviendo al tema, los objetivos de los “procedures” eran y son:

1. Actualizar, masivamente o no, la base de datos – el “procedure numerador”, el “procedure de cierre de ejercicio”, etc. Eventualmente tener alguna salida “impresa” – a veces se necesita no solo actualizar la información sino “imprimir” algo, por ejemplo, el proceso de “facturación masiva a fin de mes” no solo imprime las facturas sino que calcula tarifas, actualiza información de las mismas, etc.

2. Hacer cálculos complejos – dados algunos parámetros (obtenidos por la regla “parm” o de la base de datos), realizar algunos cálculos y retornar un valor. Digamos que “la implementación de una función”.

Independientemente del objetivo específico de cada proceso, tenían una estructura básica muy similar que era: Input->Proceso->Output.

Creo que esa estructura la vi en “Programación I” y la debe haber visto cualquiera que haya trabajado en informática.

Por ejemplo: se recibe el “mes a facturar” por parámetro (input), se procesan la facturas haciendo los cálculos requeridos, actualizando la información, etc (proceso) y se imprimen (output).

Si bien depende mucho del "procedure" en cuestión, normalmente el “peso” está puesto en el proceso en sí. Es decir, el “input” suele ser sencillo (parm de IN y/o “for each” sobre tablas) y el “output” también (parm de OUT y/o new/updates de tablas y/o output impreso).

Digamos que si no existiera el “For Each” el input de tablas podría ser bastante más complejo, pero en  GX lo tenemos muy facilitado en ese sentido :)

En cualquier caso lo que si es bastante claro es que el “output” ha sido históricamente el menos importante, es una factura impresa o grabada en una base de datos, pero en general era sencillo y por ende dejado de lado, por más que fuera el objetivo en si del proceso.

Otra características de los "procedures" es que son "objetos procedurales" (valga la redundancia), es decir, no hay una declaración de intención en ninguna parte. Digamos que el "for each" en si es la parte más declarativa, pero el "procedure" en su conjunto no. Comparándolo con una las reglas de una transacción la diferencia es bastante obvia.
En general leer las reglas de una transacción da una idea de la "intención" con las mismas, entender la intención de un procedure suele ser bastante más difícil.

Integración


Desde que existen los sistemas existe el desafío de las “integración de sistemas”. He visto muchas soluciones en este sentido, desde “tener una KB consolidada”, hasta “acceder a los datos de otra aplicación vía File Views (predecesores de los Data Views)”.Lo de tener una KB consolidada con toda la información era viable solo si todas las aplicaciones eran GX y habían sido concebidas y desarrolladas para integrarse, de modo que tuvieran un núcleo en común y no se “pisaran” las estructuras básicas entre si.

La integración a nivel de datos vía DataViews tenía la contra de que las tablas cambiaban entonces también hay soluciones de “bandeja de datos” del estilo “dejo los datos en TAL archivo” (txt, base de datos o lo que fuera) y la otra aplicación los toma de ahí. Lo mismo a la inversa.

También existe la integración a nivel de API (no acceder a los datos en si sino vía un programa que es un API “estable”), con el consiguiente problema de “interoperabilidad” entre plataformas (por eso el éxito de los TXT para el intercambio de información ). Aun hoy hay muchos “diskettitos” (no se si son más chicos de 3 y1/2 y por eso le llaman “diskettitos”) que llevan y traen información, incluso en un mundo donde hace años las disketteras son “opcionales” (yo creo que no uso un diskette hace dos o tres años por lo menos y el único que solía tener era el “boot disk”).

En fin, en todo ese universo de integración aparecen mil “optimizaciones” al mismo como: Dataqueues, replicación, aplicación de conversiones de una cosa en otra para que las partes se entiendan, etc, etc. Todo bastante “hand made”.

Buenas, malas o mediocres, estas “soluciones de integración” funcionan sobre una premisa: los consumidores de la información que debo proveer son conocidos y quienes me proveen información son conocidos.

Esa premisa es fundamental porque se podía “negociar” acerca del medio a utilizar, el formato, la frecuencia de actualización, la “estabilidad” de las APIs, etc.

Integración en el mundo de los “servicios”


Creo que es obvio para todo el mundo que esa premisa de “el consumidor de mi información y el proveedor de información que necesito son conocidos” ha caído hace años.

Fundamentalmente del nacimiento de muchos estándares de hecho y de derecho como http, XML, WebServices, RSS, etc, de algún modo el mundo cambió sustancialmente en los últimos años en este sentido.

Basado en esos estándares nacen otros más arriba como SOA, SOE, BPM, SaaS, Mashups applications,  etc.

El otro día discutiendo con un amigo sobre SaaS me decía que no veía su relación entre SaaS y Webservices, pues bien, podríamos decir que SaaS es una manera diferente de ver el negocio (SaaS versus “on-premise software”), pero también acarrea muchos desafíos de arquitectura (“multi-tenant applications” por ejemplo) y entre ellos todo el tema de “integración” se pone más claramente de manifiesto.

En definitiva, estos estándares permiten ser proveedor de “infinitos” y, sobretodo, desconocidos consumidores y ser consumidor de múltiples y, sobretodo, desconocidos proveedores. Ya no es necesario ingresar la cotización de la moneda pues se obtiene de un servicio que está en el web y si ese falla habrá otro que no falle, ya no es necesario recibir el “diskettito” con la información bancaria, la consolidación de las cuentas se puede hacer 100% consumiendo un servicio que la brinda, ya no es necesario llamar a un proveedor de tal materia prima, el pedido se realiza automáticamente a partir que se pasa el umbral mínimo del stock, etc, etc, etc.

En fin, créanlo o no, todo eso está basado en estándares que permiten la integración y donde la información que proveo o consumo es lo medular, mientras que el proceso en si es secundario.

¿Qué ha pasado con los procedures?


Si uno mira los procedures hoy son básicamente los mismos procedures de hace 20 años (tienen un poco menos de edad, pero hagamos números redondos).

El conocido esquema de “Input->Proceso->Output”, creo que priorizando el “proceso” sigue vigente, por lo menos seguro dejando de lado el output.

Ahora, ahí está la raíz del problema: si el mundo cambió sustancialmente y la prioridad es el output porque es lo que permite la integración intra e inter-organizaciones ¿cómo es posible que sigamos utilizando las mismas herramientas del mismo modo?

Cuando veo los procedures, originalmente concebidos con los fines antes mencionados, intentar priorizar el output bajo los estándares antes mencionados realmente me logran confundir, porque no: apenar.

Tengo un amigo que suele decir: “si no entra como tornillo, entrará como clavo”. No he encontrado una frase más exacta para describir un procedure que tiene que retornar un XML relativamente complejo.

Cualquiera que haya trabajado con ellos reconoce que el código no es fácil de desarrollar y mucho menos de entender.

¿Quién no ha intentado escribir un procedure de estos y se ha olvidado de un cerrar un tag recibiendo un “simpático” mensaje de “XML malformed” y Dios sabrá donde está el error?

Igual, no me quiero detener en los detalles técnicos, información al respecto abunda.

Un mundo nuevo requiere innovación.


En definitiva, la “fuerza bruta” suele servir en muchas ocasiones pero algo es seguro: no es escalable :)
Agregando más memoria a un Server puedo “resolver” un “memory leak” pero ¿hasta cuando?

Del mismo modo, puedo programar procedures que retornen un XML, es más, con el advenimiento de los SDTs esto es bastante más sencillo pero ¿hasta donde? ¿con qué esfuerzo?

Ahí es que nacen los mini-procs, si lo fuera a resumir en una frase diría que “ponen como objetivo central lo que es central: el output, lo demás es casi anecdótico”.

Cuando digo que lo ponen como “central” es porque se comienza diciendo “¿Cuál debe ser mi ouput?” y luego describiendo ese output, todo lo demás (input de tablas, proceso, etc) se hará en función de proveer el mismo.

No creo que podamos seguir hablando de “integración” (en todos sus sabores: SOA, Mashups, etc, etc, etc) sin hablar de “mini-procs”.

NOTA: alguno se puede estar preguntando: ¿qué pasa con el input?, bueno, personalmente le tengo fe a la evolución de los Data Providers.

La GX’s way de resolver el problema


Declarativa. Declaro la intención de tener determinado output que es lo sustancial, todo lo demás es “accesorio” e incluso puede variar.

Del mismo modo que en un “for each” no declaro las tablas a navegar sino el grupo de atributos a obtener, en este caso declaro el output e iré estableciendo de donde se obtendrán los inputs que lo satisfagan, eso coyunturalmente terminará siendo, por ejemplo, un “for each” en algún lado y terminará generando, por ejemplo, un XML con esa estructura.

Esto permite varias cosas, creo que la sustancial es mantener el foco en cual es el output, brindando sencillez (por ende productividad) y claridad en el “código” y la intención.

Los estándares son estables.


Eso es totalmente correcto, los estándares son estables, mientras no cambien claro :)

En realidad es totalmente FALSO, los estándares necesitan evolucionar y, por ejemplo, XML evolucionó hacia JSON, ¿quién hablaba de RSS unos años atrás? ¿cómo seguirá la evolución? Nadie lo sabe y talvez algún “predictor” de turno tenga una idea más o menos vaga de cómo será, pero mientras no sea un hecho no existe.

Ahora bien, uno puede consultar al oráculo o directamente resolver el problema de raíz: declarar el output NO significa declarar el formato (XML, JSon, etc) que por opción o imposición tengamos que utilizar en determinado caso, significa declarar una “estructura esencial”.

Nuevamente ese “formato en el cual expreso algo” es anecdótico, ha cambiado y cambiará. Lo que importa es la esencia del output, la estructura del mismo.

¿Esa estructura esencial cambiará?, si, muy probablemente cambie y tengamos que cambiar nuestro “mini-proc” extendiendolo para que incluya tales o cuales “propiedades” y el resto del proceso se adaptará para satisfacerla. Del mismo modo que si preciso agregar un atributo a un for each es solo eso, aunque atrás muchas más acciones tengan lugar.

En resumen


El objetivo de los mini-procs, a mi modo de ver, es proveer una herramienta que permita poner foco en el output, algo que ha sido historicamente dejado de lado y que hoy, en un mundo de SOA, Mashups e integración, tiene fundamental relevancia.

Además es una herramienta “declarativa” que permita la vigencia de esa declaración, independientemente de cómo ese output deba ser expresado en un momento particular de la historia.

Comentarios

  1. Podrias aportar un ejemplo partiendo de una necesidad concreta, en una especie de seudocodigo para acompañar la nota ?

    ResponderBorrar
  2. Gabriel,

    Hay un link al principio a la documentación de mini-procs (http://www.gxopen.com/commwiki/servlet/hwikibypageid?4793) creo que ahi hay ejemplos que dejan más clara la "implementación" en si. Desde el más básico, hasta cosas más complejas.

    Gustavo

    ResponderBorrar

Publicar un comentario

Entradas más populares de este blog

Abrir links con aplicaciones nativas y no el browser (deeplinking)

El problema que tengo con algunas aplicaciones Android/iOS es que cuando recibo un link por algún medio (mail, tweet, etc) al abrirlo me lo abre con el browser, en lugar de abrirlo con una aplicación nativa asociada a ese “contenido”. Por ejemplo, si recibo un link a un tweet espero que lo abra con alguna aplicación de twitter que tenga instalada y no con el browser. De modo análogo si recibo un mail con una nota de prensa de un medio X y tengo la aplicación de ese medio X instalada, espero que el link lo abra con la aplicación nativa y no con el browser. Lo mismo quisiera con mi aplicación de "banking" o cualquiera que tenga instalada y sepa manejar ese "contenido" (link). Los motivos son bastante obvios pero los resumo en: la experiencia de usuario es mucho mejor en la aplicación nativa que en el navegador. Parte importante del tema es que el mismo link sea válido tanto para ver el contenido en el browser como para verlo en la aplicación, porque como prove

¡A la salud de mi KB!

Es bueno, especialmente en "bases de conocimiento" (KB) que han pasado por varias versiones de Genexus, chequear su "estado de salud". En este sentido KBDoctor  es una herramienta que ayuda mucho, principalmente desde el punto de vista del "modelo" Genexus (atributos, calls, definiciones de variables, etc) representado en una KB. También es útil revisar la salud de los archivos que lo soportan. Hasta la 9.0 eran archivos C-tree (los famosos .DAT) que tenían indices (los famosos .IDX) y teníamos en "rebuild -y" que mejoraba esos archivos y sobre todo reconstruía los indices. A partir de la X las KBs se almacenan en MS SQL Server por lo cual la administración de la misma pasó de ser un "file server" a un "database server". En este sentido algo que me ha dado muy buenos resultados es el "CheckKnowledgeBase".

Rocha:Constantes tipo fecha

En la Rocha se soportan constantes del tipo fecha o fecha-hora con formato ANSI/ISO (AAAA-MM-DD HH:MM:SS).  Tecnicamente (Sintáxis): <date>::=    [0-9]{1,4}"/"[0-9]{1,2}"/"[0-9]{1,2} | [0-9]{1,4}"."[0-9]{1,2}"."[0-9]{1,2} | [0-9]{1,4}"-"[0-9]{1,2}"-"[0-9]{1,2} <hms>::=    [0-9]{1,2}[ap] | [0-9]{1,2}":"[0-9]{1,2}[ap]? | [0-9]{1,2}":"[0-9]{1,2}":"[0-9]{1,2}[ap]? <constant> ::=   "#"<date>"#" | "#"<date> <hms>"#" | "#"<hms>"#" Funcionalmente Se pueden utilizar esas constantes en las reglas, eventos, propiedades, etc (todo lugar donde se utilice el parser): Algunos ejemplos básicos: &FechaInicial=#2007-01-01# &FechaHoraInicial=#07-1-1 11:15a# &HoraInicial=#11a# Me parece bueno no tener que escribir funciones (CTOD, TTOC) sobre constantes tipo char para lograr una fecha y mucho mejor aun en