May 2010 - Posts
El año pasado, me uní un equipo de desarrollo en un proyecto privado. La solución inicial era una aplicación Web VB.NET, que estaban escribiendo, con proyectos de librerías de clases, usando el Mere Mortals Framework. El equipo había escrito varias páginas webs (y algunos formularios WinForm), cubriendo algunos casos de usos sencillos que se estaban comenzando a implementar. La base de datos era (y es) SQL Server 2008. No es un proyecto público, así que puedo entrar en mayores detalles, pero puedo escribir en rasgos generales sobre la historia del desarrollo.
Había ya varias entidades en el dominio, y se venían más. Para cada entidad, había que escribir muchos archivos: las clases de Mere Mortal framework, sus clases de validación, de acceso a datos, los comandos DDL de la base, procedimientos almacenados, páginas web iniciales, etc. Entonces, comencé a migrar la solución a generación de código, usando mi proyecto de generación de código AjGenesis (mi proyecto favorito :-). Pueden leer algo de esa experiencia en
Code generation for Mere Mortals Framework
Generación de código para Mere Mortals Framework
Esto es lo que llamo: “ajgenetizar” una aplicación. Dada una solución andando, elevar el nivel de abstracción, descubrir las abstracciones que necesitamos para modelar el sistema en construcción, encontrar el código similar repetitivo, las partes que sí tenemos que escribir manualmente, y entonces, poner todo es en el proceso de generación de código. El código generado debe reflejar una solución preexistente: debe ser código del que uno esté orgulloso.
El modelo inicial fue obtenido desde la base de datos. Como escribí en otros posts, esto no es el modelo ideal. Pero fue una decisión pragmática. Escribí hace un tiempo:
AjGenesis – Generating the model from the database
AjGenesis – Generando el modelo desde la base de datos
Generating a Model from the Database using AjGenesis
Generando un modelo desde la base de datos usando AjGenesis
Models for Code Generation in AjGenesis
Modelos para la generación de código en AjGenesis
Despues de obtener una solución andando, que podíamos extender manualmente o automáticamente agregando más al “modelo” de la base, fuimos migrando a un modelo abstracto. Entonces, despues de unas semanas usando la base de datos como modelo inicial, la propia base de datos comenzó a generarse desde el nuevo modelo abstracto, y la dirección del proceso fue en reverso! Ahora, cada entidad es agregada al modelo abstracto, y cualquier idea nueva de implementación puede agregarse a los templates y tareas de generación. Mucho de los artefactos de texto (clases, archivos de configuración, comando de la base de datos, proyectos, páginas web) son generados por el proceso de generación de código.
Este año, migré los templates para remover el framework Mere Mortals, usando ahora nuestro propio acceso a datos, relaciones una a varios, lazy loading, identity map, cache de otros datos, validación, StructureMap como contenedor de Inversion of Control, interfaces para abstracciones que fuimos descubriendo, services layers, etc… La parte interesante es que pudimos cambiar gran parte de la infraestructura de una solución a otra, pero sin mucho esfuerzo. Ya habíamos empezado a trabajar con service layer, en vez de ir directamente contra el framework MereMortals, y eso facilitió varias partes de la migración. Las partes manuales fueron pasadas a la nueva solución, pero el modelo es todavía el mismo modelo abstracto, serializado en XML, que teníamos antes. Y si necesitamos adoptar un ORM, si elegimos ese camino, podemos cambiar la generación para soportar eso, tenemos varios tests (no diría unitarios) que soportan el detectar cualquier cambio erróneo que tenemos. O podemos adoptar ASP.NET MVC2, u otra solución para diferentes problemas (persistencia, validaciones, tests, presentación, etc..)
Y, estoy seguro que el modelo podría ser usado para generar el núcleo de la aplicación en otra tecnología o lenguaje. No es un requerimiento de este proyecto. Pero es una especie de “prueba ácida” para nuestro modelo abstracto: si necesitáramos cambiar de base de datos, o de lenguaje de implementación, o alguna tecnología, todo está en su lugar listo para adoptar el cambio. Incluso, lo aprendido puede servir como base para otros proyectos.
Cada semana, el equipo está agregando nuevas entidades en el dominio, al avanzar en la implementación de las historias planteadas. Y se han podido ir agregando en el modelo abstracto: muchas de las “technicalities” (crear tablas e índices, procedimientos almacenados, métodos de acceso a datos, relaciones en código, etc… ) son generadas automáticamente. Y lo manual está claramente delimitado. El equipo, entonces, puede poner su esfuerzo y foco en la lógica del dominio y en los detalles de presentación.
Para mí, ha sido una prueba del poder de la generación de código desde un modelo: no es sólo generación de código. El punto clave es tener un modelo que nos ayude a representar la solución que estamos armado, separando problemas (persistencia) de soluciones técnicas (MereMortals, ADO.NET o algún ORM). Y tenemos la opción de cambiar y mejorar lo que estamos generando para el proyecto.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
El pasado fin de semana, estuve agregando características a mi intérprete de código abierto AjSharp, para que comenzara a soportar ejecución distribuida. Escribí sobre el tema en:
Distributed AjSharp: First Steps
AjSharp Distribuido: Primeros Pasos
(más post en español http://msmvps.com/blogs/lopez/archive/tags/AjSharp/default.aspx)
(más post en inglés/Anglish (Angel´s English :-) http://en.wordpress.com/tag/ajsharp/)
En esta semana pasada, escribí más código para soportar la ejecución distribuida de una aplicación AjSharp. Es un “work in progress”. De alguna manera, es la continuación de mi trabajo con aplicaciones distribuidas, que comenzó luego de mi trabajo con Fabriq, antes un poco con AjServer, luego con AjMessages, y así. La escritura de un intérprete propio permite extender el lenguaje para soportar características que tal vez se complicarían de implementar en lenguajes tipados, compilados.
En este post, quiero escribir una lista de features que me gustaría agregar (algunas ya están agregadas en el código de trunk, pero tengo que revisarlas, probarlas mejor y escribir posts sobre cómo usarlas y cómo funcionan). Antes, algunas aclaraciones de nomenclatura:
Machine.Current es un objeto base que mantiene el Environment global (Machine.Current.Environment), que contiene los nombres/valores de las variables globales, las definiciones de las clases, funciones globales, etc.. Host es un objeto que expone una Machine para que sea accedida desde otros Host. Machine es un concepto básico de AjSharp/AjLanguage. Host es lo que le agrega funcionalidad de comunicación remota.
Esta es la lista de lo que quiero implementar:
- Arrancar un host local en una dirección (máquina física, puerta)
- Conetar con un host remoto dada una dirección
- Conectar a un host remoto y enviarle la dirección de un host (local o remoto) para que pueda ubicarlo y enviarle trabajo
- Ejecutar un callback (función, rutina) local cuando un host local reciba la dirección de un nuevo host existente en alguna máquina (una especie de OnRegisterHost).
- Enviar un comando definido localmente (en el programa enviador) a un host remoto, y ejecutar en ese host remoto.
- Enviar una expresión definida localmente a un host remoto y evaluarla en ese host remoto, retornando un resultado al host llamador.
- Enviar una función/subrutina definida localmente, a un host remoto, enviarle parámetros y evaluarla/ejecutarla en el host remoto.
- Enviar un texto al host remoto, parsearlo y ejecutarlo como comando.
- Enviar un texto al host remoto, parsearlo y evaluarlo como expresión, devolviendo un resultado.
- Enviar el contenido de un archivo local a un host remoto, parsearlo y ejecutarlo.
- Obtener la lista de host locales registrados en la máquine (machine) actual.
- Obtener la lista de host remotos registrados en la Machine.Current.
- Enviar un valor local a una variable o left value expression a un host remoto.
- Enviar una copia de un DynamicObject a un servidor remoto (tengo que resolver qué pasas si es DynamicObject con una clase asociada)
- Enviar una referencia a un objeto DynamicObject al host remoto, para usarla allá como un proxy al objecto original, que sigue residiendo en el host local.
- Enviar una copia de un agente a un host remoto, y arrancarlo para que ejecute tareas allá.
- Exportar un archivo local con código fuente AjSharp, para ser usado en cualquier Include(“…”) que aparezca en el proceso de parseo del host remoto.
- Exportar un assembly local a un host remoto (tengo que decidir si ahora necesito o no esta feature, interesante).
Otro punto más:
- Una aplicación de ejemplo, como “proof of concept”. Podría ser un web crawler distribuido, o la implementación de un algoritmo genético distribuido.
Pueden ver el progreso en:
http://code.google.com/p/ajcodekatas/source/browse/#svn/trunk/AjLanguage
Agregando todas estas features, y tener además go routines, futures, channels, y agentes, está haciendo interesante a este proyecto. Y me estoy “divigtiendo como loco” :-):-)
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Este sábado que viene, 22 de Mayo, la gente de la comunidad ALT.NET Hispano presenta una VAN, des-conferencia virtual, sobre NoSQL (Not-Only SQL). La reunión será a las 18hs GMT (15hs acá en Buenos Aires), y tendré el gusto de ser el presentador del tema. Escribía hace un tiempo en la lista de la comunidad:
El movimiento NoSQL apareció promoviendo el uso de almacenes de datos no relacionales. Surgió de varias fuentes y motivaciones, y tiene sus raíces aún en implementaciones anteriores a la aparición del modelo relacional.
Pasaremos revista, un poco a la historia, un poco a las primeras grandes implementaciones como BigTable de Google, o el Dynamo de Amazon. En los últimos años a aparecido una plétora de implementaciones, y se ha generado discusión sobre relacional vs NoSQL, cuándo, porqué.
Cómo cambia el diseño de una aplicación "normal" en NoSQL.
Queries, no más joins, denormalización.
No más esquemas.
Características deseables: cómo consiguen escalabilidad, alta disponibilidad, alto rendimiento.
El teorema CAP
Distintas formas de implementación:
Distribuidas vs No Distribuidas
En memoria vs En Disco
Key-Value vs Document vs Graph vs Column
Eventual Consistency
Proyectos más conocidos: Voldemort, Cassandra, CouchDB, MongoDB, SimpleDB, Memcached, BigTable, Dynamo, HBase...
Programaremos finalmente en .NET contra una de esas implementaciones, posiblemente MongoDB.
Espero que al final de la charla, todos tengamos una idea general de NoSQL, algunas características, código de ejemplo, disponible. Y entender, que al final, es una herramienta más: habrá casos en los que es más aplicable y otros en los que no.
Me faltó agregar: ACID vs BASE, veremos esas siglas y comparación. Para mí, el tema es muy interesante. Esta es una charla de introducción, para quien esté interesado en el tema pero todavía no pudo dedicarle mucho tiempo a investigarlo. Es un tema amplio, pero espero poder transmitir el panorama más completo de lo que está pasando con NoSql.
Mis enlaces sobre el tema:
http://delicious.com/ajlopez/nosql
Seguramente al tiempo de participar de la VAN, escribiré acá los recursos que usé para prepararla, más detalladamente, así como la presentación y más enlaces. La gente de ALT.NET Hispano luego se ocupa de preparar un página con esos recursos y hasta publica un video de la VAN.
Como siempre, recuerdo al bueno de @jorgegamba:
Hay que aclarar que no se requiere ningún tipo de registro, simplemente acudir el día y la hora indicados a la dirección Web http://snipr.com/virtualaltnet, eso sí, deberán tener instalado el programa cliente de Live Meeting; hay más instrucciones sobre cómo hacer esto y otras indicaciones en la página wiki Descripción de Reuniones.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Fue un gran fin de semana, con code kata. En la tarde del sábado, comencé a jugar con serialización de comandos en mi intérprete AjSharp:
En ese momento estaba usando Windows Communication Foundation, con simple BasicHttpBindind y address. Elegí serializar comandos y expresiones en arreglos de bytes, usando BinaryFormatter, y enviarlos via WCF básico (No me gusta pelearme con serialización WCF).
Entonces, el domungi, escribí una implementación usando remoting. Es una mejor aproximación a esta situación: remoting me de soporte “out-of-the.box” para serialización de grafos de objetos, y el manejo de MarshalByRefObject, lo que es bueno para mi proyecto.
Mis primeros intentos usando remoting:
Noten el uso de las nuevas keywords expression y command. En este comando:
a = expression b+c;
se asigna una expresión b+c (pendiente de evaluación) a una variable local a. Podemos evaluarla con:
result = a.Evaluate(Machine.Environment);
(Machine es la máquina actual en ejecución, tiene un .Environment global, donde están los bindings para b y c, sus valores asociados).
El comando:
a = command PrintLine(“Hello, world”);
no imprime un mensaje. Almacena el comando en una variable local, para ser ejecutado más adelante como:
a.Execute(Machine.Environment);
En el ejemplo de arriba, podemos arrancar a un servidor programáticamente. Podemos también crear el objeto proxy a ese servidor en el cliente. Y entonces, podemos invocar comandos, o evaluar expressiones, en el otro servidor. Después de tener eso andando, agregué el llamado de funciones, pasando argumentos al servidor. Esta es la principal interface que fue surgiendo, IHost:
public interface IHost
{
// Host Id
Guid Id { get; }
// Host Invocation
void Execute(ICommand command);
object Evaluate(IExpression expression);
object Invoke(ICallable function, params object[] arguments);
// Others... Work in progress... to review
}
Un host se ejecuta en una máquina, y expone el acceso a esa máquina, con invocaciones de comandos, funciones y evaluaciones de expresiones. Hay host que son locales (class Host), y hosts que exponen su funcionalidad via remoting (RemotingHostServer), y que se consumen desde su correspondiente cliente proxy (RemotingHostClient). Estoy también trabajando en tener esas clases en WCF: hay un WcfHostServer, WcfHostClient, pero tengo que luchar con temas de serialización, todavía.
Debería agregar el pasar strings conteniendo commandos y expresiones, y que el servidor receptor los parsee y ejecute/evalúe (sería más fácil que enviar lo que estoy enviando ahora, el ICommand, IExpression ya armado).
Después de las pruebas exitosas de arriba, agregué “syntax sugar”: no hay que minimizar el efecto de una buena sintaxis, que puede simplificar el uso de una característica. Agregué la keyword at en AjSharp:
Podemos invocar un comando en el otro server usando:
at <host> <command>;
o podemos evaluar una expresión en otro servidor y devolver el resultado:
localvar = at <host> <expression>;
Tengo que trabajar más en algunos detalles de serialización. Resolví parte del callback al servidor. Esto es:
at host { adam = new DynamicObject(); adam.Name = “Adam”; adam.Age = 800; }
myadam = at host adam;
adam se crea en el host remoto. La variable local myadam, cuando uso remoting, es en realidad un transparent proxy que apunta al DynamicObject que todavía está en el host donde fue creado (hasta ahora, los DynamicObject los he puesto descendiendo de MarshalByRefObject; estoy pensando cambiar esta decisión, y hacer que se serializen por defecto, y agregar un método, tipo obj.AsProxy() para generar una referencia MarshalByRefObject explícitamente cuando el programador así lo solicite). Pero el transparent proxy que recibo no puede ser invocado directamente: no tiene un canal asociado de comunicación. Así que agregué un wrapper a ese objeto cuando lo recibo en el cliente. Si invocamos algo de myadam, como en:
PrintLine(myadam.Name);
myadam.Name = “NewAdam”;
el wrapper redirecciona todo a que se ejecute en el servidor que fue invocado, y la operación se ejecuta en el servidor.
Como siempre, pueden bajar y examinar el código desde:
http://code.google.com/p/ajcodekatas/source/browse/
en el directorio trunk/AjLanguage.
Tengo que confesar que estoy orgulloso de este avance en mi intérprete. Podría extender, llegado el caso, esta capacidad para otros intérpretes, como AjIo,, AjTalk (era la idea inicial de AjTalk, tener un Smalltalk-like VM con objetos distribuidos). Nació sólo como una idea, pero va tomando forma, un lenguaje distribuido es el camino a explorar para poder aprovechar más máquinas en algunas tareas. El proyecto es un bebé todavía, pero es mi bebé, y me divierte mucho codificarlo.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Mañana sábado a las 18 GMT (14hs 15hs acá en Buenos Aires) tenemos una nueva edición de las VAN reuniones virtuales, des-conferencias, organizadas por la comunidad ALT.NET Hispano. Esta vez, la introducción del tema, BDD, está a cargo del bueno de Hernán García (@theprogrammer en Twitter, blog: The Dynamic Programmer) (“el bueno” porque hace RT de mis post en Twitter…. :-) :-).
Escribe Hernán en la lista de ALT.NET Hispano:
Esta es una lista de los temas que espero desarrollar en la reunion
sobre Behavious Driven Development o BDD
- Que es BDD?
- Que son las Historias de usuario y quien las escribe
- Introduccion a Gherkin
- Que es Contexto / Especificacion
- Que es GWT (Given, When, Then)
- Especificaciones ejecutables.
- BDD and unit testing.
- Ejemplos con: StoryQ, StorEvil and SpecFlow
La fecha es el sabado 15 de Mayo.
Recuerden lo que escribía Jorge Gamba sobre estas reuniones:
Hay que aclarar que no se requiere ningún tipo de registro, simplemente acudir el día y la hora indicados a la dirección Web http://snipr.com/virtualaltnet, eso sí, deberán tener instalado el programa cliente de Live Meeting; hay más instrucciones sobre cómo hacer esto y otras indicaciones en la página wiki Descripción de Reuniones.
Mis enlaces sobre el tema BDD:
http://delicious.com/ajlopez/bdd
Les adelanto que el sábado 22 de Mayo, daré el puntapié inicial de VAN sobre el tema NoSQL, ya vendrá post con temario más detallado.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Se acerca la conferencia Code Generation 2010 en Junio, del 16 al 18, en Cambridge, Reino Unido:
http://www.codegeneration.net/cg2010/index.php
The Code Generation conference is Europe's leading event on Domain-Specific Languages, Model-Driven Software Development and Code Generation. The event has a strong practical focus and an emphasis on sharing experiences and knowledge. A range of sessions from beginner to expert is included.
Ya saben, soy un entusiasta de la generación de código basado en un modelo de libre definición. Es interesante ver que hay gente interesada en generación de código, usando modelos, DSL (Domain Specific Languages), DSM (Domain Specific Models), MDD, etc. Me gusta el “subtitle”: Raise your level of abstraction. Sí! Ese es el punto clave: hay tantas “technicalities” en nuestro trabajo del día a día, que uno se pierde en los árboles, sin llegar a ver el bosque. Tantas librerías, APIs, archivos de configuración para escribir, que estamos perdidos en el medio de tantos detalles. El desarrollo de software es una actividad fascinante. Pero algunas veces puede ser una tarea enorme.
Leo en la página:
WHO'S CG2010 FOR?
CG2010 is for people who want to successfully apply or just learn more about the following topics:
* Code Generation !
* Domain-Specific Languages
* Model-Driven Software Development
* Model-Driven Architecture
* Eclipse Modelling Tools
* Executable UML
* Software Factories and Software Product Lines
* Generative programming and other similar approaches.
The focus throughout the event is on practical experience of these tools and technologies with a range of sessions from beginner to expert.
Un buen ejemplo de lo que podemos esperar de esta conferencia:
Dave Thomas
KEYNOTE - The Imaginary Sickness of the Middle-Class Gentleman
"For more than forty years I have been speaking prose without knowing anything about it…”
So says M. Jourdain in Le Bourgeois Gentilhomme. But, writing 340 years ago, Molière could have been writing about me. For I too have been writing a kind of prose—Domain Specific Languages—for about 40 years. Now, like Jourdain, I find there's a name for what I do, and I find that there are professors studying it and conferences discussing it. How exciting!
But as Molière also said, “Nearly all men die of their remedies, and not of their illnesses.” And that's a trap we seem to be rushing towards with our new enthusiasm for DSLs. So in this talk we'll look at DSLs, and why most of them seem to have too little D and too much L. Bring rotten fruit.
Dave Thomas is a programmer.
Es bueno leer “is a programmer”. Como todos nosotros.
Hay un video que comenta la conferencia del 2009:
Es bueno ver tanta actividad en este tema. Hay un sitio de comunidad para la gente interesaada en MDD y temas relacionados en:
http://www.modeldrivensoftware.net/
Pueden seguir a su organizador, @MarkDalgarno en Twitter (él está también interesado en Lisp, como estoy yo ;-)… tenemos que unir los dos intereses, generación de código y Lisp).
De mi parte, tengo que postear nuevos ejemplos e ideas usando mi proyecto de código abierto AjGenesis
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
En estos días, he estado escribiendo un intérprete tipo lenguaje Io, en C#. Se llama AjIo (¿de qué otra forma podría llamarlo? :-). Escribí sobre el tema en mis anteriores posts:
Working in AjIo: Io-like interpreter in C#
AjIo: Intérprete tipo Io en C#
Ahora, quisiera discutir el diseño que adopté para soportar objetos enAjIo. Este intérprete no es un Io verdadero, no es una implementación exacta del lenguaje Io. Es mi proyecto, y mi intención es reescribir Io, parcialmente, para que pueda usar objectos nativos de .NET y acceder a toda su librería de clases. Soy un entusiasta de usar las Virtual Machine existentes (.NET, Java) y sus librarías de clases, para reimplementar sobre ellas lenguajes dinámicos, funcionales o de otro tipo.
La interface IObject es la madre de todos los objetos en AjIo:
Más detalle en el código fuente:
namespace AjIo.Language
{
public interface IObject
{
string TypeName { get; }
IObject Self { get; }
IObject Parent { get; }
object Evaluate(object expression);
void SetSlot(string name, object value);
object GetSlot(string name);
void UpdateSlot(string name, object value);
}
}
Los métodos de slot son usados para implementar propiedades dinámicas en los objectos AjIo. Un objeto AjIo no tiene predeterminadas propiedades, sino que se pueden agregar (definir con valores) en cualquier momento de la ejecución. El método UpdateSlot necesita que el slot esté previamente definido. Vean que UpdateSlot y SetSlot reciben como valor (segundo parámetro) NO un IObject, sino un object nativo de .NET cualquiera.
La propiedad TypeName es usada para imprimir un objeto. Esto es, evaluando:
Object clone
imprime como
Object_14fd2b5
El prefijo “Object” es el nombre del tipo del nuevo objecto. Notar que Object es un objeto en AjIo, no es el nombre de una clase. Y es el objeto “tope” de toda la jerarquía.
La propiedad Self apunta al objeto en proceso. Puede que no sea el apuntado por la palabra C# this. Tendré que discutirlo cuando llegue, en otro post, al tema de los objetos locales.
El Io original es un lenguaje basado en prototipos. Cada objeto Io tiene un slot Protos, con la lista de prototipos de la que depende. Usando YAGNI, en lo que escribí todavía no necesité una lista de prototipos. Por lo tanto, sólo hay una propiedad Parent que apunta al padre del objeto, si existe. Hay un objeto que no tiene padre, y es el prototipo Object del que derivan todos los otros objetos AjIo.
El método Evaluate usualmente recibe un mensaje (que es un nombre más argumentos), pero, de nuevo, como quiero soportar objetos nativos, envío como parámetro a este método un object de .NET.
El proyecto es “work in progress”, la interface de arriba no está “esculpida en piedra”, y puede que sufra modificaciones en el transcurso del desarrollo. Estoy usando TDD: en el caso que necesite algo nuevo, lo agregaré, y los tests ya escritos me servirán de soporte para ver que todo siga andando. El proyecto va tomando forma, espero que queden pocos cambios pendientes en esta interface. El código fuente lo pueden encontrar en:
http://code.google.com/p/ajcodekatas/
en el directorio AjIo.
Próximos posts para escribir: descripción de las implementaciones iniciales de esta interface.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Ayer, en la charla de WordCamp Argentina que compartí con el bueno de @eglinsky, mencioné una pregunta que me hago desde el siglo pasado: ¿cómo será el software de la nave Enterprise? Había poco tiempo en la charla, y me limité a apuntar a los próximos años inmediatos del software. Pero quisiera hoy acá comentar cómo se me planteó esa pregunta, y algunas ideas de respuesta.
En los años ochenta y noventa, leía la revista Byte, que tan buenos números trajo en esos años (recuerdo uno dedicado a lenguajes de programación, donde conocí la programación funcional en detalle, y otro sobre Smalltalk; también algunos números dedicados a lenguajes en particular, creo recordar uno de Forth). Uno de sus columnistas habituales era Steve Ciarcia, la Circuit Cellar.
Pueden leer sobre Ciarcia en:
http://www.circuitcellar.com/
http://www.devili.iki.fi/library/author/203.en.html
Parece que muchas de sus columnas están en línea, o están en forma de libros expuestas en Google. Pero no pude encontrar una en especial. No creo que era una columna, era un recuadro en alguno de sus artículos, aparecido, que recuerde, en los noventa (puede que fuera un Ask Byte, otra columna que escribía). Ahí, Ciarcia explicaba que había recibido una carta de un grupo de estudiantes de una universidad norteamericana. Se había propuesto escribir todo un informe/libro sobre cómo construir una Enterprise, la nave de Star Trek (conocida por acá como Viaje a las estrellas). Y estaban consultando a expertos en diversos campos. La consulta a Ciarcia era sobre el hardware y software de la Enterprise.
Me gustaría tener la respuesta de Ciarcia acá. Lo que escribo ahora es sólo de recuerdo, lo que me llamó la atención. Escribía Ciarcia que para responder rápidamente a situaciones críticas (imaginen viajes a la velocidad de la luz, etc), diversos partes de la Enterprise debían ser autónomas, controladas por computadoras, que trabajan cada una en su tema. Y que habría una red de esas computadoras. Era como si el Enterprise fuera un organismo (no sé si llegaba a ese punto la descripción de Ciarcia, o es algo que agregué yo).
Pero ese artículo me sirvió para retomar lo que venía pensando de los ochenta: la necesidad de encarar programas que actuaran de forma distribuida, y quizás, en paralelo. Eso me había venido de las lecturas sobre limitaciones en Inteligencia Artificial, y la observación que hacían otros sobre cómo funcionaba el cerebro humano, y también los organismos. Siempre me quedó que la computación distribuida es un tema muy interesante de seguir. Es más que map/reduce, es hacer que una red de computadores trabaje para resolver un problema. En los noventa aparecieron proyectos exitosos, como Beowulf (cluster con Linux, solían estar en http://www.beowulf.org/), no exactamente lo que buscaba, pero daban una punta para usar computadoras comunes, para ejecutar una tarea distribuida. Google ha sido el gran explotador de esta idea: gran parte de Google ejecuta sobre un conjunto inmenso de computadores “normales”, lo que les permite escalar “horizontalmente”: para atender a más pedidos, simplemente agregar más máquinas, y en caliente. Igual, no era eso lo que estaba buscando. Cuando luego, en este siglo, descubrí a Fabriq de @asehmi y su host=”*” (indicar que una tarea, dentro de una serie de tareas, se puede instalar y ejecutar en cualquier nodo de una red de trabajo), me sirvió de inspiración para explorar cosas como AjAgents, AjMessages, y AjProcessor, pensando últimamente cada vez más en Actor Model, pero distribuido, y en agregar agentes distribuidos a AjSharp.
Pero volvamos a la pregunta inicial: ¿cómo será el software de la Enterprise? Digo como broma: ¿Qué está viendo Spock cuando en una pantalla busca información del nuevo planeta que están por visitar? ¿Google o Microsoft? :-)
Es muy difícil saberlo. En los siglos que “faltan” para llegar a la Enterprise, el software puede evolucionar, dar paso a otra cosa, y desaparecer. Hoy ya es una industria madura. Pero no se me ocurre algo que lo reemplace. Concuerdo con Ciarcia: el software de la Enterprise, será distribuido. Eso es lo que puedo afirmar. En la ejecución de software distribuido está la clave para conseguir más de lo que hasta ahora conseguimos, en la resolución de problemas, en escalabilidad, en robustez, etc… La aparición de "el cloud” se puede ver como un inicio hacia eso. Dónde se ejecuta una pieza de una aplicación, tendrá cada vez menos importancia.
Pero lo que de alguna forma disparó en mi mente la pregunta que le hicieron a Ciarcia: ¿cuál es el futuro de la computación?
Algunos puntos de acá a un par de siglos:
- Computación ubicua: software corriendo sobre hardware que está en todas partes: en las paredes, mesas, etc…. Desaparición de la computadora personal: habrá software y datos personales. Me acerco a una pared, y puedo dar mi presentación, que aparece en ella, recuperada desde una “gran nube”. O pasar mi multimedia en la “pared”. Una especie de Max Headroom: todo está disponible en todas partes.
- Computación en cada elemento físico: desde contenedores, a piezas de automóviles, software revisando el funcionamiento o la posición del material, dando esos datos a una red global, extensión de lo que es hoy Internet. Cada dispositivo (TE móvil, heladera, auto, camión, … ) conectado a esa red.
- El ascenso de Inteligencia Artificial realmente operativa. La formación de robots autónomos, “organismos” que aprender a interactuar en su entorno, ya sea con inteligencia o con menos. Exploración del espacio usando esos “organismos”.
- Potenciación de toda actividad científica con la ayuda del software/hardware: desde las ciencias duras, hasta las matemáticas, serán afectadas (ya lo están siendo) por el poder de computación (para simulaciones, resolver problemas) que harán de cada uno de los investigadores, o de un grupo, un Polymath. Justamente, en matemáticas se está planteando el uso de gran poder de computación en algunos temas, ver http://polymathprojects.org/. Pero imagino también la aparición de “organismos matemáticos” que, basados en Inteligencia Artificial, como hacía el programa Eurisko de Douglas Lenat en los ochenta, se sumerjan en la exploración de nuevas ramas de las matemáticas, por sí mismos.
- La evolución de la web semántica a un repositorio de conocimiento humano (no sólo información, sino conocimiento). Programas que operan sobre eso, logrando más información o, incluso, conocimiento.
- Como ahora está pasando, cambio en las relaciones y métricas humanas: el trabajo en grupos distribuidos será cada vez más habitual. Todo software y hardware que aparezca para conseguir eso, será adoptado. No creo que desaparezca el grupo humano en contacto físico: lo que veo, es que grupos físicos trabajaran en colaboración con otros grupos que están distribuidos en el planeta.
- Agentes artificiales para casi todas las tareas que hoy delegamos en personas, o tenemos que hacer nosotros mismos.
- Integración de hardware/software con el cuerpo humano. Si se da, será para reparar deficiencias de un individuo. No creo que haga falta para potenciarlo. Simplemente con tener agentes que hagan nuestro trabajo, rutinario o no, no será necesario integrar software y hardware en nuestro cuerpo para incrementar las capacidades de un ser humano. Ejemplo: no hace falta tener más memoria, implantar en nuestro cerebro algo de hardware/software que potencie esa parte. Simplemente, delegaremos ese tema a toda Internet o a lo que venga.
- Reproducción de nuestra mente: más especulativo, pero podría haber algún camino. Una réplica nuestra, o varias, programadas con nuestros gustos, intereses, que sirva como “gran agente” para potenciar las actividades de cada uno.
Otras ideas?
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Ya escribí sobre el tema en:
Hacia un Hospital Information System de Código Abierto
Hacia una Historia Clínica Digital de Código Abierto
Quería pasar acá en limpio algunos puntos a explorar. Esto es sólo un borrador, pero para ir pasando en limpio algunos temas. Veo que es un proyecto demasiado ambicioso, pero no por eso puedo dejar de ir pasando esto por escrito. Veremos en qué derivan todas estas ideas.
Principales Entidades
Persona: Datos de un ser humano, en general.
Profesional Médico: Rol de Persona; médico/a, enfermero/a, etc.
Paciente: Rol de Persona.
Entidad Médica: Hospital, Institución, empresa con lugar físico. No contemplaría todavía sucursales. Tiene consultorios, y si admite internación, también sectores, habitaciones, camas.
Financiador: Empresa que financia el tratamiento de un paciente, si éste no se atiende en forma particular. La persona puede tener 0, 1, o varias financiadoras. Una obra social, una medicina prepaga, son ejemplos de empresas financiadores.
Proveedor: De insumos en general, para la Entidad Médica.
Medicamento: Lo que se le suministra al paciente, que entre legalmente como medicamento. No es comida. Es una entidad a analizar: puede tener una o varias drogas principales, tiene presentación (ej. grageas, en envase de 30), nombres comerciales. No sé cómo llamar a los distintos tipos de presentación: solución, grageas, pomada… etc.
Insumo médico: Otros insumos, como inyecciones, cánulas, etc… que se usan en el tratamiento de un paciente, pero no son medicamentos.
Historia Clínica: Asociada por paciente. Debe tener la capacidad de albergar tipos de items definibles por cada implantación del sistema (mi approach: tener puntos de extensibilidad, donde agregar nuevos tipos de items (modelo) y nuevas formas de mostrarlos (vistas) y manipularlos)
Procesos
Atención ambulatoria: atención de paciente en consultorio
Atención de internación: atención de paciente en habitación/cama.
Indicación médica: el médico anota el posible diagnóstico e indica el tratamiento: prácticas de laboratorio, otras prácticas (kinesiología, p.ej.), medicamentos, dieta.
Dispensación desde Farmacia: la entrega de medicamentos e insumos médicos, desde Farmacia, si existe.
Suministro por Enfermería: el suministro de los medicamos prescriptos en la indicación médica, por enfermeros/as.
Prácticas de Laboratorio: toma de muestras, análisis y sus resultados.
Stock de Farmacia e Insumos Médicos: control de lo dispensado a Enfermería u otros sectores, y lo devuelto.
Turnos: Asignación de turnos de consultorio a pacientes ambulatorios.
Liquidación a Financiadores: pasaje de las prácticas efectuadas, medicamentos suministrados por paciente, a su correspondiente Financiador.
Liquidación de Honorarios: a personal médico.
Compras y Proveedores: Clásico
Caja: cobranza directa a paciente, pago a proveedores, etc.
Tengo que revisar hasta donde llegan las implementaciones de otros sistemas de código abierto que encontré y mencioné en los pasados posts, o sea, cuánto de estas entidades y procesos se atreven a cubrir. Como decía en el último post, el problema es que no hay un cliente final concreto que pida estas características. Pienso que un buen punto de entrada, ni trivial ni super complejo, debe ser el de asignación de turnos. Puntos que deberá resolver, seguramente por puntos de extensión a proveer en cada caso: aceptación del paciente (si está habilitado por su financiador o no, si las prácticas están habilitadas o no, requisitos antes de la consulta (como venir en ayunas…), etc…)
Bueno, como dice Linus Torvalds, talk is easy, show me the code. Es proyecto demasiado ambicioso, pero es hora de por lo menos intentar modelar e implementar algo. Próximo post, deberá venir con código.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
El próximo sábado, 8 de Mayo, se realizará el encuentro anual WordCamp de Argentina, dedicado a usuarios del software de blogging Wordpress:
http://argentina.wordcamp.org/
Creo que ya hace tiempo está lleno el cupo de asistentes. El lugar del evento serán las oficinas de Microsoft Argentina, aquí en Buenos Aires.
Gracias a una invitación del bueno @eglinsky, daré con él una charla sobre algunos temas. Esta es la agenda de las charlas planeadas, espero que nos toque el mediodía como dice ahí, porque despues estoy de mudanza de libros y de cubil:
http://argentina.wordcamp.org/agenda/
Vamos a presentar, comentar:
Windows Live Writer: software que estoy usando para escribir este post. Comentaré brevemente sobre la MetaWeblog API (ver http://en.wikipedia.org/wiki/MetaWeblog). Pueden leer
Coding blog engine with MetaWeblog API support and using it with Windows Live Writer
Mis enlaces sobre el tema en http://delicious.com/ajlopez/metaweblog. La estuve usando en un proyecto (sobre XML-RPC más algún código en C# que encontré en la web, creo que del artículo de MSDN MetaWeblogAPI C# Code Sample).
Windows Web Platform Installer: que nos permite instalar desde la web todo lo necesario para poder ejecutar Wordpress en Windows. Yo también voy a mostrar Wordpress andando sobre Windows, usando un Apache Friends XAMPP.
Silverlight Plugin for Wordpress: Cómo se instala, habilita y usa este plugin, que permite insertar una aplicación Silverlight en un post. Ver Silverlight for Wordpress
Silverligth Media Player for Wordpress: otro plugin dedicado a video, multimedia sobre Silverlight, lo que permite aprovechar Silverlight Streaming.
Bueno, tenemos bastante para mostrar en 45 minutos, algunos tips para usuarios/bloggers de Wordpress. Dos puntos interesantes, si quieren investigar: el uso creativo de la API de MetaWeblog (pueden publicar post desde sus sistemas), y aplicaciones RIA (Rich Internet Application) con Silverlight, para usar desde el blog.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Como mencioné en:
AjLisp family: Implementing Lisp Interpreters in C#
estuve trabajando en dos intérpretes Lisp: AjLisp y AjSharpure (un intérprete tipo Clojure). Pero quería explorar cuál es el núcleo del lenguaje, la mímima parte que debería ser implementada, para tener un intérprete Lisp.
Entonces, escribí AjCoreLisp. Pueden bajarlo del proyecto Google Code
http://code.google.com/p/ajlisp/source/browse/#svn/trunk/AjCoreLisp
Está implementado en C#. La solución:
tiene 5 proyectos:
AjCoreLisp: la librería de clases, núcleo del proyecto, implementando el lenguaje base, pero sin parser ni lexer, sólo en runtime de ejecución.
AjCoreLisp.Tests: como es costumbre, desarrollé la librería anterior usando Test-Driven Development. Este es el proyecto de tests de la librería.
MinimaLisp: Una prueba de concepto. Tiene lexer, parser, y una mínima máquina que define el ambiente inicial. Muestra el uso de la librería núcleo, construyendo un intérprete Lisp mínimo.
MiminaLisp.Console: el intérprete de consola interactivo.
MiminaLisp.Test: Tests TDD escritos para el desarrollo de MinimaLisp.
La interfaz raíz IExpression:
public interface IExpression
{
object Evaluate(IEnvironment environment);
}
Todo Lisp tiene soporte de lista. Esta es la IList interfaz:
public interface IList : IExpression
{
object First { get; }
object Rest { get; }
IList Next { get; }
}
No actualización de los campos de la lista, es inmutable. Si queremos agregar que pueda cambiarse, hay que derivar de este proyecto, y poner la nueva implementación en un nuevo proyecto (como podría ser MinimaLisp u otro). Notar que tomado de Clojure la idea de tener Rest and Next: la primera retorna un objeto. Uso la segunda cuando espero que el resto de la lista sea una lista también.
Todo form (cabeza ejecutable de lista) implementa IForm:
public interface IForm
{
object Apply(IEnvironment environment, IList arguments);
}
Entonces, la clase Form implementa IForm y IExpression:
public class Form : IForm, IExpression
{
private IList parameters;
private IIdentifier parameter;
private IList body;
private IEnvironment environment;
public Form(IList parameters, IList body, IEnvironment environment)
{
this.parameters = parameters;
this.body = body;
this.environment = environment;
}
public Form(IIdentifier parameter, IList body, IEnvironment environment)
{
this.parameter = parameter;
this.body = body;
this.environment = environment;
}
// ....
public object Evaluate(IEnvironment environment)
{
return this;
}
public virtual object Apply(IEnvironment environment, IList arguments)
{
IEnvironment newenv;
if (this.parameter != null)
newenv = this.MakeNewEnvironmentList(arguments);
else
newenv = this.MakeNewEnvironment(arguments);
return Machine.EvaluateBody(this.body, newenv);
}
// ....
}
Noten que Form no evalúa sus argumentos. Este es el trabajo de la clase derivada Function:
public class Function : Form, IExpression
{
public Function(IList parameters, IList body, IEnvironment environment)
: base(parameters, body, environment)
{
}
public Function(IIdentifier parameter, IList body, IEnvironment environment)
: base(parameter, body, environment)
{
}
public override object Apply(IEnvironment environment, IList arguments)
{
return base.Apply(environment, BaseForm.EvaluateList(arguments, environment));
}
}
Como es usual, macros tienen una “vuelta de tuerca”: evalúan su cuerpo, pero entonces, evalúan el valor retornado:
public class Macro : Form, IExpression
{
// ...
public override object Apply(IEnvironment environment, IList arguments)
{
object value = base.Apply(environment, arguments);
value = Machine.Resolve(value, environment);
return Machine.Evaluate(value, environment);
}
}
(Machine.Resolve está relacionado con una implementación de Delayed Evaluation, que uso para conseguir una especie de Tail Recursion). Ok, bastante código fuente por ahora. Miren el código del proyecto para más detalles. El punto principal es que AjCoreLisp implementa pocas primitivas:
El enlace de primitivas al ambiente actual es el trabajo del MinimaLisp Machine:
public MinimalMachine()
{
this.Environment.SetValue("first", new First());
this.Environment.SetValue("rest", new Rest());
this.Environment.SetValue("cons", new Cons());
this.Environment.SetValue("quote", new Quote());
this.Environment.SetValue("define", new Define());
this.Environment.SetValue("lambda", new Lambda());
this.Environment.SetValue("flambda", new FormLambda());
this.Environment.SetValue("mlambda", new MacroLambda());
this.Environment.SetValue("let", new Let());
this.Environment.SetValue("letrec", new RecursiveLet());
this.Environment.SetValue("eval", new Evaluate());
this.Environment.SetValue("if", new If());
this.Environment.SetValue("do", new Do());
this.Environment.SetValue("nil?", new IsNil());
this.Environment.SetValue("list?", new IsList());
this.Environment.SetValue("equal?", new IsEqual());
}
Basado ese conjunto de primitivas, pude escribir más funciones:
(define list x x)
(define definem
(mlambda x
(list
'define
(first x)
(cons 'mlambda (rest x))
)
)
)
(define mapfirst (fn lst)
(if (nil? lst)
nil
(cons
(fn (first lst))
(mapfirst fn (rest lst))
)
)
)
(define mapcond (fn lst)
(if (nil? lst)
nil
(if (fn (first lst))
(cons
(first lst)
(mapcond fn (rest lst))
)
(mapcond fn (rest lst))
)
)
)
(define append (x y) (if (nil? x) y (cons (first x) (append (rest x) y))))
(definem cond lst
(if (nil? lst)
nil
(list
'if
(first (first lst))
(cons 'do (rest (first lst)))
(cons 'cond (rest lst))
)
)
)
(define atom? (x)
(cond
((nil? x) t)
((list? x) nil)
(t t)
)
)
(definem and lst
(if (nil? lst)
t
(list
'if
(first lst)
(cons 'and (rest lst))
nil
)
)
)
(definem or lst
(if (nil? lst)
nil
(list
'if
(first lst)
t
(cons 'or (rest lst))
)
)
)
(define not (x)
(if x
nil
t
)
)
(definem backquote (lst)
(cond
((nil? lst) nil)
((atom? lst) (list 'quote lst))
((equal? (first lst) 'unquote) (first (rest lst)))
((and (list? (first lst)) (equal? (first (first lst)) 'unquote-slice)) (list 'append (first (rest (first lst))) (list 'backquote (rest lst))))
(t (list 'cons (list 'backquote (first lst)) (list 'backquote (rest lst))))
)
)
(definem while lst
(list 'if (list 'not (first lst)) nil (cons 'do (rest lst)) (cons 'while lst))
)
Me gusta mi implementación de backquote (para usar en expansión de macros), un mini “tour-de-force” de este lenguaje. Estos tests dan verde (notar el uso de unquote y unquote-slice):
this.EvaluateAndCompare("(backquote (a b c))", "(a b c)");
this.EvaluateAndCompare("(backquote (a (b c) d))", "(a (b c) d)");
this.Evaluate("(define x '(b b))");
this.EvaluateAndCompare("(backquote (a (unquote x) c))", "(a (b b) c)");
this.EvaluateAndCompare("(backquote (a ((unquote x)) c))", "(a ((b b)) c)");
this.EvaluateAndCompare("(backquote (a (unquote-slice x) c))", "(a b b c)");
this.EvaluateAndCompare("(backquote (a ((unquote-slice x)) c))", "(a (b b) c)");
this.EvaluateAndCompare("(backquote (a (unquote-slice x) (unquote-slice x) c))", "(a b b b b c)");
No hay soporte de números. Escribí algunos tests usando implementaciones tipo Peano:
(define succ (x)
(cons x nil))
(define pred (x)
(first x))
(define add (x y)
(if (nil? x)
y
(add (pred x) (succ y))
)
)
Hace un rato que no toco y mejoro el código, pero mi próximo paso podría ser refactorizar AjLisp (intérprete más completo) para basarse o tomar ideas de este intérprete núcleo. Ahora, tengo una idea más clara de lo que es necesario, esencial, y de lo que es accesorio en un intérprete Lisp.
Y me divertí escribiendo esto ":-)
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
El año pasado, descubrí el lenguaje de programación Io:
http://www.iolanguage.com/
overview
Io is a prototype-based programming language inspired by Smalltalk (all values are objects, all messages are dynamic), Self (prototype-based), NewtonScript (differential inheritance), Act1 (actors and futures for concurrency), LISP (code is a runtime inspectable/modifiable tree) and Lua (small, embeddable).
Tiene una sintaxis simple, sus características están basadas en lenguajes funcionales, Smalltalk, Self y otros. Como de costumbre, quiero escribir mi propia versión, con un cambio: soporte de objetos nativos. Esto es, para implementar un intérprete sobre una máquina virtual con librería de clases. Las actuales opciones son Java y .NET.
Dos semanas atrás, el bueno de @MartinSalias me comentó sobre el lenguaje Io, y apareció de nuevo en mi radar. Entonces, el pasado domingo, comencé mi propia implementación, basado solamente en lo que leí en el sitio. No será el mismo lenguaje, veré que quedará o no adentro de esta implementación. Es trabajo en progreso.
El código está en mi proyecto de Google AjCodeKata:
http://code.google.com/p/ajcodekatas/
En el trunk, en el directorio AjIo. Hay una solución .NET, con tres proyectos:
La librería de clases es el núcleo, el programa de consola puede ser usado para interactuar con el intérprete, y el proyecto de test tiene las pruebas automáticas que escribí durante el proceso de diseño/codificación.
He escrito el lexer, el parser, y los principales objetos del lenguaje usando Test-Driven Development, como acostumbro.
En una de las primeras pruebas del intérprete, podemos escribir:
Hace unos días, implementé los operadores de asignación ::=, :=, = (arreglos de sintaxis adornando los métodos setSlot, newSlot, updateSlot):
Un tiempo més tarde (pueden consultar el History.txt dentro del repositorio), agregué soporte de objectos nativos .NET:
Próximos pasos:
- Escribir más operadores de comparación (sólo escribí ==)
- Números nativos (ahora, sólo son reconocidos por el lexer los enteros, pero pueden manejarse otros tipos, probar 1 / 6, retorna un double)
- Precedencia en operatdores aritméticos (ahora 2 + 2 * 3 retorna 12, en vez 8)
- for, foreach, range, y más (ahora hay sólo if())
- block() (Tengo implementado method())
- include()
- Comenzar a escribir parte de los objetos de la librería original de Io
Sobre este últimos punto: debo decidir cóomo implemento cosas como:
List clone
Posibles opciones:
- List como un objecto derivado de Object (obtenido de(Object clone) con sus propios slots, como wrapper sobre una lista nativa
- List clone retornando objectos ArrayList nativos, teniendo el tipo ArrayList sus slots asociados
- No implementar List, y usar directamente objetos nativos
Como en AjSharp, el Io original tiene agentes y coroutines. Quiero agregar las características de AjSharp (agentes, goroutines, channels, queue channels, futures) en AjIo. Io implementa agentes en “threads” de máquina virtual: esto es, no usa los threads del sistema operativo, sino que la máquina virtual va ejecutando parte de un agente, parte del otro, pasado de un código a otro durante la ejecución (eso es lo que imagino, no he visto el código de implementación). No tomaré esa aproximación, no por ahora.
Este artículo, en Anglish:
http://ajlopez.wordpress.com/2010/04/30/working-in-ajio-io-like-interpreter-in-c/
Como ven, me he divertido escribiendo todo esto!
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez