Sobre la generación de código

Quisiera hoy tratar un tema, que de alguna manera lo trato en cada momento en que tengo oportunidad. No es un tema esencial, quizás, dentro del desarrollo de código, pero me parece importante tratarlo, por un tema digamos táctico: hoy por hoy, dada la situación de una serie de tecnologías, “frameworks” y estilos arquitectónicos, pienso que es indispensable estar advertido de este tema. Me refiero a la generación de código. Recorramos una introducción, que nos ponga en perspectiva, que nos muestre algunas causas de la situación actual, y que apoyen la necesidad de la generación de código.

Antes alguna aclaración: es un tema que me importa. Déjenme entonces, revolcarme en la explicación, detenerme en ejemplos y aclaraciones, pasar de un tópico a otro, enumerar detalles y volver al tema principal, divertirme con alguna chanza, referirme a alguna experiencia personal olvidable, o ponerme serio en alguna frase. Y si en alguna parte parezco merecer la internación en instituto mental, y el chaleco de fuerza, les recuerdo que hasta ahora, no lastimé a nadie, y estoy tomando la medicación diaria…. 😉

No sé si podré transmitir todo lo que quiero expresar. Ludwig Wittgenstein escribió, en una introducción a su Tractatus Lógico-Philosophicus, alguna frase como “Lograría su cometido si complaciera aunque sólo sea a un lector que lo comprenda”. Espero no ser tan oscuro como el joven Ludwig, y que algo de lo que escriba se entienda y sirva a alguien.

El tema me importa: espero que se note.

Todo cambia

Recuerdo mis primeros pasos en el desarrollo de software. Tuve que desde perforar tarjetas, graboverificar datos, hasta trabajar con ensamblador de un venerable IBM 360, o un RPG que apenas llegaba a RPG II. Decenas de líneas de código en DATA DIVISION fueron escritas en planillas de programación. Tuve que escribir incomprensibles comandos de Job Control Languages, para hacer que el más mínimo programa pudiera ejecutar. Luego aparecieron por aquí, en mi pais, Argentina, los mini computadores, cada uno con su propio sistema operativo, y sus propios lenguajes y herramientas. Solo con los años, dejé las tarjetas perforadas, por un teclado en una máquina personal. Tuve que escribir en varias variantes de COBOL, en Fortran, en Algol, y hasta en APL (algo que no lo deseo a nadie, ni siquiera a un fanático de Haskell). Asistí al despertar del CP/M, su versión en red, un primer IBM PC, un Xenix de Microsoft, y varios compiladores C. Trabajé con Turbo Pascal, con Turbo C, y con un DBase que apenas abría dos tablas a la vez. Apareció un día una Lisa de Apple, así como al tiempo una Mac, algo llamado mouse, Microsoft contesta con Windows, y …. Puedo seguir un par de párrafos más. Lo que quiero transmitir, más que descubrir ante Uds que nací en el milenio pasado, es destacar, llamar la atención sobre un tema: la tecnología cambia. Si alguien piensa que la tecnología que tiene ahora entre manos, será “the ultimate solution”, me temo que tengo que decirle: mentira. Todo cambia. Podemos discutir las razones: la evolución de la tecnología, la innovación que empujan los nuevos jugadores, el avance en los requerimientos de los propios clientes, y demás. Pero la realidad es una: todo cambia.

La complejidad

Una vez asentado ese hecho (no una opinión, no una visión relativa, no una teoría, sino un hecho), pasemos a otro. A medida que aparecen nuevas tecnologías, requerimientos (por ejemplo, ya no hay solo ventanas gráficas, tenemos páginas web, otras presentaciones, texto a voz, pequeños dispositivos….), y formas de hacer sistemas, vemos que todo conspira para que cada sistema que encaremos, sea cada vez más complejo, o por lo menos, más largo y grande de construir. Ya es raro encontrar un sistema que pueda desarrollar un programador en solitario: cualquier sistema no trivial implica un equipo de trabajo, y el diseño, creación, ensamble, prueba de multitud de artefactos. Ya no es un simple formulario en Clipper: cada sistema implica parva de elementos a manejar, construir, relacionar.

Podríamos discutir si esto lo llamamos complejidad, o simplemente largura. Pero de alguna forma, Dorothy, ya no estamos más en Kansas: la creación de software, se complicó.

No somos vulcanos

¿Recuerdan al Señor Spock, de Viaje a las Estrellas? Como vulcano, podía analizar todo, y manejar ingentes cantidades de información, y seguir con la razón hacia adelante, resolviendo todo problema. No somos vulcanos. Mientras un vulcano, me imagino, puede escribir un sistema completo como un todo, nosotros, como humanos, no podemos “manejar” más de ocho o nueve temas al mismo tiempo. La construcción de software es una actividad humana que implica la mayor cantidad de niveles de detalle: tenemos que ser capaces de ver la arquitectura general del sistema, hasta estar en el detalle del último procedimiento almacenado, o la serialización de un mensaje en forma eficiente para transportar en un servicio web. Esa en la razón de la aparición de arquitectura, patrones y otras soluciones: son soluciones que ayudan a superar nuestras limitaciones humanas. Un sistema con capas o sin capas, es de igual de complejo para un procesador. Es por y para nosotros, los humanos, que los sistemas se organizan, se parten, se analizan y diseñan. Es por nosotros, que la arquitectura de software apela al viejo “divide y vencerás”. Es por nosotros, que tenemos patrones. Es por nosotros, que adoptamos en programación estructurada la abolición del GOTO (noten que cualquier procesador tiene GOTO, y que todo ejecutable, tiene miles de GOTO: la desaparición de esta “infame” construcción ocurrió a nivel humano, a nivel de los lenguajes que manejamos, los procesadores ni se enteraron del problema).

Cada año que pasa, es más evidente que necesitamos ayuda para construcción de software. No podemos solos.

Software que genera software

En los ochenta, me comentaron una idea: cuando uno arma una herramienta de software, sería bueno que nos ayude a generar más software. No solamente armar herramientas para otros, sino que de alguna forma, cada esfuerzo que hagamos en armar algo, nos ayude, potencie, las capacidades de seguir haciendo. Esto permite que cada tiempo que invertimos, de alguna forma nos vuelva en provecho a nuestro trabajo, y por otra, ejercitar el “dog fooding”: comer la comida del perro, usar las propias herramientas, para apreciar las ventajas y limitaciones de lo que producimos.

Ese consejo lo comencé a aplicar en mis primeros programas en Lattice C, para PC. Necesitaba escribir rutinas que pasaban de una estructura de datos a un sistema de archivo indexado que había armado en un venerable assembler. No quieran imaginar la cantidad de código que eso implicaba. Luego, necesité pantallas de ingreso de datos, que manejaran el cursor, posicionamiento en una consola de texto, ingreso de campos y demás. Armé una librería de ingreso y manejo de campos. Pero igual cada pantalla era gran cantidad de código. Entonces, recordando el consejo del párrafo anterior, se armó un generador ese código en C. El propio generador estaba escrito en C. Epifanía: la creación de gran parte de un sistema, que era un trabajo tedioso, lleno de probables errores, quedó reducida a minutos.

Algunos de Uds lo habrán experimentado: descubrir algo que nos ayuda enormemente en el trabajo de cada día. Pero ¿cuál era el problema de esa solución? Solo funcionaba para lo que yo necesitaba. Si quería generar otra cosa, tenía que cambiar mucho del código original. Igualmente, con un grupo, pasamos la librería original a Xenix, y notablemente, siguió produciendo código para ese sistema operativo.

Pero la tecnología cambiaba. Llegó un momento, en que era más fácil usar las nuevas IDEs (entornos de desarrollo), que generar el código de esa forma. Pero siempre me quedó en la cabecita, la idea de volver a esa herramienta.

Pero destaquemos algo: la idea de software generando software, no es nueva. Es una idea que aplicamos cada vez que ejecutamos un compilador. Veamos el esquema: escribimos nuestros programas en un lenguaje de nivel más alto que el de la máquina. Pero luego, no vamos pasando de ese lenguaje a binario a mano: no estamos generando los bits (que de eso se compone un ejecuble) manualmente en un archivo. No señor. Apelamos a una herramienta.

Creando sistemas con tecnologías

Si Uds. trabajaron muchos años en alguna tecnología (llámese Clipper, Visual Fox, Visual Basic, Java o .NET), habrán llegado al punto de ser “proficient”, de ser capaces de armar sistemas no triviales, manejando sin titubear cada detalle de la tecnología que eligieron. Claro, esa capacidad lleva su tiempo adquirirla. Pero habrán resuelto cómo armar los clásicos ABMs (altas, bajas y modificaciones), accesos a bases de datos, reportes, presentación de menúes, login de usuario y otros. Así hacíamos el sistema S1, luego el S2, y cuando nos encargan el sistema S3, tomamos el S2 como base, y lo vamos cambiando, para no generar el S3 desde el principio.

Eso que hicimos por años se puede resumir:

– Dada una tecnología, la vamos conociendo (aprendiendo cada propiedad de cada control en Visual Basic, o cada método de la API de ADO, DAO, JDBC o lo que nos venga…)

– Dado los sistemas que nos toca construir, vamos solucionando los distintos elementos (cómo acceder a datos, cómo ingresar una entidad, dónde colocar las validaciones…)

– Cuando tenemos un nuevo sistema, nos basamos en lo que ya construímos

Frameworks y librerías

Próximo paso que algunos dimos: luego de haber resuelto los puntos del párrafo anterior, se nos ocurre:

– Armar una librería de clases, que resuelvan lo que hacemos repetitivamente en cada sistema

– O adoptamos algún framework, ya sea de Visual Fox, el de Lothka para Visual Basic, ya sea las recomendaciones de Sun para un J2EE, o Struts, o Spring, o cualquier otro, que alguien haya hecho, para solucionar algunos temas que no queremos armar nosotros.

Pero armar una librería de clases es trabajoso. Y cuando finalmente la conseguimos, cambia la tecnología. Ejemplo: durante años, aprendimos cómo trabajar con Visual Fox. Luego, armamos la librería de clases que nos va a solucionar todo lo que hagamos de ahora en más con ese tecnología. Luego, la realidad se ríe, y aparece la web, Java, multiplataforma, .NET y todo lo demás, y nuestra inversión en la librería, bien, pueden imaginar donde podemos ponerla.

No vamos mejor si adoptamos una librería de otra gente. Al principio, la librería parece maravillosa. Pero al tiempo, no soluciona todo. Y cuando cambia la tecnología, resulta que la librería ya no es soportada. De nuevo, a empezar desde cero, o casi cero.

Arquitectura y patrones

Por lo menos, alguien piensa en cómo hacer sistemas: en los estilos arquitectónicos, en descubrir patrones (soluciones a problemas, que se pueden aplicar en distintos contextos) y demás. Estudiamos esos conceptos, ilusionados por encontrar la “silver bullet”, la bala de plata que mate todos los vampiros que amenazan todo nuestro esfuerzo de creación de software.

Pero si examinan cualquiera de esos principios, implican algo: un montón de trabajo. La necesidad de partir los sistemas (nacidos de la complejidad, de nuestras limitaciones como humanos), hacen que cada trabajo que encaremos, implique la generación de multitud de elementos: desde una capa de presentación, hasta una capa de datos, desde una fachada de servicio, hasta un gateway de grabación de entidades, desde una service interface tecnológica, basada en servicios web, hasta conversores de entidades a mensajes y viceversa.

De nuevo, tenemos soluciones, pero mucho trabajo.

Look ma, no code

Otra solución intentada, es generar pantallas, páginas, funcionalidad en “runtime”, en ejecución. Cansados de las mismas páginas y menúes, y otros elementos, decidimos poner cómo es el formulario y qué tabla actualizar, en metadata. Esta metadata puede estar en XML on en una base de datos, o donde decidamos.

Pero es muy dificil producir un sistema que contemple todo. Sólo algunas pantallas se podrán armar dinámicamente en ejecución. Y dependiendo de la tecnología, habrá que aprender y probar miles de detalles de reflection, creación dinámica de controles, y más. Y cuando al final terminamos de hacer algo potable en ASP, aparece ASP.NET 1.x. Y cuando finalmente creamos controles con ASP.NET 1.x, aparecen master pages y otros controles, en ASP.NET 2.x. Lo mismo si creamos controles “on the fly” para JSP, y luego aparece JSF.

No es una solución que me desagrade, pero notemos que implica de nuevo, una montaña de trabajo, que puede quedar obsoleta en cualquier momento.

Aprendiendo, aprendiendo

Ya sea que pasamos de Visual Fox a .NET, ya sea que conocemos .NET pero queremos aprender conceptos de arquitectura, ya sea conocemos arquitectura, pero queremos manejar un framework como NHibernate o Struts, ya sea conocemos EJB y queremos aprender EJB3, todos esas necesidades de aprendizaje, o la mayoría, son causadas por lo que vimos hasta acá: el cambio permanente, el aumento de la complejidad, y la necesidad de seguir creando software que esté a la altura de lo que los demás están construyendo.

Yo dicto cerca de una docena de clases por semana, de temas tan diversos como PHP, PHP5, patrones, estilos arquitectónicos, Java, JSP, Struts, Spring, Hibernate, EJB2, Jboss, Tomcat, JSF, .NET, Ajax, Windows Workflow Foundation, y me falta abarcar corte y confección y estamos hechos. Veo llegar asistentes a los cursos, y trato de convencerlos que el curso no es del tema que dice el título del curso: no es aprender un tema, que dentro de seis meses va a cambiar. Trato (no siempre lo consigo, debido a limitaciones de mi expresión), de hacer ver que todos esos temas, son tecnologías para resolver problemas. Y trato de advertir, percatar, cuáles son los problemas, y las causas de que tengamos esos problemas. Trato de transmitir, que si vienen a un curso C1, y no ven más allá del tema, dentro de seis meses van a venir al curso C2, que será una simple actualización del anterior, con las mismas esperanzas que albergaban al estudiar C1. Trato de convencerlos de que no vengan más a otro curso: que cada tecnología pasa, lo importante está en otro lado.

Quisiera que cada asistente viera, entonces, más allá del tema circunstancial del curso. Aprender una tecnología, sin pensar más allá, es casi una pérdida de tiempo.

Todos mis cursos, son iguales: no trato de enseñar el tema, sino algo más, algo que trasciende el tema que sirve de excusa al curso. Espero que este “post” ayude a poner en claro algunos puntos que trato de transmitir. También, me sirve para poner en claro mis propias ideas, y, algo que quizás no se dan cuenta, me permite explayarme, regocijarme, sin necesidad de hablar durante horas (ya estoy viejito, me cansa hablar y hablar, disculpen y tengan piedad…;-)

Cabecitas, y más cabecitas

De vez en cuando, aparezco en alguna consultar. El año pasado, me tocó visitar un piso lleno de gente, con computadoras personales en cada escritorio: todos desarrollando. El piso era inmenso, no había paredes, y veía a todo el mundo inclinado sobre sus teclados y pantallas. Sólo se veían las cabecitas.

Pero al acercarme, a ver qué hacía cada grupo, encontré lo que temía: varios estaban generando artefactos, que bien podrían delegarse a que un sistema los genere: cantidad de código repetitivo, que bien podría ser generado automáticamente.

No sé cómo será en su pais. Acá en Argentina, hay cantidad de grupos de desarrollo que necesitan programadores Java. Estoy convencido que la necesidad de esos programadores, es debido a la escasa productividad de muchas herramientas de desarrollo de Java. Un Eclipse pelado, no es un Visual Studio. Y en Java, hay multitud de subtecnologías para elegir, cada una con su propia complejidad. Vayan sino a ver un archivo de configuración de Struts o Struts2, un mapeo del Hibernate, o un archivo de configuración de Spring, o un ejb-jar de Enterprise Java Beans. Se los regalo: son obra del diablo. Claro, hay plugins, y demás utilitarios para generar algo de eso. Cada uno trabaja a su manera, sin colaborar con lo demás que nos toque.

Creo que mucho de esa fuerza de programación, se podría aprovechar de forma más eficiente. Creo que a veces, programamos, de la misma forma que cosechábamos hace un siglo el trigo: llamábamos a una multitud de gente, le dábamos una hoz a cada uno, y a trabajar. Hoy una cosechadora hace el mismo trabajo. Recordemos alguna historia de las fábricas japonesas: cuando se automatizó gran parte de la línea de producción, ¿hubo despidos? No, se utilizó la gente, no para apretar tornillos, sino para controlar la calidad, y encargarse de las tareas que no podía realizar un simple robot.

Herramientas y agentes

J.P.Plauger, mítico programador, creador de compiladores, empresas y libros, me llamó la atención, en una artículo suyo de hace ya más de una década, sobre algo que pasó en la historia humana: por un lado, aparecieron herramientas, cosas que usamos, para hacer lo que queremos hacer, pero de forma más fácil. Pero también aparecieron en su tiempo, los agentes: otros organismos que hacen ellos, lo que no queremos hacer nosotros. Desde animales de carga, hasta, me temo, esclavos humanos.

Hoy, en desarrollo de software, tenemos muchas herramientas. Pero aún la mejor IDE, nos obliga a sentarnos enfrente, y armar las ventanas arrastrando de a uno los botones. ¿No se podrá delegar gran parte de ese trabajo en un agente de software? Un generador de código puede ser más que un wizard, o un activo de una “software factory” de la IDE de moda: puede ser un sistema experto, que tome decisiones, que dado un modelo, llegue más allá de lo automático. Tal vez, este es el aspecto más oscuro de explicar ahora en este “post”. Recuerden: podemos conseguir más que una herramiente, un agente. Algo más sobre “inteligencia artificial” más abajo.

Domain Specific Languages

Vimos que una estrategia, como la empleada en la compilación, implica:

– un lenguaje de alto nivel

– una herramienta que pase de ese lenguaje a algo que entienda la máquina

Hace un tiempo, aparece el concepto de DSL (Domain Specific Languages). En lugar de usar un lenguaje que modele en alto nivel algo genérico (como algunos pretenden con UML), se pueden inventar lenguajes que modelen, expresen, las necesidades que tenemos y que haya herramientas que, interpretando, procesando esos modelos expresados en un lenguaje específicamente orientado al dominio a solucionar, vayan generando el artefacto final necesario para pasar del modelo de alto nivel a algo más cercano a la máquina.

Alguien puede pensar que nunca usó un DSL. Creo que podría estar equivocado. Veamos un par de casos. Tomemos el lenguaje SQL. Un comando como

select * from employee

nos soluciona un conjunto de detalles, que antes, con un sistema indexado (un ISAM, un venerable Btrieve, y otros), implicaba programar un cursor, obtener cada estructura de registro, pasarla a una estructura de memoria, recorrer programáticamente un índice, recordar que el campo nombre está en tal posición, y más y más detalles. Vean cómo el lenguaje SQL es un DSL: no es un lenguaje genérico. No sirve para hacer sistema cualesquiera. Nadie escribe formularios en SQL o hace cálculos científicos o rutinas recursivas. Sólo está dedicado a solucionar el tema de acceso a datos. Pero ha sido lo bastante potente y flexible, para que hoy lo hayamos adoptado en cada recoveco de nuestros sistemas. Detengámonos en esos puntos:

– No es genérico, es específico de un dominio

– Es flexible

– Hace lo que necesitamos hacer, por nosotros

Segundo caso de DSL: un lenguaje no tiene que ser un lenguaje textual. Tomemos el caso de un DSL exitosísimo, que cambió la forma de programar en Windows. Es el caso del diseñador de formularios del venerable Visual Basic del milenio pasado. Vean cómo dibujando un formulario, Visual Basic se encarga de armar lo que nos hubiera llevado páginas y páginas de código C++. Algunos de Uds. recordarán la alienación que era codificar un simple “Hello, World”, con Visual C++, siguiendo las recomendaciones del bueno de Petzold. Visual Basic nos liberó de eso. Alguien podría haber pensado: no hace lo mismo que C++, no es tan eficiente, no permite ser tan flexible… Bullshit…. Visual Basic nos ayudó por más de una década, con un DSL gráfico.

Algunos generadores de código

Algunos de Uds ya habrán experimentado con utilitarios de generación de código. En un próximo párrafo, mencionaré lo que yo pediría a un generador. Pero veamos ahora algunas limitaciones.

Primero: el generador sólo genera lo que él quiere. Típico de generadores “profesionales”, que sólo producen lo que los creadores del generador imaginaron. Es difícil, y en algunos casos, imposible, extenderlo más allá de lo que hacen actualmente. Variante de esto: sólo genera código para entidades, o sólo para una tecnología, o sólo para EJB, o sólo para…. y puedo seguir. Claro, la herramienta soluciona el problema, y al comienzo estamos chochos de haberla encontrado. Pero advertiría desde ahora, que encontrarán limitaciones.

Segundo: el generador sólo parte de un modelo predeterminado (típicamente de una estructura de tablas de base de datos). Creo haberlos convencido que hay más bajo el sol que generar entidades y mapeadores. Hay colecciones inmensas de artefactos que tenemos que generar en cualquier sistema no trivial. Y seguirán apareciendo, por lo menos, en el futuro cercano. Si el generador sólo está pensado para partir de un modelo determinado, nos limita en lo que podemos pedirle. La historia nos ha mostrado, que siempre necesitamos algo más.

Tercero: el generador es cerrado, no se puede aprovechar e integrar en sistemas nuestros, o no entrega el código de base, o no permite armar plantillas y demás auxiliares.

Puedo seguir enumerando problemas. Mencionemos uno más: hay quien menciona que utilizó generadores de código, pero sólo lo usa para generar el código inicial de un sistema, y luego ya modifica el código generado, y no puede regenerar sin perder los cambios que hizo. Sugerencia: pongan en claro qué artefactos se generan automáticamente, y cuáles son los generados manualmente. Cuando Uds compilan un ejecutable, y necesitan cambiar un algoritmo, no van y cambian los bits del .exe. No: van al modelo, al lenguaje de programación, lo cambian y compilan de nuevo. Lo mismo deberíamos conseguir algún día, con generación de código. Como no podemos generar todo, debemos tener la disciplina de decidir cuáles artefactos son generados por el utilitario, y cuáles son los artefactos nuestros. En algunos casos, en los repositorios de código, en un CVS, cuando se trabaja en grupo, NO SE GUARDA lo generado automáticamente: solamente se guarda el modelo, y lo generado manualmente. Esto refuerza la responsabilidad de no tocar ese código automático: cualquier cambio manual que hagamos sobre ellos, no se guardará en el repositorio común.

El camino del demonio

Quisiera insertar ahora, en este momento, una advertencia. Todos podemos hacer un generador de código, o utilizar alguno ya armado. Algunas de las características deseables, fueron apareciendo en la discusión, y quedará más claro en la próxima sección. Pero levanto la mano para que no sigan un camino: XSLT.

Podrá ocurrírseles, en algún momento, que el modelo inicial, la metadata de partida, se encuentre en XML. Creo que es una elección pragmática: luego, más adelante, ese modelo se puede dibujar, crear con utilitarios más simpáticos o gráficos, pero un buen XML sirve como un DSL para un dominio que querramos manejar.

Pero no se les ocurra que podrán generar lo que quieran con XSLT (transformaciones de XML). XSLT es el camino del demonio. Para cualquier cosa no trivial, es algo que complica el universo, de una forma no predecible. Es como tratar de rascarse la oreja izquierda con el pie derecho. Poder se puede, pero les va a costar. Trabajar con XSLT es como un problema de ingenio. ¿Recuerdan el acertijo de tener un bote, dos orillas, y en una una oveca, una lechuga y un lobo, y sólo caben dos en el bote, aparte de uno? Bien, algo así es tratar de manejar XSLT para generar código. “Forget it”, XSLT caca…. 😉

Hacia un generador de código

¿Qué le pediríamos entonces, a un generador de código? Gran pregunta, intentemos algunas respuestas:

– Que genere código que hubiéramos generado nosotros: si genera código inentendible, estamos en mal camino. Ese es el problema de varios wizards y demás herramientas: hacen lo que ellas quieren, no lo que nosotros queremos.

– Que genere cualquier texto que nos imaginemos que necesitamos: no basta que genere lo que el generador de código decida. Debe ser lo bastante flexible, para que podamos generar lo que querramos: desde una simple entidad, a un mapeo de Hibernate, desde una página web, hasta un mensaje de Windows Communication Foundation, desde el archivo de configuración de Struts, hasta el interminable ejb-jar.xml que nos pide el JBoss versión 17.84 que tengamos el año que viene.

– Que parta de un modelo simple, o compuesto, pero libre: no que parta de una base de datos, y sólo genere entidades y mapeadores. Necesitamos más flexibilidad. Ya vimos los que nos pasa en la vida real: todo cambia, necesitamos multitud de artefactos. Cualquier inversión en un generador de código que no permita incluir un modelo libre, me parece riesgosa. Creo que como prueba ácida, le pediría a un generador, que permita, desde un modelo libre, generar todo programa “Hello, World” que se nos ocurra. Si una herramienta no puede obtener ese resultado, estamos en el horno.

– Que permita escribir los templates, plantillas que querramos, y generarlas en grupo, en serie, en paralelo, o como querramos. Tanto el orden y enumeración de artefactos a generar, como las plantillas, como la toma de decisiones (generar de tal forma o no), debe estar bajo control del utilitario, y bajo control nuestro.

– Que permita generar desde un modelo, al cambiarlo, de forma fácil: si para generar los artefactos, por un cambio en el modelo, hay que dar cuarenta pasos, de nuevo estamos en problema. Compilar hoy es una tecla. Lo mismo debe ser la generación de código.

Dunga dunga un ratito

De alguna forma, un generador de código ideal no estará atado a una tecnología. Siempre habrá alguna “better mousetrap”, siempre alguien inventará alguna nueva forma de hacer algo, siempre habrá un ruso con insomnio, o un hindú sin novia, que no tiene otra cosa que hacer que crear algo nuevo, ya sea en forma de librería, framework, patrón, o estilo arquitectónico. Un generador de código debe ser agnóstico de la tecnología, de las modas, de las soluciones actuales y futuras.

El generador de código que adoptemos, debe poder adaptarse a lo que querramos hoy y mañana y pasado mañana. La estrategia es: no importa la tecnología, el patrón o el framework que aparezca, nuestro generador deberá aprovecharse de lo que surja. Es lo que llamo la estrategia “dunga dunga”: si aparece una nueva tecnología T1, le hacemos “dunga dunga” a T1, si aparece un nuevo framework PiruloStruts, adaptamos nuestras plantillas a aprovecharse de ese framework, “dunga dunga” a PiruloStruts. Es como un maestro de aikido: siempre habrá alguien más fuerte, sólo hay que utilizar la fuerza del otro, para vencerlo.

Mi corazoncito

Claro, los que asistieron a algunas de mis charlas, ya conocen el final: tengo mi propio generador de código, el proyecto de código abierto AjGenesis. Lo pueden bajar, probar, examinar, integrar, modificar, hagan lo que quieran. Pero no digan que no les mostré la luz… 😉 😉

Se basa en:

– Tener un modelo totalmente libre, que hoy está serializado en archivos XML.

– Plantillas que generan artefactos de texto

– Tareas programables, que cargan los modelos, ejecutan lo que uno quiera, y son invocables desde programas nuestros, desde la línea de comando, o desde un utilitario como el NAnt.

Entonces, se arma uno o varios modelos, que expresan lo que Uds quieran de su sistema, de forma independiente de la plataforma, y luego, adosándole modelos (uno o varios, de nuevo libres), que indican la tecnología a usar, y escribiendo las plantillas que Uds. quieran, generan lo que se les ocurra.

Pueden leer sobre el modelo libre que usa en:

Generando Código- Hello World con AjGenesis

(como el modelo está serializado en texto… adivinen… se puede generar desde el mismo generador!!!). Esto implica:

M1 (de alto nivel) ===> Templates+AjGenesis ==> M2 (de nivel medio) ==> Templates+AjGenesis ==> Mn….. ==> Artefactos de texto finales

¿Se entiende? Si uno tiene pensado un modelo M, bien puede generarlo desde otro modelo que alguien traiga: por ejemplo, desde la estructura de base de datos, o desde un gráfico UML serializado en XMI, o lo que se invente mañana. Sólo es cuestión de generar el modelo desde el cual queremos partir. Hoy lo generamos manualmente: pero tengo algunos intentos promisorios, para que el modelo que necesite, se genere desde otro modelo que tengamos más a mano.

(Notablemente, ahora, muchos generadores de código más “profesionales”, están adoptando esta estrategia: modelo libre…. vieron la luz… :-) 😉

Pueden ver algunos ejemplos no triviales:

Generando aplicaciones con AjGenesis

Desde un modelo inventado para el ejemplo, se producen aplicaciones completas en VB.NET 1.x, VB.NET 2, C# 1.x, C# 2, JSP, usando patrones de Business Entities/Business Components a la Microsoft, o usando Domain-Driven Design de Evans, usando MySql o SQL Server, usando Gateways, Data Mappers, o Hibernate, o NHibernate. O lo que vuestra imaginación quiera: el cielo es el límite.

Ese modelo del ejemplo, hoy se genera manualmente. Tengo utilitarios, basados en AjGenesis, que generan ese modelo, desde un modelo más esquemático. Y estoy trabajando para generarlo desde otras fuentes. Si el modelo a usar se puede expresar en texto, PUEDE SER GENERADO por el propio sistema, más un sistema experto. No imagino una aplicación más inmediata de la “inteligencia artificial”. Imagino agentes inteligentes, que colaboren en una red compartida, cada uno generando parte del modelo, cada uno consumiendo algo que otro produce, y colaborando, para generar un sistema… Sí, ya sé, tengo que tomar la píldora verde, en lugar de la roja… 😉

Más artículos sobre generación de código en:

Generación de Código

Pero no tiene mucha documentación. Si Ud. lo encuentra útil, le pediría:

– Escribir, comentar sobre su experiencia, en la web (lo que no está bajo Google, no existe…:-)

– Compartir los templates, o por lo menos, comentar cuáles creó, para qué, y sus resultados

Estoy trabajando en tener un repositorio de templates en la web, para poder catalogarlos, y que otros usuarios puedan (no es obligación) publicar las plantillas o modificaciones que le resulten útiles.

Generadores de código más “armados” (pero me parece, sinceramente, menos flexibles), desde:

http://www.codegeneration.net/

Más allá de la generación de código

Hay que tener claro algo: la generación de código es sólo una solución pragmática a la situación actual. No implica abandonar todo pensamiento crítico, toda esperanza de mejora en la creación de sofware. Creo que vamos por buen camino: tenemos arquitectura, patrones, vamos conociendo cada vez más, cómo generar software de calidad. Estamos, creo, en una etapa aristotélica de nuestra disciplina: estamos ordenando conocimientos, clasificando datos, comenzando a darnos cuenta de cuáles son los esquemas, relaciones, problemas esenciales. Pero nos falta aún encontrar a un Galileo o Newton de los sistemas (mi natural modestia, me impide señarlar a un candidato que tengo “in pectore”… ;-).

Conclusión

Estudien cómo hacen los sistemas. Consigan dominar la tecnología que tienen entre manos. Descubran lo común a todo lo que hacen. Y en algún momento, adopten alguna herramienta, que les ayude a generar automáticamente lo mismo, que Uds. hubieran generado. Dedicar la inteligencia y el tiempo, donde el tiempo y la inteligencia se necesitan. Dejemos de escribir palabras de lenguaje: creemos software.

La mejora herramienta está entre nuestras orejas, apliquemos la neurona, generación de código, vermuth con papa fritas, y good show!

Angel “Java” Lopez
http://www.ajlopez.com/

This entry was posted in 1389, 1390, 2643, 3463, 6145. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>