Archive for the '2643' Category

Aplicaciones Creando Aplicaciones

Monday, April 28th, 2014

En todos estos años, he estado trabajando en diferentes aproximaciones para hacer que programas creen programas. Este post es un resumen y revisión de los caminos que he tomado, y en los que sigo trabajando, como un Work in Progress. Pienso que hay maneras interesantes de hacer programación, listas para ser exploradas.

Aplicaciones Dinámicas

Algo que hace unos años no hubiera encarado. Pero la ductilidad que da JavaScript me trae de nuevo a esta idea. Todo se basa en describir una aplicación (entidades, relaciones, vistas, código), y ejecutarla en un programa especializado (generalmente en páginas web) que conozca cómo interpretar y ejecutar la definición de la aplicación. Escribí una demo de la idea para la competición Knockout del año pasado:

Más información en mi post Aplicaciones Dinámicas en Node.js.

[View:http://www.youtube.com/watch?v=GQdyyNWCasI]

La aplicación pudo ser descripta usando una simple estructura: en este ejemplo, es un objeto JavaScript sencillo que puede ser serializado a JSON. La misma estructura puede ser interpretada por diferentes programas “host”: una aplicación web (la demo de arriba), o una aplicación web SPA (de Single Page Application), una aplicación mobile (Phonegap o nativa). Y hasta podría usarla como base para generar código en una tecnología concreta, como Sinatra, PHP, Express+Node.js+MongoDB, etc.

Generación de Código

Ya saben, uno de mis temas preferidos. He estado creando tareas, plantillas y modelos de libre definición para generar aplicaciones en Express/Node.js y en otras tecnologías (Sinatra, Django, Flask, PHP, todo Work in progress). Tengo implementaciones de mi herramienta de generación de código en C#, Ruby y Node.js. Pero mis últimos trabajos usan la de Node.js:

https://github.com/ajlopez/AjGenesisNode

Pueden ver un ejemplo en:

https://github.com/ajlopez/AjGenesisNode-Express

Una aplicación generada:

 

Estoy trabajando en crear un sitio en línea donde cualquiera pueda definir el modelo, y elegir una serie de opciones de tecnología. El sitio generaría código, listo para bajarse en un .zip.

Tarjetas

En el proyecto:

https://github.com/ajlopez/SimpleCards

Describo cada aplicación como un conjunto de “cards” (o sea, tarjetas, en un “deck”, mazo). Una tarjeta puede tener valores simples, o un valor que sea a su vez una tarjeta o un mazo de tarjetas. Por ejemplo, una tarjeta puede tener un id, un nombre, un título como valores simples, e información adicional, otros valores. Una tarjeta puede tener un valor que a su vez sea un mazo de tarjetas (por ejemplo, una tarjeta de Elementos Químicos, puede tener un mazo de tarjetas, una por cada elemento químico a describir). Cada tarjeta/mazo puede ser mostrado en diferentes contextos: desde una aplicación web, una SPA, una aplicación móvil (podría implementarse para PhoneGap o para nativo). Una cosa es la estructura y contenido de una tarjeta, y otra es el mostrar la tarjeta. Esto de mostrar depende del contexto de la aplicación que alberga las tarjetas.

Un ejemplo simple

https://github.com/ajlopez/SimpleCards/blob/master/samples/deck/js/model.js

var model = {
    title: "My Deck",
   
    cards: [
        { title: "Card 1", text: "This is the card 1" },
        { title: "Card 2", text: "This is the card 2" },
        { title: "Card 3", text: "This is the card 3" }
    ]
}

Otro ejemplo, con pantallas:

https://github.com/ajlopez/SimpleCards

El contenido de un tarjeta pueden ser valores con texto simple, texto largo, una URL, la URL a una imagen, o la descripción de algún componente especializado a ser mostrado (por ejemplo, un Google Maps). La descripción de la tarjeta y su contenido puede ser estático o puede ser generado en el momento. Por ejemplo, podría implementar leer un “feed” y transformarlo en un mazo de tarjetas. O podría recuperar la descripción de un mazo o una tarjeta desde una API REST. Una tarjeta puede tener algunos valores parciales (por ejemplo, id, título), para ser mostrado en el mazo, y cuando uno entra y quiere ver la tarjeta completa, un componente adicional puede RESOLVER la tarjeta y conseguir los datos adicionales, por ejemplo usando su id. Un ejemplo: una tarjeta tiene título y id. El id es la URL de la página en la Wikipedia. Cuando una tarjeta necesita ser vista, el programa adicional toma el id, y resuelve la tarjeta, bajando el contenido de la página, extrayendo texto, enlaces relacionados, imágenes.

Mucho para hacer, y muy interesante.

Nos leemos!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

Generación de Código con AjGenesis para Ruby (1)

Friday, August 30th, 2013

Ya hace unos meses porté el AjGenesis clásico (de .NET) a Ruby. Ver avance en:

https://github.com/ajlopez/AjGenesisRuby

Tengo un simple ejemplo de Hola mundo

https://github.com/ajlopez/AjGenesisRuby/tree/master/samples/hello

y un ejemplo un poco más interesante, de “scaffolding” sobre Sinatra, desde un modelo con dos o más entidades:

https://github.com/ajlopez/AjGenesisRuby/tree/master/samples/site

Elegí Sinatra porque algo había estado practicando en mis anteriores charlas de Ruby. Espero armar un ejemplo con relaciones uno a varios, y con interface JSON/Ajax entre cliente y servidor, así como luego portar los templates a uso de Cuba. Podría generar desde AjGenesis Ruby código para Node o C#, es lo mismo.

Bien, para dar cuenta del estado actual de ese trabajo, di una charla en la pasada Meetup de Ruby en Buenos Aires, el miércoles 28 de Agosto. Resultado (con UNA RAPIDA INTRO A ANGLISH!!!):

http://www.youtube.com/watch?v=y8DxmSgxKow

[View:http://www.youtube.com/watch?v=y8DxmSgxKow]

Donde trato de explicar la historia y la motivación para mi interés en la generación de código. No es mi intención proveer plantillas/templates para distintas tecnologías. Mas bien, es motivar a que Uds, en su equipo, consultora, línea de negocios, hagan el experimento de “raise the level of abstraction” y vean cuánto pueden codificar en este “pichón de sistema experto” que es AjGenesis. Quiero llegar a expandirlo para que sea un sistema experto, como explico en la charla, donde sea fácil incorporar nuevos agentes que se encarguen de solucionar un problema, por ejemplo, guardar un documento en un NoSQL, o validar una fecha en una interface web, o en una interface Android, etc. Una vez identificados los problemas, cada uno puede escribir el agente que le parezca.

Nos leemos!

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

Generación de Código con AjGenesis: Nueva Versión e Ideas

Tuesday, March 19th, 2013

Hace una semana moví mi proyecto de generación de código AjGenesis (la versión .NET) desde Codeplex a GitHub. El sitio de Codeplex tiene una nueva versión publicada AjGenesis 0.6 (no lo puse en GitHub porque hace un tiempo removieron de ahí la posibilidad de tener downloads de binarios). Recuerden que es un proyecto de código abierto, así que aparte de bajarse los binarios se bajan el código correspodiente. Si no conocen AjGenesis, pueden leer mis posts sobre el tema.

La nueva versión es el compilado del trunk de Codeplex. Tiene pequeñas correcciones y alguna mejora, y ha sido usado en proyectos reales. Hasta parece que lo han usado para generar código para Ruby On Rails, pero nadie del proyecto ha publicado un post todavía así que no tengo evidencia para mostrarles.

Es tiempo de pensar la próxima versión. Algunas ideas a implementar, como “roadmap” tentativo:

– Refactorizar los tests, para usar las tools de Visual Studio

– Reescribir AjGenesis Web Studio, en ASP.MVC 3, using C#, Razor, and Bootstrap 2.0

– Un nuevo programa principal de consola, renombrado a ajgen (en vez del actual, AjGenesis.Console, un nombre largo para estos tiempos ;-).

– Soporte de comandos en repositorios. Esto es (algo está implementado en la versión actual, pero es “Work in Progress”), poder usar un nombre/verbo cuando se lanza el programa principal de consola, por ejemplo:

ajgen generate <parameters>

ajgen newentity <parameters>

La forma general es

ajgen <verb> <parameters>

Los verbos estarán definidos en repositorios, y cualquiera podrá escribir nuevos comandos (en principio, serán tareas usuales de AjGenesis). De esta manera, podría soportar generación de código de una forma más fácil y extensible: en vez de especificar archivos específicos de tareas y modelos, éstos podrían ser ubicados en lugares definidos. En las versiones anteriores, yo estuve reluctante a agregar eso, búsqueda automática de tareas: preferí lo explícito a lo implícito. Pero luego de ver cómo se maneja la generación de código en frameworks como Ruby on Rails, Django, Express, me gustaría explorar esta forma.

La manera usual

ajgen <task or model files>

seguirá soportada como siempre, sin cambios. Sólo si el primer parámetro es un nombre, se lo tomará como verbo y se buscará la tarea asociada.

Algunos objetivos para más adelante:

– Soporte de JSON para escribir modelos

– AjSharp/AjBasic como lenguajes de scripting. Ahora, AjBasic está acoplado, interno al proyecto AjGenesis

Ah! Y no se olviden que hay nuevas versiones de AjGenesisAjGenesisNode implementado en JavaScript usando Node.js, y AjGenesisRuby usando Ruby.

Nos leemos!

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





				

AjGenesis Generación de Código en .NET, Javascript y Ruby, Las Puertas Están Abiertas

Thursday, May 31st, 2012

Tengo la costumbre de levantar temprano en la mañana. El martes pasado, me levanté algo más temprano, todavía, porque tenía una idea rondando en la cabeza. La semana pasada trabajé bastante con Javascript y Node.js, en mis proyectos personales, y había conseguido algo que ahora veía que podía fácilmente implementar en Ruby. No lo había hecho por meses, porque no me parecía que hubiera un camino claro, pero luego de mi experiencia de la semana pasada, tomé la decisión de cómo implementarlo. Estoy hablando de tener un motor de plantillas (“template engine”) para mi generador de código AjGenesis, ahora en Ruby. Puse manos a la obra, y en tres horas tuve algo andando, armado usando TDD (con “commits” frecuentes que pueden ver en el log de GitHub).

El resultado quedón en mi cuenta de GitHub:

https://github.com/ajlopez/AjGenesisRb

Inicialmente, había planeado (el año pasado) usar uno de los motores de plantillas ya disponibles en Ruby, como Haml. Pero preferí escribir mi propia implementación, más alineada con el AjGenesis original. Esto lo tomé luego de la buena experiencia que tuve la semana pasada cuando escribí AjGenesis en Javascript/NodeJs, ver:

https://github.com/ajlopez/AjGenesisNode

En ese proyecto, separé el motor de plantilla en otro paquete, ya publicado en NPM:

https://github.com/ajlopez/SimpleTpl

De esta manera pude reusar el formato de plantilla en otro proyecto Javascript sobre Express,:

https://github.com/ajlopez/SimpleMvc

una simple implementación de MVC (Model View Controller).

Entonces, ahora tengo tres proyectos:

El clásico AjGenesis, implementado en .NET (ver el directorio de ejemplos)
AjGenesis en Javascript/Node, usando la SimpleTpl template engine, con interpolación de expresiones Javascript y con soporte de comandos Javascript embebidos en el medio de la plantilla (ver directorio samples)
AjGenesis en Ruby, con un motor interno de plantillas similar al anterior, con soporte de expresiones y comandos Ruby embebidos (ver directorio samples)

AjGenesis en Javascript fue publicado en npm (Node Package Manager) como beta.

AjGenesis en Ruby no está todavía como gema.

RECUERDEN: todos estos proyectos GENERAN los artefactos de texto QUE QUIERAN. No son sólo para un lenguaje. Por ejemplo, desde AjGenesis en Javascript generé una solución para .NET, ver los ejemplos.

Es muy interesante ver cómo ideas simples pero poderosas pueden ser reimplementadas en lenguajes dinámicos (de ahí mi temprano interés en tener desde hace años a AjBasic y más recientemente, a AjSharp). Próximos pasos: más ejemplos, línea de comando, gema ruby, release de paquete node (ya no beta), y sitio web implementando “Code Generation as a Service” (ASP.NET implementation commented in my old post). (ver también AjGenesis: Basis of Its Implementation).

Otros lenguajes de implementación pendiantes: Python, quizás Java.

(La foto original desde: http://commons.wikimedia.org/wiki/File:Table_Rock_Dam_during_April_2008_White_River_Flood.jpg)

Nos leemos!

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

AjGenesis: Bases de su implementación

Saturday, November 19th, 2011

Dediqué gran cantidad de tiempo al desarrollo de AjGenesis, mi proyecto abierto de generación de código desde un modelo de libre definición. Es tiempo de escribir que es lo que considero los principales puntos que formaron y hacen a AjGenesis.

Primero: el uso de un modelo libre en memoria, que es manejado y accedido como si fuera un objeto común en un lenguaje de programación. No necesito recorrer nodos XML o algo raro. Puedo visitar y manipular uno o varios modelos como si fueran objetos dinámicos. No adopté un modelo tipado o un modelo con un esquema predeterminado: el modelo es de libre definición, puedo poner en cada modelo lo que quiera y necesite. El modelo es deserializado desde XML o desde texto simple, o puede ser inyectado desde un programa: AjGenesis puede ser albergado en un programa .NET cualquiera y ser usado como una librería.

Segundo: el uso de un lenguaje simple y dinámico para ejecutar tareas simples o complejas, con acceso a una librería de clases rica. En AjGenesis, uso AjBasic, un intérprete que puede acceder a .NET. Puede usar, crear y cambiar objetos dinámicos, como son los modelos.

Tercero: el uso de plantillas, con soporte de expresiones y comandos (como ciclos, condicionales, etc…) escritos usando el mismo lenguaje dinámico.

(Algunas alternativas temprana fueron: usar XML con esquemas para modelos, y XSLT para las transformaciones. Las rechacé porque sentí que tenían límites que podrían afectar el desarrollo claro y extensible del sistema).

Ver:
Building an Application with AjGenesis
Code Generation with AjGenesis in a Real Project
Models for Code Generation in AjGenesis
AjBasic: An Open Source Basic-alike Interpreter
Generating Code Hello World with AjGenesis

Teniendo estos tres pilares, uso AjGenesis desde hace años, con diferentes tecnologías, lenguajes y frameworks (desde Java a .NET, desde JSP a ASP.NET a ASP.NET MVC, desde PHP4 a PHP5 a .NET4 y espero .NET5, desde DDL para MySql como para MS SQl Server, hay usuarios que lo usaron para Oracle, y un usuario ha estado generando código para Ruby on Rails!). Notablemente, estoy generando artefactos de texto para tecnologías que no existían al comienzo del proyecto. Y todo eso con mínimos cambNotably,os al AjGenesis mismo. Puedo ejecutarlo en Linux y en Max OSX gracias al proyecto Mono (Ver Running AjGenesis Using Mono and Ubuntu).

Ideas a implementar: la capacidad de inyectar el modelo (su deserializador), el poder elegir el lenguaje dinámico a usar (tengo planeado agregar AjSharp como lenguaje dinámico para las tareas y plantillas).

Pero si tengo los tres puntos que enumeré arriba, yo podría implementar AjGenesis en otras tecnologías. Como prueba de concepto, comencé hace unos días a implementar esas ideas esta vez usando Ruby: objetos dinámicos, que pueden cargarse desde archivos en formato YAML (o XML, tendría que explorar otros formatos), el uso de Ruby como lenguaje de las tareas, y el uso de templates usando ERB (o alguna otra tecnología de plantillas en Ruby).

Pueden ver el progreso de la idea en: https://github.com/ajlopez/AjGenesisRb

Nos leemos!

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

AjGenesis: Generación de código para Ruby on Rails

Tuesday, October 18th, 2011

Gracias al bueno de @lmpetek que escribió un post sobre su experiencia con AjGenesis:

Rails tiene scaffold, nosotros usamos AjGenesis

Es bueno encontrar evidencia publicada de usuarios de mi proyecto open source AjGenesis de generación de código DESDE UN MODELO. Me llega evidencia de que lo usan (correos electrónicos, comentarios en mis charlas, etc…), pero encuentro poca evidencia publicada, y es bueno encontrarla. Interesante que @lmpetek y sus equipos usen AjGenesis (incluso llegó a usarlo fuera de Windows, gracias a que funciona con Mono en otros sistemas operativos). Sé que sus equipos hasta lo usaron para generar reportes de MS SQL Server Reporting Services 😉

También recuerdo que de una aplicación que estaban construyendo en Java, al tener un modelo independiente de la tecnología, se pudo pasar a dar una demo en .NET con poco esfuerzo. Y que si quieren modificar la forma de acceder a los datos (por ejemplo, de JDBC a Hibernate) tranquilamente pueden modificar los templates para conseguir ese efecto. Teniendo la lógica en archivos generables una sola vez, cuando cambian el modelo y regeneran, esa lógica no se pierde. Y cuando trabajaron en .NET, pudieron pasar de usar un framework para las operaciones sobre objetos (persistencia) a otra forma, usando ADO.NET, SIN CAMBIAR LO QUE YA HABIAN escrito de la solución. Algo comenté sobre esta experiencia en:

Generación de código con AjGenesis en un proyecto real

Incluso un proyecto, que ya habían iniciado sin generación de código, sirvió de base para abstraer el modelo y la forma de codificación (proyectos, patrones, clases, reparto de las responsabilidades) y conseguir generación de código. Escribí sobre eso en:

AjGenetizando una aplicación

Y ahora comienzan a usarlo para Ruby on Rails. Notable! Leo en el post:

Luego de utilizarlo en proyectos reales para generar soluciones en .Net y Java, fue absolutamente natural utilizarlo para generar proyectos Ruby on Rails.
A la generación de código la considero un aliado indiscutido en la programación diaria para cualquier equipo de desarrollo maduro.

Si el proyecto tiene una base de datos ‘Legacy’ utilizamos AjGenesis para extraer la información desde las estructuras de las tablas en la DB y volcar esto en entidades agnósticas con las que luego  generamos los modelos, los controladores y las respectivas vistas.
Recién en este punto avanzamos manualmente, agregando la ‘inteligencia’ al proyecto. Aportando el diferencial real para que una aplicación tenga ese plus que tanto valora nuestro cliente. La diferencia es que esta etapa para nosotros comienza muy tempranamente.
Podemos regenerar toda la apariencia de la aplicación, realizando cambios en los templates en que se basa la generación y tener todo funcionando en poco tiempo.

Noten una cosa: como ya el equipo entiende AjGenesis (de proyectos anteriores en Java y .NET), puede escribir sus propios templates, en lugar de usar la generación que viene con Ruby on Rails. Eso apoya algo que defiendo: hay que hacer sus propios templates, en base a lo que uno sabe. Usar templates de otros puede ser fácil al comienzo, pero al madurar el proyecto y querer modificarlos puede complicarse. La generación de código tiene que producir texto que entendamos. ¿Qué mejor que hacerlo con nuestros propios templates? Basados en nuestra experiencia de codificación “normal”. Es por eso que los templates que vienen con AjGenesis son de “prueba de concepto” y nada más. Cada equipo, empresa, debe cultivar y nutrir a sus artefactos de generación de código, en lugar de simplemente importarlos de otro lado. Es decir, promuevo el crecimiento orgánico (por ejemplo, baby steps, incremental).

Vean que el conocimiento adquirido en los equipos en la separación de las responsabilidades ha ido sobreviviendo (y espero mejorando) de .NET a Java y ahora a Ruby on Rails. Un ejemplo de dunga dunga a la tecnología 😉

Post relacionado (gracias al bueno de @ferclaverino):

AjGenesis y Generación de Código: viendo la luz

donde explica su experiencia en proyecto real con AjGenesis.

Nos leemos!

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

Elevar el Nivel de Abstracción (Parte 1) Introducción

Saturday, June 4th, 2011

En este siglo escribí muchos posts sobre generación de código. Es un tema que me interesa desde los ochenta del siglo pasado: cómo hacer programas que escriban programas. Pero no es solamente generación de código: quiero poner énfasis en generación de código DESDE UN MODELO. Ahora, quiero escribir sobre la base de esa solución pragmática a algunos de los problemas que encontramos en el desarrollo de software. Mi principal afirmación:

Generación de Código desde un Modelo es un ejercicio de Elevar el Nivel de Abstracción

La historia de la programación es una historia de “elevar el nivel de abstracción”. En lugar de manipular botones en el panel frontal de las primeras computadoras, ahora escribimos programas usando un lenguaje que es una abstracción: usamos “int a” como una abstracción de una palabra en memoria. Escribimos “foo(bar)” como abstracción de guardar el estado en la pila, y saltar a una dirección en memoria: ya no escribimos más instrucciones BALR (Branch and Link Register) en un lenguaje ensamblador de mainframe IBM. Entonces, cada día estamos usando generación de código: desde el lenguaje general o específico que usamos para escribir programas, nuestros compiladores generan código de máquina, el único código que cuenta para las computadoras.

En esta nueva serie de post quiero explorar y escribir sobre estas ideas:

– Nosotros mejoramos continuamente nuestras ideas y habilidades, pero la tecnología también está sujeta a cambio constante
– Modelos abstractos vs modelos tecnológicos, concretos
– Separar los problemas de las soluciones
– Destilar y reusar el conocimiento de los desarrolladores
– Generación de Código DESDE UN MODELO como un ejercicio de abstracción
– Entonces, la generación de código desde un modelo tiene un efecto beneficioso colateral: arroja luz sobre la separación entre lo que es importante y lo que es accidental o técnico 
– La generación de código puede (y debe) coexistir con la codificación manual

Muchos de estos temas fueron mencionados en mis posts de AjGenesis, pero es tiempo de presentarlos de nuevo como un todo integrado. El título de esta serie “Raise the Level of Abstraction” (ver mi post en inglés) nació en una charla técnica en uno de mis clientes, ya hace unos años. Es bueno encontrar la misma frase como “leit motiv” para la conferencia Code Generation 2011:

http://www.codegeneration.net/cg2011/index.php

Recuerdo también otra frase anterior de ese sitio: “code generation for the pragmatic engineer”. La generación de código desde un modelo no es una “bala de plata”: es otra bala, herramienta más, a usar en el contexto correcto.

(Nota: Encontré las imágenes que acompañan a este post buscando el Google Images, con términos: “two apples”, “two oranges”, “two sheep” and…..  “two person” ;-)… no busqué Microsoft ;-))

Nos leemos!

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

Generación de Código e Inteligencia Artificial

Tuesday, May 31st, 2011

A finales de los setenta y principios de los ochenta (ya en el siglo pasado ;-)) estuve aprendiendo de todo sobre programación, lenguajes de programación y ciencia de la computación en general. Eran los días de COBOL, BCPL, ensamblador de IBM/360, JCL (Job Control Language), tarjetas perforadas, sistemas operativos Pick, Algol/W, Fortran, PL/I, y C (mi preferido) (en CP/M, DOS, Unix/Xenix). Uno de mis temas preferidos (entonces y ahora) era la Inteligencia Artificial, un término amplio (aún más en estos días). Esos días fueron la época dorada de los sistemas expertos (recuerdo Mycin, EMycin, el configurador automático de DEC, y otros). En ese entonces, estuve escribiendo montones de código C, entonces, como programador perezoso que soy, comencé a escribir mis propios utilitarios en C para generar más programas C ;-). Desde entonces que tengo na idea:

La Generación de Código debe ser una aplicación de Inteligencia Artificial

Hacia finales de los ochenta, principio de los noventas, el monto de código a escribir para tener una aplicación profesional fue disminuyendo (nuevas IDEs, “wizards” y librerías). Pero fue un estado transitorio: la complejidad impuesta por el mercado, por los requerimientos de los clientes, la aparición de aplicaciones en línea, concurrencia en todo, nuevas tecnologías y lenguajes (Windows, GUIs…) todo conspiró para el aumento del esfuerzo que debe ser empleado para cualquier aplicación no trivial. Abracé a Java a mitad de los 90, y luego a .NET en 2001. Grandes librerías de clase, nuevos trucos, estilos arquitectónicos, patrones, JSP, JSF, MVC, ASP.NET, Javascript, Ajax, algo de PHP, computación distribuida, capas físicas, escalabilidad, seguridad, rendimiento, …. De nuevo, el desarrollode software se transformó en ámbito complejo. Y ahora, tenemos mobile, Android, Windows Phone 7, ASP.NET MVC, nuevos JDKs, JVMs, lenguajes dinámicos… Podría continuar enumerando tecnologías sin por siempre… 😉

Por eso, al comienzo de este siglo, decidí comenzar my proyecto de generación de código, AjGenesis. Primero, éste es el proceso actual que uso en mis proyectos:

(Jeje… Ok, son un desarrollador, no un diseñador ;-))

Los modelos de partida (a la izquierda) son de libre definición: uno puede usar el modelo que quiera y le convenga, no están “fijos”. Esta es una decisión clave: yo quiero que podamos tener la libertad para comenzar con cualquier modelo que elijamos como base para nuestra generación de código. Pero es importante destacar: debe haber un MODEL. No es sólo generación de código: lo que propugno es GENERACION DE CODIGO DESDE UN O VARIOS MODELOS. Usualmente, tengo un modelo abstracto, como:

<Project>
	<Name>AjApp</Name>
	<Description>Building an Application using AjGenesis</Description>
	<Model>
		<Entities>
			<Entity Source="Entities/Customer.xml"/>
			<Entity Source="Entities/Supplier.xml"/>
		</Entities>
	</Model>
</Project>

y uno o más modelos dependientes de la tecnología como:

<Technology>
	<Programming>
		<Dialect>CSharp4NhMvc</Dialect>
	</Programming>
	<Database>
		<Dialect>MsSql</Dialect>
		<Name>AjTestNh</Name>
		<Host>.\SQLEXPRESS</Host>
	</Database>
	<NHibernate>
		<Dialect>NHibernate.Dialect.MsSql2000Dialect</Dialect>
	</NHibernate>
</Technology>

(más información en mis AjGenesis posts (en inglés) y mis posts (en español)). Los modelos se pueden escribir en XML o en texto. O podemos usar nuestros propios modelos (ver Models for Code Generation in AjGenesis, Modelos para Generación de Código en AjGenesis). Los artefactos de texto pueden ser Java, C#, VB.NET, Ruby, cualquiera que necesitemos. Como ejemplo de lo flexible que es este “approach”: cuando comencé con los ejemplos de AjGenesis generé PHP y JSP 1.x. Desde entonces, prácticamente sin cambiar esencialmente el proceso, pude generar para PHP (nuevas versiones), Java, JSP 2.x, Hibernate, NHibernate, ASP.NET 1.x, ASP.NET 2.x, ASP.NET MVC… Pude adaptarme a cualquier tecnología basada en código. Para conseguir tal flexibilidad, no hay IDE asociada en el proyecto. Tiene una interfaz espartana, pero me gusta. Me permite ir explorando nuevos caminos, sin estar anclado a una IDEA, aunque hace menos atractivo su uso.

Desde su concepción, adopté un lenguaje dinámico, AjBasic, para soportar tareas y “templates” (plantillas): yo no quería SOLAMENTE un motor de transformaciones, de un modelo a código mediante plantillas. Quería tener el poder de un lenguaje GENERAL, pero que a la vez permita manejar obj.Propiedad, sobre un objeto no tipado de antemano: los objetos son tan maleables como los modelos iniciales, que son tratados accedidos como objetos. ¿Por qué un lenguaje general, y no uno que sólo soporte algún if y for a nivel de templates? PARA SOPORTAR LA EXTENSIBILIDAD, más allá de la expansión de plantillas. Y para poder acceder a toda la librería .NET (uno no debe desperdiciar una librería de clases cuando la encuentra). Y ¿para qué más? Sorpresa! Para ….. soportar Inteligencia Artificial!

Afirmo:

La Generación de Código desde un Modelo puede ser implementada como un Sistema Experto, y entonces, es una clara aplicación para Inteligencia Artificial

Gráficamente:

Podemos ver a los desarrolladores de software como expertos humanos. Podemos “destilar” su experiencia y colocarla en sistemas expertos, agregdos al proceso de generación de código. Algunos ejemplos:

– Un sistema experto peude usar un motor de reglas para tomar decisiones, pequeñas, medianas o grandes. Una pequeña: “El reporte web puede tener muchas filas, necesitamos paginación, filtro, y ordenar por tales columnas, que son las más importantes para este dominio… “. Y entonces, alguna parte del sistema parte recomendaría: “Sí! Podemos usar JQuery y JQuery.UI, hacer filtro del lado del servidor, servir los datos desde este acceso Ajax… etc…”… y otra parte (sí, el sistema experto podría ser “multi-mente” ;-)) diría “No! Necesitamos filtro del lado del servidor, y necesitamos estas consultas y servicios para cumplirlos, y estos puntos de acceso Ajax y … “ ¿Se capta la idea?

Una micro-decisión que empleé el año pasado en un proyecto real: algunas entidades en el modelo abstracto fueron marcadas con el atributo “massive” (masiva) indicando: “tenemos gran cantidad de instancias de la entidad X en el sistema”. Entonces, cuando en la interfaz de usario necesitamos seleccionar una de esas entidades X, en vez de presentar una lista desplegable, el motor de generación de código (con lenguaje general que decide con if, funciones y rutinas) colocó una caja de texto de búsqueda, con auto-complete, y un servicio Ajax en el servidor.

Podría usar para el modelo abstracto una ontología de base sobre la cual poder hacer inferencias y tomar decisiones. Ejemplo:

– Cada entidad puede ser: una persona, una compañía, un lugar, un bien físico, un evento, un documento. Entonces, el sistema experto podría inferir: un lugar físico tiene una dirección; un bien físico debe ser guardado en un lugar físico; un documento X debe ser necesario para representar el movimiento de un bien físico de un lugar a otro; una persona puede ser un empleado; cada empleado tiene seguridad social… etc…. etc.. Entonces, cuando necesitamos un reporte de los eventos X, podemos inferir: los necesitamos ordenados por fecha, agrupados por lugar físico, etc..… etc… Tal documento tiene un total de moneda, sería interesante tener reportes agrupados por distintos criterios (por ejemplo, por parte involucrada en ese documento, un cliente, una compañía, una persona). Y por mes. Ah! Y necesitamos un gráfico de torta, y … y así, así… 😉

Podría agregar un motor de reglas para tomar algunas de estas decisiones, con reglas tipo “si la entidad X es masiva y la interfaz de usuario es web y podemos usar JQuery entonces… “. O reglas como: “si la entidad X hereda de la entidad Y y necesitamos persistencia, podemos adoptar la estrategia tabla-por-jerarquía. O tal vez alguna otra parte del sistema experto recomiendo tabla-por-clase-concreta. Y de ahí, generar los mapeos, la base de datos”. O: “esta entidad X es un documento que tiene una fecha; necesitamos agregar un índice sobre esta columna fecha/hora”. Es una forma de poner explícitamente las razones por las que tomamos decisiones como ésa cada día. Actualmente, en el proceso de AjGenesis, muchas de esas decisiones están en las tareas y en pistas que quedan en los modelos abstractos y de tecnologías. Pero bien podrían colocarse a nivel del sistema experto.

Como gran panorama, la generación de código desde un modelo involucra:

– Tenemos este punto de partida: modelos abstractos, modelos técnicos (con restriccionos como “este sistema lo necesitamos en ASP.NET MVC 3”)

– Esta es el entregable esperado (algún sistema ya armado parcialmente, que sirvió como prueba de concepto de las tecnologías que vamos a usar)

– Y tenemos todo este conocimiento experto destilado de la experiencia de nuestros desarralloradores, buenas prácticas, patrones…  Y con todo esto podemos ir desde el comienzo hasta el final esperado, aprovechando el conocimiento acumulado, configuraciones de ORM, librerías de inyección de dependencias, patrones de UI, patrones de implementación, conocimiento en la creación de bases de datos normalizadas, etc..

El desarrollo de software y su arquitectura está relacionados con:

– Conocer lo que necesitamos obtener

– Conocer cuales son los problemas a resolver (persistencia, concurrencia, seguridad, rendimiento, traza, interfaz usable por el usuario, etc…)

– Conocer cuales son las soluciones disponibles (base de datos relacionales, bases NoSQL, lenguajes de programación, librerías de clases, frameworks, tecnologías de interfaz de usuario, patrones de todo tipo…)

La generación de código desde un modelo tiene (para mí un gran) beneficio: pone en claro la existencia, SEPARACION y RELACIONES entre todos los puntos de arriba. En general, aprendemos todo eso pero centrados en una o dos tecnologías. Y cada problema viene mezclado con su solución. Y cada decisión nos viene “acoplada” a detalles técnicos, nos entretenemos en cada árbol, sin poder ver el bosque.

Otro camino a explorar (que inicialmente lo quise explorar para AjGo, mi código de soporte para investigar formas de jugar al Go): el uso de agentes expertos. ¿Qué significa “agente experto” en ésta, mi jerga? Mi visión: tener módulos, agentes que pueden ser agregados y removidos sin mayor esfuerzo, que puedan resolver problemas. Alguien podría desarrollar un agente experto en JavaServer Faces. Podría ser que alguien tenga un agente especialista en el nuevo ASP.NET MVC 6.6, o en el JSF 17.2, o en el nuevo “SuperDuperOpenSourceUIThatIsTheNextBigThingHere”. No impoirta, siempre podemos adoptar NUEVAS SOLUCIONES a PROBLEMAS SIMILARES (ingresar la factura en una interfaz, consultar el estado de tal tema, realizar operaciones), habiendo destilado el nuevo conocimiento y “envasádolo” en un nuevo agente experto.

Ok, todas estas son razones para un (¿próximo?) AjRules ;-). Y la justificación de mi trabajo con AjLisp (see here) y algo del código de un viejo AjProlog a ser portado a .NET (ver algo en AjCodeKatas).

Otros posts relacionados con el tema:

Modelos, decisiones, Inteligencia Artificial en AjGenesis

Sobre la Generación de Código

Imagen tomada de Artificial Intelligence, Introduction & Application (Part I)

Nos leemos!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

Dynamic Language Runtime (Parte 3) Expresiones Binarias

Monday, April 25th, 2011

Próximo post
Anterior post

Implementé algunos ejemplos simples usando DLR. Mostré cómo crear y evaluar expresiones. Cada Expression tiene algunas propiedades y métodos expuestos. Algunas de las más importantes:

Noten que cada objeto Expression tiene un NodeType, y Type separado. Exploremos esos valores:

BinaryExpression expr = Expression.Add(Expression.Constant(10),
    Expression.Constant(20));
Console.WriteLine(expr.GetType().FullName);
Console.WriteLine(expr.Type);
Console.WriteLine(expr.Left.Type);
Console.WriteLine(expr.Right.Type);
Console.WriteLine(expr.NodeType);
Console.WriteLine(expr.Left.NodeType);
Console.WriteLine(expr.Right.NodeType);

Veamos Expression.Add. Es una expresión binaria. Cada una de esas expresiones tiene dos ramas:

Obtengo la salida:

Noten que el .GetType() (el tipo .NET) de la Expression creada, es SimpleBinaryExpression: no es sólo un objeto Expression. Tampoco hay un AddExpression como clase en DLR. El expr.NodeType indica que la expresión creada es un Add. Los creadores de DLR decidieron no tener una clase dedicada para los Expression.Add.

Un BinaryExpression tiene Type: System.Int32, un entero de 32 bits. Este es el tipo que indica qué clase de valor retornará esta expresión. Se deriva de la acción de la expresión binaria (sumar) y los tipos de sus ramas izquierda y derecha.

En C#, podemos combinar expresiones binarias:

// double result = (3d + 2d) / 7d;
// Console.WriteLine(result);
BinaryExpression expr2 = Expression.Divide(
    Expression.Add(Expression.Constant(3d),
        Expression.Constant(2d)),
    Expression.Constant(7d)
    );
Func<double> binaryDelegate = Expression.Lambda<Func<double>>(expr2).Compile();
Console.WriteLine(binaryDelegate.Invoke());

Principal fuente consultada para este ejemplo: “Pro DLR in .NET 4” de Chaur Wu. El código de esta serie de post se mantiene en  http://code.google.com/p/ajcodekatas/ en el directorio trunk/Dlr.

Próximos pasos: expresiones IfThenElse, expresiones switch, qué es un visitor, y qué es Reduce.

Nos leemos!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

Dynamic Language Runtime (Parte 2) Hello Expressions!

Saturday, April 23rd, 2011

Próximo Post
Anterior Post

En mi anterior post escribí un simple programa “Hello, world”. Esta vez, quiero comenzar a explorar las Expression de DLR. El código de esta serie de posts se mantiene en 
http://code.google.com/p/ajcodekatas/ en el directorio trunk/Dlr.

Primero, una Expression en DLR no es una System.Linq.Expression (uno de mis primeros errores, en este ejemplo, fue usar la version Expression de Linq, en vez de la de DLR). DLR tiene su propia implementación de Expression, con más metodos. Esta implementación está en el namespace  Microsoft.Scripting.Ast. AST viene de  Abstract Syntax Tree: cada expresión, en DLR como en Linq, es una estructura de datos en memoria, que representa algo como 4, 5+a, llamadas a métodos, etc…

La clase Expression de DLR class tiene métodos estáticos para crear objetos Expression. Por ejemplo

var expr = Expression.Constant(“I’m a string”);

 

 

es la forma de crear una expresión constante. Pero necesitamos no solamente constantes, sino también variables:

var expr = Expression.Variable(typeof(string), “foo”);

 

 

Este comando crea una expresión variable, que representa una variable con nombre “foo” y tipo string.

¿Cómo invocar una expresión? Recordemos, los objetos Expression son árboles, datos en memoria, no código compilado. La magia de DLR (y de Linq también) es ser capaz de COMPILAR la expresión a un delegado, y entonces, poder invocarlo:

expr.Compile().Invoke(); // you can use Invoke with parameters, too

 

 

(Generalmente en mis intérpretes, no llego a compilar, recorro y ejecuto las acciones de los nodos del árbol de comandos y expresiones)

Entonces, para reproducir el  “Hello, World”, escribí este código de ejemplo:

// Console.WriteLine("Hello, Method!");
MethodInfo method = typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });
Expression callExpression = Expression.Call(method, Expression.Constant("Hello Method!"));
Expression.Lambda<Action>(callExpression).Compile().Invoke();

 

 

Precedí el código con un comentario que contiene el código C# equivalente.

Nota: necesitamos un Expression.Lambda (en este caso, un lambda Action) para crear un delegado alrededor de una expresión. Una acción es algo para invocar, sin retornar un valor (una rutina, en vez de una función). Un Action<string> es una rutina que recibe un parámetro string. Un Action sin nada más, no tendría parámetros.

¿Cómo usamos una variable y le asignamos un valor? Veamos un ejemplo:

// string x = "Hello, Assign!";
// Console.WriteLine(x);
ParameterExpression x = Expression.Variable(typeof(string), "x");
Expression blockExpression = Expression.Block(
    new ParameterExpression[] { x }, 
    Expression.Assign(x, Expression.Constant("Hello, Assign!")),
    Expression.Call(method, x));
Expression.Lambda<Action>(blockExpression).Compile().Invoke();

 

 

Noten que el Expression.Block recibe un enumerable de ParameterExpressions, y luego un param array (una cantidad variable de argumentos) con Expressions que constituyen el cuerpo del bloque que vamos a ejecutar.

En el próximo ejemplo, implementé un código C# (descripto en el comentario, pero código inválido), que luego implemento en DLR: un condicional que retorna un valor:

// x = "Hello";
// if (true)
//     x.ToLower();
MethodInfo toLowerMethod = typeof(string).GetMethod("ToLower", new Type[] {});
ParameterExpression y = Expression.Variable(typeof(string), "y");
ParameterExpression z = Expression.Variable(typeof(string), "z");
Expression blockExpression2 = Expression.Block(
    new ParameterExpression[] { x, y},
    Expression.Assign(x, Expression.Constant("Hello")),
    Expression.Condition(Expression.Constant(true),
        Expression.Call(x, toLowerMethod),
        Expression.Default(typeof(string)),
        typeof(string))
        );
string result = Expression.Lambda<Func<string>>(blockExpression2).Compile().Invoke();
Console.WriteLine(result);

 

 

La primera expresión en el bloque es la asignación de la constante “Hello” a la variable x. Noten que cualquier variable es inyectada como parámetro en un bloque. Esta es la forma de declarar variables en bloques de expresiones DLR. Hay una Expression.Condition que toma como parámetros a una expresión booleana, una Expression que se evalúa si la condición es verdadera, una Expression que se evalúa si la condición es falsa,  y el tipo del valor a retorna. Este tipo de condición es similar al operador ternario ?: de C#.

Principal fuente consultada para este ejemplo: “Pro DLR in .NET 4” de Chaur Wu.

Próximos paso: compilar expresiones más complejas, expresiones binarias, expresiones IfThenElse, y más.

Nos leemos!

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