La innovación, nuestra razón de ser
Uno de los principios que he intentado aplicar tanto en el desarrollo de nuestros productos como de los proyectos en los que hemos participado, es el de acercar la tecnología al usuario de forma sencilla. Buscando en todo momento maximizar la funcionalidad sin, por ello, olvidar la excelencia técnica.
Dentro de esta serie de iniciativas voy a contaros como aplicamos conceptos de compiladores y maquinas de pila para simplificar la operación de los administradores de nuestros productos.
En Divisa iT ya contábamos, dentro de nuestra plataforma Proxia®, con mucha experiencia en el desarrollo de sistemas de automatización de formularios. Pero éstos, llegado un punto, y como bien me gusta insistir a mis clientes, no hacen magia, y era necesario arremangarse para obtener el resultado deseado. La pregunta era, ¿se puede dar a esto una vuelta de tuerca adicional? ¿podemos hacer algo más por el usuario?
La respuesta desde el punto de vista del qué hacer, vino de la mano, como muchas veces, del análisis comparativo. Si un niño – mis hijos – eran capaces de manejar Scratch con soltura, ¿por qué no una persona adulta y con cierta iniciativa? Si bien Scratch no era directamente aplicable, si lo era la idea. Lógicamente no íbamos a desarrollar algo de cero – el time-to-market sería excesivo –, así que opté por utilizar Blockly de Google, que nos proporcionaba la base para lo que necesitábamos.
Para los que no lo conozcáis, lo que Blockly nos permite es programar arrastrando bloques, que pueden incluir secuencias de control (si, si no, repeticiones, llamada a funciones, eventos, …), generando un código en un lenguaje de alto nivel (JavaScript entre otros).
El problema venía de la interpretación del resultado de Blockly, lo que queríamos hacer era tanto poder controlar un flujo de aprobación (con o sin bifurcaciones) como simplificar las llamadas al backoffice del cliente.
Para realizar esto, la mejor opción era interpretar este código en servidor, tanto por las implicaciones de seguridad, como por el propio control del flujo de aprobación, sin olvidar que la necesidad de que el código fuera independiente del cliente – caso de aplicaciones nativas desarrolladas en Swift, Kotlin o Java –. Podía haber generado gramáticas complejas en servidor para interpretar el lenguaje de alto nivel (usando ANTLR, por ejemplo, cosa que hemos utilizado en otras ocasiones), pero me parecía matar moscas a cañonazos.
La solución pasó por volver a los principios. Si nos preguntamos qué elementos básicos (pero muy básicos) influyen en una actividad de programación sin duda diremos, la codificación y la compilación. Desde ese punto de vista y abstrayéndolo al caso que nos ocupa
Por tanto lo único que teníamos que hacer era que Blockly hiciera esa compilación, no ya a un lenguaje de alto nivel, ni siquiera a un DSL que hubiéramos definido con una gramática concreta, sino directamente a un pseudo-ensamblador que pudiéramos implementar en una máquina de pila construida ad-hoc. Así pues el primer paso fue incluir un nuevo generador de código en Blockly para generar un código como el que podéis ver en la siguiente figura.
Para los que no lo tengáis tan fresco, ese ensamblador no es sino una serie de instrucciones básicas a ejecutar que son interpretadas por una maquina virtual, que en este caso vamos a crear nosotros. Esas instrucciones pueden incluir desde guarda esta variable, compara el resultado con cero, si el resultado es cierto salta a la instrucción 35, etc. Como podéis ver estas instrucciones no sólo incluyen pasos o secuencias, sino también permiten almacenar el estado del programa en memoria en un momento determinado. La memoria es, en este caso, una pila, puesto que toda la operación de guardar y/o leer datos se realiza mediante un algoritmo LIFO.
El uso de esta maquina de pila no sólo facilita la interpretación del código en servidor, sino que también permite cumplir con otro requisito que teníamos desde el principio y que era el de permitir que la aplicación fuera robusta frente a fallos o caídas del servicio y que permitiera montar esos procesos de aprobación. Tened en cuenta que un proceso de aprobación se caracteriza por:
Como no íbamos a hacer la barbaridad de tener procesos corriendo en el servidor ad-infinitum - en una escucha pasiva o activa - , la solución pasaba por persistir el estado completo de ejecución del programa: la pila, y la información de donde se encontraba el proceso - la línea de la instrucción - . Así combinamos: la máquina de pila, una máquina de estados finita y una persistencia física de datos. ¡Problema resuelto!
Si te interesa lo que hacemos no dudes en aplicar a nuestras ofertas de empleo, no vas a hacer siempre estas cosas, pero que sepas que en Divisa iT sabemos como hacerlas y podemos ayudarnos mutuamente para hacer cosas mucho mejores. ¡Animate!
Los iconos empleados son cortesía de FlatIcon