November 2007 - Posts
El bueno de Augusto Alvarez, que ya contribuyó con variada información a este blog, me envió el enlace a este video:
Vean lo notable del concepto: la interacción que se logra con unos simples conceptos aplicados. Me gustó lo de tener lugares de punto fijo, aplicar gravedad, detectar la continuidad de una línea.
Hay varios más videos de este producto en YouTube, como:
Un precursor de estas ideas parece ser:
En ese video explicación es más detallada.
Interesante. Sería un buen ejercicio de programación, implementar alguna de estas ideas, en el lenguaje que elijamos. Temas a resolver:
- Detección de polígonos y curvas, su cerramiento (en caso de quedar abierto).
- Giramiento, movimiento de "cuerpos" bidimensionales.
- Manejo de puntos fijos
- Manejo de la gravedad, rotación sobre punto fijo, dinámica
- Extensión a tres dimensiones
Nos leemos!
Angel "Java" Lopez
http://www.ajlopez.com/
El bueno de Darío Quintana ha actualizado un programa que había escrito hace un tiempo, para generar un modelo de AjGenesis desde assemblies compilados. Ahora, la nueva versión está descripta en:
Generando con AjGenesis desde los assemblies
En la imagen vemos el directorio del proyecto principal, que está acompañado por otro proyecto de tests con NUnit, ejemplos, y código ya compilado.
Es interesante ver cómo el modelo se puede obtener desde distintas fuentes. En un post anterior, describí una forma, apenas un ejemplo, de obtener información desde una base de datos:
AjGenesis- Modelo desde la Base de Datos
Darío, en su post, muestra cómo usa su proyecto desde un código de tareas de AjGenesis:
function GetEntities(path)
AssemblyManager.LoadFrom(AjGenesisFromAssemblyPath)
obj = new AjGenesis.FromAssembly.Collector()
list = obj.GetEntities(path,null)
return list
end function
Usa el nuevo AssemblyManager para cargar la librería AjGenesis.FromAssembly.
Las clases Model, Entity, Property son el modelo, de manera similar a las que tenemos en ejemplos de AjGenesis. La clase Collector es la que crea un objeto Generator, que es el que hace el trabajo duro de encontrar las entidades dentro de un Assembly:
using System.Collections;
namespace AjGenesis.FromAssembly
{
public class Collector
{
public ArrayList GetEntities(string assemblyPath, string ns) {
Generator g = new Generator();
g.Path = assemblyPath;
g.AssemblyToObjects();
ArrayList array = new ArrayList();
foreach (Entity entity in g.Model.Entities)
{
array.Add(entity);
}
return array;
}
}
}
Un fragmento de Generator:
public void AssemblyToObjects() {
Assembly assembly = Assembly.LoadFrom(Path);
Type[] types;
types = assembly.GetTypes();
//Get all types from the assembly
for (int i = 0; i < types.Length; i++)
{
//Veo que interfaces está implementando
bool ImplementaIEntity = false;
Type[] interfacesTypes = types
.GetInterfaces();
ImplementaIEntity = true;
if (ImplementaIEntity)
{
Entity entity = new Entity();
entity.Name = GetTypeName(types
.Name);
entity.FullName = types
.FullName;
if (types
.BaseType != null)
{
entity.Inherits = GetTypeName(types
.BaseType.Name);
entity.InheritsFullName = types
.BaseType.FullName;
}
PropertyInfo[] propertyInfo = types
.GetProperties();
foreach (PropertyInfo pi in propertyInfo)
{
Property prop = new Property();
prop.Name = pi.Name;
prop.TypeName = pi.PropertyType.Name;
if (pi.PropertyType.FullName != null)
{
prop.TypeFullName = pi.PropertyType.FullName;
}
else
prop.TypeFullName = string.Empty;
entity.Properties.Add(prop);
}
_model.Entities.Add(entity);
}
}
}
Este es sólo un fragmento, vean el código original de Darío para más detalle. Se usa Reflection para obtener los tipos de un assembly, y las propiedades de cada tipo. Creo que Darío quiere mejorar la forma de detectar cuándo un tipo en el assembly es o no una entidad, usando interfaces o atributos.
Nos leemos!
Angel "Java" Lopez
http://www.ajlopez.com/
AjGenesis se caracteriza por partir de uno o varios modelos, libres de definición, para generar artefactos de texto, usando tareas y plantillas programables. Cuando inicié el proyecto, recuerdo haber leído el libro de Kathleen Dollard Code Generation in Microsoft .NET
Una de las recomendaciones de la buena de Dollard, es tomar metadata de algún lugar, por ejemplo la base. Como no creo que toda la metadata esté en alguna parte, me incliné desde el principio por un modelo libre (también me aparté rápidamente del camino de Dollard, basado en generar código basado en transformaciones de XSLT, que es el "camino del diablo", no lo intenten en sus casas, sin avisar a sus padres...;-). Hay varios puntos que me interesaron de la postura de Dollard, será cuestión de escribir más adelante un post comentando el libro.
Pero no hay que descartar el tomar metadata, información que nos pueda servir, de otras fuentes, la más común es la base de datos que tengamos entre manos. Recordemos que la generación de código es una solución pragmática, no debemos dejar de usar lo que nos resulte conveniente para el proyecto en el que estemos trabajando.
Así que ya hace unos meses, puse un pequeño ejemplo dentro de los que vienen en el AjGenesis. Pueden verlo en la
AjGenesis Versión 0.5
Está en la carpeta examples\LoadDB.
Trabaja como ejemplo de consulta de esquema contra una base Northwind que tengamos en nuestro MS SQL Server. Desde ese directorio, en una línea de comando, ejecutamos
make
Este comando ejecuta una tarea de AjGenesis:
..\..\bin\AjGenesis.Console Tasks\DbProcess.ajg
pause
Se conecta a la base:
PrintLine "Connection"
AssemblyManager.LoadWithPartialName("System.Data")
con = new System.Data.SqlClient.SqlConnection()
PrintLine "ConnectionString"
con.ConnectionString = "server=(local);uid=sa;database=Northwind"
PrintLine "Command"
cmd = new System.Data.SqlClient.SqlCommand()
cmd.Connection = con
cmd.CommandText = "select * from Information_Schema.Tables"
con.Open()
Uso la información que está en Information_Schema.Tables. Observen el uso del nuevo AssemblyManager, que permite cargar assemblies (tendría que revisar si es necesario cargar el System.Data, y si puedo dejar de usar LoadWithPartialName que ahora en .NET 2.0 está "deprecated")
Luego, consigue los nombres de las tablas:
dr = cmd.ExecuteReader()
TableNames = new System.Collections.ArrayList()
while dr.Read()
PrintLine "Table " & dr.Item("Table_Name") & ": " & dr.Item("Table_Type")
TableName = dr.Item("Table_Name")
if dr.Item("Table_Type")="BASE TABLE" then
TableNames.Add(TableName)
end if
end while
dr.Close()
Una vez conseguida esa información, obtiene las columnas de las tablas, armando un modelo en memoria, en una collección Tables:
Tables = new System.Collections.ArrayList()
For each TableName in TableNames
PrintLine "Loading Table " & TableName
Table = new AjGenesis.Models.DynamicModel.DynamicObject()
Table.Name = TableName
Table.Columns = new System.Collections.ArrayList()
cmd.CommandText = "SELECT * from Information_Schema.Columns where Table_name='" & TableName & "'"
dr = cmd.ExecuteReader()
while dr.Read()
ColumnName = dr.Item("Column_Name")
PrintLine "Processing Column " & ColumnName & ": " & dr.Item("Data_Type")
Column = new AjGenesis.Models.DynamicModel.DynamicObject()
Column.Name = ColumnName
Column.DataType = dr.Item("Data_Type")
if dr.Item("Character_Maximum_Length") then
Column.Length = dr.Item("Character_Maximum_Length")
Column.IsNumeric = false
else
if dr.Item("Numeric_Precision") then
Column.Length = dr.Item("Numeric_Precision")
Column.Scale = dr.Item("Numeric_Scale")
Column.IsNumeric = true
end if
end if
Column.SqlName = Column.Name
Column.Name = Column.Name.Replace(" ","")
Table.Columns.Add(Column)
end while
dr.Close()
Table.SqlName = Table.Name
Table.Name = Table.Name.Replace(" ","")
Tables.Add(Table)
end for
Finalmente, hace el viejo truco de recorrer ese modelo, y aplicarle un template, para generar otro modelo (recuerde esta capacidad del proyecto: un modelo puede ser un XML, serializado en archivo de texto, entonces, un proceso de generación puede generar otro modelo para usar o retocar más adelante):
FileManager.CreateDirectory("Model")
for each Table in Tables
TransformerManager.Transform("Templates\Table.tpl", "Model\${Table.Name}.xml", Environment)
end for
Un ejemplo de modelo generado:
<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<Table>
<Name>Region</Name>
<SqlName>Region</SqlName>
<Columns>
<Column>
<Name>RegionID</Name>
<SqlName>RegionID</SqlName>
<DataType>int</DataType>
<Length></Length>
<Scale></Scale>
</Column>
<Column>
<Name>RegionDescription</Name>
<SqlName>RegionDescription</SqlName>
<DataType>nchar</DataType>
<Length>50</Length>
<Scale></Scale>
</Column>
</Columns>
</Table>
Ahora, con el AssemblyManager, se podría tomar una .dll cualquiera y cargarla, para usarla en nuestra generación (tengo que postear sobre el uso que le dió el bueno de Darío Quintana a esta "feature", ver Generando con AjGenesis desde los assemblies). Me imagino que podemos usar, por ejemplo, la librería Meta de MyGenerationSoftware para conseguir metadata de cualquier base de datos. Vean también que está disponible el código fuente de ese utilitario.
Nos leemos!
Angel "Java" Lopez
http://www.ajlopez.com/
La gente del Departamento de Computación de la Facultad de Ciencias Exactas y Naturales, de Universidad de Buenos Aires, y la comunidad smalltalkera de Argentina, junto con empresas que desarrollan y empresas proveedaras de herramientas, están organizando el
Smalltalks 2007 - Primera Conferencia Argentina de Smalltalk
Del lunes 10 de diciembre al miércoles 13 de diciembre, se estará presentando trabajos y conferencias sobre Smalltalk, en sus distintas variedades. Son actividades sin arancel, pero necesitan registrarse (ya llegaron a los más de 200 inscriptos).
Pueden ver el programa detallado en:
http://www.dc.uba.ar/events/smalltalks/2007/programme/
La gente de MerCap tendrá una presentación sobre (ver detalle)
XTrade - Arquitectura de un Sistema Financiero complejo
XTrade es un sistema complejo que modela parte del funcionamiento del sistema financiero. Desde siempre el mundo financiero ha sido un entorno volátil en el cual siempre surge nueva operatoria, nuevas formas de utilizar los instrumentos financieros existentes y nueva normativa que cumplir. Debido a esto en general los sistemas que apuntan al mercado financiero requieren un nivel de flexibilidad mayor que los sistemas que apuntan a modelos de negocio donde no se producen tantos cambios.
La gente de InfoOil hablará sobre (ver detalle)
Zafiro
Plataforma para construcción de sistemas de negocios complejos
Para cumplir con las exigencias que impone la industria del petróleo en sus ramas de
mantenimiento de equipos, perforación y administración de la producción, es necesario contar con sistemas lo suficientemente flexibles para poder adaptarse en tiempo y forma a los cambios drásticos que experimenta esta industria.
Leandro Caniglia de Caesar Systems tendrá una presentación sobre Software Development
Software Development
Software development is a highly sophisticated discipline whose success requires the concurrence of many best practice patterns. Smalltalk is an ideal environment to integrate all of them homogenously throughout the entire development process. This talk reviews several aspects of software production and shows why smalltalkers are in a privileged position to address its challenges.
El bueno de Leandro (al que le debo un artículo sobre Smalltalk a cambio de un almuerzo que amablemente me invitó en el siglo pasado) está trabajando en Caesar Systems como director de desarrollo:
Leandro Caniglia joined Caesar Systems in 2001 and serves as director of development. For more than a decade prior to this, Caniglia worked as a Smalltalk consultant for several companies in Argentina, Brazil and Chile. He was professor at the University of Buenos Aires for more than 20 years. Caniglia has also worked as a researcher in the CONICET, the official office for scientific research in Argentina. He founded SUGAR, the Smalltalk User Group of Argentina and the MathMorphs Squeak User Group. He has a Ph.D. in Mathematics and has published extensively on Computational Algebraic Geometry.
http://www.caesarsystems.com/info_team.htm
(Arggg!!! Geometría algebraica, qué hermoso!)
Bueno, habría tanto que comentar, tantos temas interesantes. Vayan, pasen y vean el programa, lean los abstracts.
Smalltalk es un mundo. Desde acá las felicitaciones por la iniciativa, que va encaminada al éxito.
Nos leemos!
Angel "Java" Lopez
http://www.ajlopez.com/
Hoy tenemos a nuestro alcance el inmenso poder de Internet y de la web en particular. Tal vez, algunos de Uds. no recuerdan lo que era el mundo cuando estas herramientas no existían, o no estaban al alcance de muchos de nosotros. Pero era otro mundo, se los aseguro.
Ahora, nuestros conocimientos, opiniones, lo que sabemos, lo que nos pasa, nuestra experiencia, y más, todo puede compartirse, sin más que publicarlas en foros, listas de correos, páginas personales, y desde hace unos años, en blogs.
Quisiera destacar la revolución que ha provocado la aparición de los blogs, y sus entusiastas productores de posts, los bloggers, algunos compulsivos como yo. Los blogs han cambiado la forma de distribución de conocimiento, y en el ámbito de la informática, se ha convertido en EL canal de comunicación de gente entusiasta que comparte lo que conoce, lo que hace, problemas y soluciones, nuevas tecnologías y aplicaciones de las existentes. Desde hace unos años, cuando tengo un problema o quiero conocer sobre un tema, en lugar de preguntar en una lista de correo, voy a Google (en el caso de un tema probablemente vaya también a Wikipedia). Y desde hace un tiempo, la mayor parte de la información relevante sobre un tema se encuentra en la blogosfera.
Pero puede pasarle a un blogger, lo mismo que a un escritor: no tener una idea sobre la que escribir, sentirse paralizado ante la página web en blanco. Veamos una lista de ideas de posts:
- No se amedrente ante un tema. Si es muy extenso, mejor, podrá planear varios post: un post inicial sobre su plan de ataque al tema, luego posts periódicos sobre los distintos puntos. Puede cambiar el orden, si ve que necesita seguir otro plan.
- Luego de escribir algunos posts, propóngase una periodicidad: un post por semana, por ejemplo. Por supuesto, puede escribir entre medio, pero lo importante es mantener el compromiso asumido.
- No tiene que escribir un post todo en un momento. Si no se siente cómodo en escribirlo de un tirón, vaya escribiéndolo de a partes, por ejemplo, poniendo el esquema de párrafos, rellenando los que tiene más en claro, colocando enlaces a visitar para profundizar el tema, escribiendo al final del propio borrador tareas pendientes. Recuerde cómo se come un elefante: pedacito a pedacito.
- Si le interesa un gran tema, vaya planteándo varios posts, como si fuera a escribir un libro. Escribir posts lo ayuda a mejorar sus habilidades de comunicación, que son más que necesarias en nuestra profesión, tanto como las habilidades técnicas.
- Si recibe un comentario interesante a un post, con una pregunta a contestar en extenso, conteste en otro post.
- Ha leido un libro. Publique un resumen, comentarios, con recursos y enlaces mencionados en el volumen.
- Escriba sobre un nuevo programa que ha instalado, y probado. No olvide incluir alguna captura de pantalla. ¿Qué problemas encontró en la instalación, documentación?
- Si trabaja con una metodología, como Scrum, describa cómo ha sido su experiencia. ¿Cómo son las reuniones de standup? ¿Cómo ha sido su primera iteración?
- Al estudiar un tema, seguramente recolectará información en la web. Organice esos enlaces, clasifíquelos por relevancia y subtema, y escriba un post para ayudar a otro a informarse sobre el tema
- Tiene que estudiar el tema persistencia en un sistema. Explore y escriba sobre las distintas tecnologías, librerías que han aparecido para resolver el problema. Describa el problema inicial
- Si fue a una conferencia, escriba lo que entendió, enumere los enlaces o recursos presentados
- ¿Aprendió un nuevo patrón? Ideal escribir sobre el mismo, con algún ejemplo
- Relájese. Si tiene algun chiste, video de broma, anécdota, puede incluirlo en algún post
- Es su primer contacto con un framework, como Spring, o NHibernate. Escriba su experiencia, acompañada por un código de ejemplo
- Si maneja más de un idioma, piense en abrir otro blog. Es lo mejor para no confundir a los suscriptores
- ¿Está pensando en implementar un sistema? Pase en limpio sus pensamientos en un post, donde describa lo que quiere hacer, y su estrategia de implementación
- Utiliza herramientas todo el día, describa qué usa, cómo, en qué lo ayudan
- Está desarrollando una herramienta de código abierto. Vaya publicando sus ideas, sus avances, criterios de diseño
- Encuentra una nueva aplicación en la web 2.0. Describa su experiencia de uso
- Participa de varias listas. Escriba su existencia, la forma de suscribirse, en qué forma lo ayudan
- En su trabajo, luego de terminar un proyecto, seguramente tendrá algo para comentar: una nueva tecnología que usó, o algo que haya aprendido sobre programación. O algo que haya aprendido sobre el propio manejo del proyecto e interacción en grupo.
- Hay un tema en inglés que le interesa, con numerosos recursos en la web, escriba un resumen en español, siempre mencionando las fuentes consultadas
- En un foro o lista de correo preguntaron algo de lo que Ud. conocía la respuesta. No sólo conteste en la lista, publique un post con la misma
- En listas sobre una tecnología, hay preguntas que se repiten, las llamadas preguntas frecuentes. Son candidatas para escribir un post interesante. Podrá usar el enlace cuando alguien haga la misma pregunta
- Dió un examen de certificación. Explique cómo se preparó, que libros, recursos utilizó. ¿Cómo se desarrolló el examen?
- Cada tanto, aparece un nuevo término en nuestro diccionario técnico. Explique a qué se refiere esa nueva "buzzword", definiciones, origen, fuentes consultadas
- Va a asistir a una conferencia del gremio. Escriba para difundir el evento. Puede ser importante para alguien que esté leyendo
- Tiene dudas sobre un tema, pregunta en una lista, y obtiene varias respuestas. Organícelas, y escriba un post con el resumen de la solución. No olvide incluir los créditos
- Encontró un blog que tiene información interesante. Escriba un artículo, comentando los post del otro blog que más le sirvieron o que le parecieron más interesantes
- Este es un post largo: en general se prefieren posts más cortos, pero si el tema lo amerita, puede escribir de esta longitud. Trate en lo posible de colocar alguna figura. Si tiene que explicar pasos en un entorno de desarrollo, capture pantallas e insértelas. Inserte código formateado si es posible
- No se desanime si al principio las estadísticas de visitas no explotan. Escribir un blog es un proceso lento, un proceso de siembra, y más adelante, cosecha. Lo interesante es que se va construyendo de a poco. Ya aparecerá su estilo, y descubrirá en qué temas despierta mayor atención de sus lectores y comentadores
Un punto más: muchas empresas han comenzado a ver la ventaja de pedir a sus postulantes, no una certificación, sino que muestren su blog. El blog refleja lo que uno conoce, sus intereses, la organización y capacidad de expresarse. El blog es parte de la hoja de vida.
Bueno, espero haberlos convencido de comenzar a escribir un blog, si todavía no lo hicieron. O si lo tienen, espero que estas ideas para temas a escribir les sirvan y puedan ponerlas en práctica. Si quieren difundir lo que hacen, el blog es ideal. Si quieren destacar las ventajas de alguna herramienta, solución, lenguaje, patrón, qué mejor que escribir un post sobre el tema.
(imagen del comienzo "tomada" del post http://www.stublog.co.uk/?p=505)
PS: Desde hace unos meses, me he propuesto escribir un post por día, en mis blogs, una lista actualizada en
A post a day, keeps the doctor away
Nos leemos!
Angel "Java" Lopez
http://www.ajlopez.com/
En el anterior post
Programando para una Grid
enumeré algunas aplicaciones que pueden aprovechar el concepto de grid computing, pensando en algunas aplicaciones para AjMessages, AjAgents (o el venerable AjServer): como siempre, esto es el AjLenguaje en el AjMundo... :-). Tengo una lista ampliada, para comentar.
Más aplicaciones
- Programas de Biología Molecular y Genética: Tenía que revisar esta rama, (ver el curso de Sebastian Bassi y cía sobre Introducción a la Biología Molecular para Programadores), pero es interesante encontrar que hay implementaciones como BLAST que bien podrían portarse a una grid. Vean alguna implementación de BLAST en grilla en Digipede.
- Rendering y procesamiento de imágenes: Mucho de los algoritmos de iluminación, reflejos, armado de imágenes realistas, pueden realizarse en paralelo. Tengo que revisar cuáles son
- Producción de animaciones: Si una imagen, para su proceso, necesita un algoritmo no paralelizable, se puede usar cada nodo de la grilla para procesar una imagen, pero usar la grilla completa entonces para producir una serie de imágenes, que compondrán una animación.
- Procesamiento de media: tanto la compresión de video, como la detección de key frames, cambios de escena en un video, puede particionarse en nodos de una grilla.
- Procesamiento ETL: Extract, Transform y Load, un clásico del procesamiento "batch", bien puede ser enviado paralelizado a una grid.
- Detección de Spam: Una empresa de distribución de listas de correo, como egrupos.net, bien podría derivar el análisis a una grilla. Tal vez es más una aplicación de computación distribuida, pero tanto AjMessages como Fabriq están ahí cerca: no son solo para explotar en una grilla.
- Simulaciones: un tema amplísimo. Hay sistemas donde no es fácil ver el resultado de dada una entrada, ver qué produce. Ante distintas entradas (por ejemplo, forma de un barco y velocidad), hay que calcular el resultado (resistencia, velocidad final, turbulencia). Hay que probar distintos conjuntos de entrada. Entonces, cada entrada (pueden ser miles) se puede ir entregar a un modelo simulado, ejecutando en un nodo. Con varios nodos, se simulan más resultados.
Enlaces
He coleccionado varios enlaces en el adictivo Delicious sobre Grid Computing
http://del.icio.us/ajlopez/gridcomputing
Para este post, me he detenido más en
http://www.gridgain.com
http://www.digipede.net
http://www.gridgistics.net/
Es muy interesante la implementación de la gente de Digipede. Distribuyen assemblies, hay un servidor que recibe tareas, las distribuye en distintas máquinas donde corren los agentes Digipede, mantiene una base de datos con las tareas lanzadas y pendientes, y expone una interfaz web de control. Una aplicación de usuario puede comunicarse con el servidor Digipede, mediante un servicio web.
Lo interesante de GridGain es la "gridificación" de un método, usando Java annotations. Interesante idea a explorar.
Algunas ideas locas
Para que noten que todavía no pueden darme de alta en el nosocomio mental en el que estoy albergado, veamos:
- Generación de código en grilla: Lo tenía para colocar en el anterior artículo, pero me olvidé. No solamente se puede paralelizar algo de generación de código, sino que creo que podemos montar distintos agentes expertos, que completen el modelo, "conozcan" de arquitectura y patrones, de code coverage, de unit tests, y que vayan colaborando, generando artefactos finales e intermedios, armando una "pipeline" de producción de código, o trabajando en paralelo. Siempre pensando que esos agentes pueden estar en una grilla.
- Computer Go en grilla: Ya hay algunos trabajos hechos con GNUGo. Pero sería interesante poder armar que el AjGo tenga una organización interna basada en un concepto de agentes (como tantas palabras, agente es un concepto difuso, disculpen la ambigüedad). Algo presenté de la idea este año, en el Congreso de Go que se realizó aquí en Argentina. Habría agentes especializados en resolver problemas concretos (invasión de territorio, reduccion de territorio, formación de ojos, impedir formar ojos, escape de grupo, etc ...) que bien pueden ejecutarse en una grilla. Eso permitirá un "scale out" interesante, en cuanto se complique obtener respuestas en tiempo razonable, debido a la naturaleza del juego.
- Lenguaje de programación "grillable": Tal vez debería comenzar con solamente tener un lenguaje de programación con ejecución en paralelo o diferida. Tengo ideas para extender AjBasic con CCR o similar (tengo algo diseñado, no publicado ni bajado a código, con lazy evaluation en paralelo), o de implementar algo más orientado a programación funcional, donde algun operador (se me ocurre procesamiento de listas y otros) sea "grillable": pueda delegarse el trabajo en paralelo a una grilla, que puede existir o no, o que puede ser ampliada en caso de ser necesario para el resultado a tiempo del algoritmo empleado. Sería interesante tener un lenguaje así: que funcione en una sola máquina, pero que transparentemente, pueda colocarse en una grilla, siga funcionando igual, pero obtenga toda la ventaja de tener una grid abajo. Se viene el AjG#... ;-)
Conclusión y Agradecimiento
Creo que es un tema interesantísimo. Agradezco desde acá al bueno de Gabriel Szlechtman (confieso que tuve que copiar el apellido, todavía no me lo aprendo), que sugirió lo de procesamiento de media, algo de generación de código (tomado de sus ideas de generador de código), detección de spam, y otros.
¿Conocen otras aplicaciones, implementaciones, para comentar?
Nos leemos!
Angel "Java" Lopez
http://www.ajlopez.com/
En estas semanas, estuve dando alguna charla explicando conceptos de generación de código en Tandil y en Corrientes, gracias a la gente del MUG. En esas charlas, muestro ejemplos de AjGenesis, proyecto que cumpliendo con el "dog fooding" uso todas las semanas. En la versión actual en desarrollo
AjGenesis 0.5
(publicada el 18 de Noviembre, no confundir con la anterior de Septiembre)
estoy experimentando en tener la capacidad de poder invocar a una o varias ventanas desde una tarea, para solicitar parámetros al usuario, interactivamente.
Si bien todo hasta ahora sale del modelo o modelos que tengamos serializados en archivos XML, bien puede ser cómodo, dependiendo de la tarea, pedir al usuario algún dato en el momento, como una conexión a base de datos.
Siguiendo con esa idea, encontrarán un nuevo proyecto experimental AjGenesis.Recipes que usa al nuevo proyecto AjGenesis.UI. Este último es el que tiene la definición de la ventana a usar para pedir información al usuario.
Veamos algunas ventanas de AjGenesis Recipes, para tener una idea de hacia dónde va la idea:
Al principio no muestra nada en el árbol. Pueden ir a File | Open... y elegir un archivo de recetas de ejemplo: Recipes.xml contenido en el directorio del código fuente del proyecto.
Este archivo contiene:
<?xml version="1.0" encoding="utf-8" ?>
<Recipes Name="Recipes">
<Node Name="Hello World">
<Recipe Name="Hello World VB.NET Module" Task="Tasks/HelloWorldTask.ajg" Documentation="Tasks/HelloWorldTask.html"/>
</Node>
<Node Name="VB.NET">
<Recipe Name="Entities" Task="Tasks/Task1.ajg" Documentation="Tasks/Task1.html"/>
<Recipe Name="Services"/>
</Node>
<Node Name="CSharp">
<Recipe Name="Entities"/>
<Recipe Name="Services"/>
</Node>
</Recipes>
Cada nodo puede contener nodos y recetas. Una receta tiene un nombre, que se muestra en el árbol, una tarea, código de AjBasic a ejecutar, y un archivo que documenta en HTML a la receta.
Si hacemos doble click sobre la receta de Hello World VB.NET Module aparece una ventana, en la que indicamos el archivo de modelo a usar, y el archivo .vb a generar (estos son datos que se especifican en la tarea):
Lo nuevo es el archivo de tarea, que usa al nuevo proyecto AjGenesis.UI y su ventana. Veamos Tasks\HelloWorldTask.ajg:
form = UIManager.CreateInputForm()
form.Text = "Class Generator Wizard"
form.AddFileField("Model","Model to use","")
form.AddFileField("FileName","File to Generate","")
n = form.ShowDialog()
if n = 1 then
ModelFile = form.GetField("Model")
FileName = form.GetField("FileName")
ModelManager.LoadModel(ModelFile,Environment)
TransformerManager.Transform("Templates/HelloWorldVb.tpl",FileName,Environment)
end if
El UIManager es un nuevo manager en esta versión de AjGenesis. Noten cómo se puede definir una ventana, sus campos, procesarla, y tomar los campos de vuelta, para usarlos en el proceso de generación.
Todavía está en desarrollo, pero me pareció interesante comentar lo que se viene en esta nueva versión.
Vean que igual se sigue usando modelo. Prácticamente todas las recetas necesitarán uno o varios modelos desde donde partir. Pero con AjGenesis Recipes se podrá indicar el modelo interactivamente. Será cuestión de ver si los usuarios encuentran esta forma de operar útil o no, en contraposición a una serie de tareas NAnt ya armadas. También se pueden hacer recetas sin modelo: simplemente se alimenta de parámetros, por ejemplo, la conexión a una base de datos, y de ahí obtener la información que necesita para trabajar.
Me imagino que usando esta interfaz, podemos definir nuestros propios archivos de recetas, tareas, y plantillas, invocados desde este programa. Podemos tener una receta para generar todos los DAOs de un modelo de entidades, o una receta que nos pida cuál de las entidades generar. O una receta que pregunte si queremos usar NHibernate o directamente ADO.NET. O cuál es la base MySql que vamos a usar.
Próximos pasos:
- Estabilizar el código (especialmente el manejo de directorios, su posicionamiento relativo)
- Manejar mejor las excepciones
- Capturar la salida de las tasks y mostrarlas en alguna ventana
- Completar AjGenesis.UI para que maneje un conjunto interesante de controles (hoy apenas texto, elegir un directorio, y elegir un archivo) y una serie de ventanas como un wizard
- Permitir el uso de controles y ventanas de usuario
- Una vez hecha la experiencia de algunas recetas, ver si es interesante o útil o factible, integrarlo en Visual Studio (o por qué no, en Eclipse), a la GAT, o partiendo de Visual Studio Integration Package.
Sugerencias, comentarios, bienvenidos!
Nos leemos!
Angel "Java" Lopez
http://www.ajlopez.com/
Este miércoles 14 de noviembre pasado, gracias a la organización del Microsoft User Group y la invitación del departamento de Informática de la Universidad del Nordeste, estuve dando una charla sobre generación de código, mostrando las ideas que subyacen a esta solución pragmática, comentando la gran cantidad de utilitarios que existen para distintos escenarios y tecnologías, y viendo algunos ejemplos con mi "pet project" AjGenesis.
No estuve en el campus cercano a Corrientes, sino en una sede del centro de la ciudad. En la universidad se dictan múltiples carreras. Pueden tener más información en su página de la Wikipedia:
Universidad Nacional del Nordeste - Wikipedia, la enciclopedia libre
Me gusta visitar universidades, donde veo el movimiento de conocimiento que existe. Ahora, las universidades en mi pais están más conectadas entre sí y con el mundo, por lo menos, más que cuando yo estudiaba en el siglo pasado. La UNNE tiene tratos de dictado de posgrados en informática, con otras universidades, de Argentina y de España.
Me encontré con el bueno de Darío Quintana, interesado en NHibernate y Domain-Driven Development. Cualquiera interesado en NHibernate DEBE leer su blog. No tuve tiempo de mostrar en detalle algunos templates de DDD, pero espero "postear" en estos días sobre el tema.
Como siempre, el material, presentación, código, y enlaces mencionados, están disponibles en:
Material del Seminario de Generación de Sistemas con AjGenesis en Corrientes
Estuve poco tiempo en la ciudad de Corrientes, pero aproveché para conocer el río, y comer algo de surubí (lo mío es ser un sibarita...:-)
Gracias desde acá a Gladys Dapozo, titular del departamento de informática de la Universidad del Nordeste, y como siempre, gracias a Oscar Turquet, Sandra y Mónica, del MUG, por haber orquestado toda esta movida.
Vean en el sitio del MUG las actividades que se realizan en todo el pais, en el marco de la Gira Nacional. El MUG de Argentina es el decano de los grupos de usuarios aquí en mi pais, con doce años de existencia, y siempre trata de llegar más allá de Buenos Aires (los que conocen mi pais, saben que hay una tendencia a hacer todo en la capital Buenos Aires). Además, el MUG trata de promover actividades que surjan desde los propios lugares, más que sólo enviar disertantes.
Más información si quieren visitar Corrientes:
Corrientes, Argentina
Corrientes - Wikipedia, the free encyclopedia
CORRIENTES - TURISMO - ARGENTINA - CORRIENTES - PORTAL
Corrientes - Capital de la Provincia de Corrientes - Argentina
Una foto satelital del área en
Corrientes, Argentina, and the Parana River
Espero volver con más tiempo, para un dorado a la parrilla.. :-)
Nos leemos!
Angel "Java" Lopez
http://www.ajlopez.com/
En anteriores posts, comenté sobre los proyectos AjMessages y AjAgents:
AjMessages- hacia un procesador de mensajes
Agentes usando Concurrency and Coordination Runtime (CCR)
Una de las capacidades que tiene AjMessages es comunicar distintas instancias del programa, que pueden ejecutar en diferentes máquinas servidoras. Se le pueden enviar mensajes de configuración dinámica, lo que permite que a cada máquina se le pueda dar un trabajo distinto. También puede configurarse para que una acción (elemento mínimo direccionable dentro de una aplicación AjMessages) pueda ser atendida en distintas máquinas. AjAgents apunta a que también en algún momento tenga agentes distribuidos, pero por ahora es una aplicación local.
AjMessages se podría distribuir de forma que un servidor pueda controlar otras instancias del sistema:
Quisiera enumerar aquí algunas de los escenarios de uso de un sistema que pueda ejecutar en una grilla de servidores, lo que se llama Grid Computing. Como toda "buzzword" tecnológica, puede tener un alcance amplio, pero tratemos de definirla.
Según el excelente artículo introductorio de la gente de IBM:
New to Grid Computing
Grid Computing permite unir un pool de servidores, sistemas de almacenamiento, y redes, en un gran sistema único, de manera que podamos manejar todos esos recursos múltiples a una tarea. Para el usuario, o la aplicación, el sistema aparece como un gran sistema único de computación.
En el caso de AjMessage, siguiendo las ideas de Fabriq, ese efecto se consigue porque los distintos servidores ejecutan una o varias aplicaciones, y sus acciones, de manera transparente.
El concepto de Grid Computing permite obtener mayor capacidad de procesamiento, sin necesidad de tener un gran sistema de hardware o software, sino apelando a repartir la carga y distribuyendo la tarea entre máquinas de línea. Dependiendo del sistema que organice esa distribución, podemos agregar más máquinas, obteniendo mejores resultados, sin necesidad de cambiar la aplicación.
Imaginen que podemos tener un conjunto de servidores, formando una grilla, y brindar ese conjunto a los usuarios que lo necesiten, para en algún momento resolver alguna tarea. Me imagino un Grid as a Service, que seguramente alguien ya está implementando.
Pero concentrémonos hoy en el tema: ¿qué casos de uso, escenarios, podemos imaginar para usar una grid?
He aquí la lista que estuve confeccionando:
- Resolución de algoritmos genéticos: Un problema que tal vez no tenga un algoritmo normal de resolución, o cuya complejidad crezca con su tamaño de forma exponencial, puede llegar a ser un reto siguiendo procedimientos tradicionales. Con algoritmos genéticos, podemos ir probando soluciones parciales, y mediante cambio y selección, ir descubriendo mejores soluciones. Es claro que eso se puede hacer en paralelo, siendo ideal para ser dado como tarea a una grid. Me gustaría procesar algo como lo de http://www.darwinathome.org.
- Búsqueda en árbol: en muchos problemas de inteligencia artificial, es necesario explorar ramas en un árbol de búsqueda. Uno de los casos donde se aplica, es en el análisis de jugadas de un juego, pero también en decisiones de negocio y planeamiento. Me imagino una grilla colaborando en la decisión de la próxima jugada en un juego de Go, uno de los problemas difíciles de la inteligencia artificial actual, ver ....)
- Araña e indexador en la web: la tarea de examinar un sitio, tomar el contenidos de sus páginas, analizarlas, detectar enlaces, y seguir explorando a partir de ellos, es una tarea que bien puede ser repartida. Mientras un nodo consigue el contenido de otra página, va generando tareas para otros nodos, como analizar las páginas enlazadas desde la actual en proceso.
- Trabajo en lote: podría darse a una red el trabajo de procesar gran cantidad de información que sea "partible", desde transformaciones de una tabla de base de datos, hasta análisis de logs para generar estadísticas. Si la entrada es divisible, el proceso de cada parte puede ser enviado a un nodo distinto. Por ejemplo, un nodo se puede ocupar de transformar los datos de una tabla de transacciones, pero sólo los de enero, mientras que otro se ocupa de procesar los de otro mes
- Distribución de listas de correo electrónico: Un caso típico, si somos una empresa que brinda este servicio, al llegar un correo electrónico destinado a una lista que mantenemos, delegamos el envío de cada email en particular, con personalización incluida por ejemplo, a nodos de la grilla.
- Procesamiento de mensajes: Podemos necesitar recibir mensajes XML, y aplicarle transformaciones, o en base a su contenido, derivarlos a un proceso u otro. Las transformaciones y controles se los podemos deriva a nodos de la grilla. Si aumenta el caudal de mensajes entrantes, simplemente aumentamos la cantidad de nodos de procesamiento.
- Ejecución de un workflow: Siguiendo con la generalización, podemos diseñar un flujo de trabajo, cada uno de sus pasos puede ejecutarse en nodos diferentes. Habrá nodos que puedan ejecutar más de un paso, y habrá pasos de toma de decisiones. Me imagino como caso concreto, la ejecución de todos los pasos ante un nuevo tenant, en un sistema encargado de provisioning de un sistema brindado como Software as a Service.
- Map Reduce: Es un modelo de programación para procesar grandes conjuntos de datos. Se especifica una función Map que procesa un par clave/valor de entrada, genera pares clave/valor intermedios, en general varios. Hay otra función Reduce que se aplica a todos los pares clave/valor intermedios que compartan la misma clave. Por ejemplo, una función Map puede recibir un documento a procesar, genera pares palabra/documento por cada palabra relevante que encuentre, y la función Reduce toma esos pares de una misma palabra, para generar una lista de documentos que contengan a esa palabra. Para una explicación más detallada, ver un "paper" de Google Labs MapReduce: Simplified Data Processing on Large Clusters.
Creo que hay varias implementaciones de estos escenarios en grillas y otras soluciones. Me gustaría armar una prueba de concepto, usando el AjMessages o similar como base.
Cambiando la óptica, se puede pensar en exponer la grilla con uno o varios web services, e implementar alguna forma de poder "sembrar" trabajos desde otros sistemas en la grilla. Se me ocurre sembrar:
- Assemblies completos, e invocación de algunos métodos en clases y objetos a determinar.
- Programas en lenguajes de scripting, controlados por razones de seguridad
- Agentes, que pueden consistir en assemblies o en código para una máquina virtual de agentes
- Programas escritos en DSLs Domain Specific Language, uno o varios lenguajes que algunos nodos de la grilla entiendan.
Semejante grilla se puede brindar como servicio a otros sistemas. Surge el concepto de Grid as a Service, el alquiler de su consumo, el control del nivel de servicio, y demás, que algún software de control deberá proveer.
Ya escribiré en particular sobre Grid Computing, por ahora puede consultar el ya mencionado artículo de IBM:
New to Grid Computing
y una interesante implementación de código abierto en Java:
GridGain
(El gráfico del comienzo de este artículo está "inspirado" en uno de GridGain, pero los nodos se pueden comunicar entre sí, y repartir su trabajo, siguiendo la indepedencia de localización de cada acción en AjMessage).
Nos leemos!
Angel "Java" Lopez
http://www.ajlopez.com/
Uno de los temas a encarar cuando uno usa un generador de código, o de artefactos de texto en general, es determinar si lo generado se va a usar como "puntapié" inicial y luego modificar, o si cada vez se va a regenerar, para reflejar cualquier cambio en el modelo inicial (modelo abstracto, clases en UML, esquema de la base). Esta segunda opción permite usar la generación de código como si fuera un compilador de modelo: cambia el modelo, regeneramos el código.
Pero a veces, dentro del código generado, queremos poner algun fragmento nuestro, agregado luego de haberlo creado por primera vez. En la reunión de Agosto pasado:
Reunión de Generación de Sistemas con AjGenesis
organizada por el Microsoft User Group de Argentina se planteó esa necesidad. Bien, ni lento ni perezoso, agregué algo de código a AjGenesis. Gracias a los que lo probaron en el grupo de generación de código, ahora puedo escribir un breve "post" sobre su uso.
Lo pueden probar desde la versión 0.5:
AjGenesis 0.5
a descargar desde CodePlex.
El ejemplo
En esa versión, en el directorio examples\HelloPreserve encontraremos un ejemplo de uso.
El ejemplo se construye desde la línea de comando ejecutando
make
que es un archivo .bat que contiene:
..\..\bin\AjGenesis.Console Model.xml Build.ajg
Esto carga un modelo tipo Hello World de Model.xml:
<Project Name="HelloWorld">
<Messages>
<Message>Hello</Message>
<Message>World</Message>
<Message>Again</Message>
</Messages>
</Project>
(si es su primer contacto con un ejemplo de este tipo, leer:
Generando Código- Hello World con AjGenesis
Generando aplicaciones con AjGenesis
)
El make invoca a trabajar un pequeño programa AjBasic Build.ajg:
PrintLine "Generating HelloWorld"
TransformerManager.Transform("ModuleVb.tpl", "HelloWorld.vb", Environment, "PRESERVE")
Lo nuevo es el tercer parámetro de Transformer.Transform. Recordemos: Transformer es un objeto ayudante, que está implantado en el "environment" de variables de AjGenesis, accesible desde nuestros programas escritos en AjBasic. Es el objeto que nos permite invocar al transformador de plantillas. Pero aparte de tener un método Transform con dos parámetros (el primero es el nombre de archivo de la plantilla a procesar, el segundo el nombre de archivo a generar en el proceso), ahora tiene una variante adicional: si pasamos un tercer parámetro, lo usa como texto a buscar para preservar código. Veamos su uso en la plantilla.
La plantilla del ejemplo es ModuleVb.tpl:
'
' Project ${Project.Name}
' Automatically generated by AjGenesis
' http://www.ajlopez.com/ajgenesis
'
' PRESERVE comment start
' PRESERVE comment end
Module Module1
Sub Main()
System.Console.WriteLine( _
<#
n = 0
for each msg in Project.Messages
if n then
Print "& "
end if
n = n + 1
#>
"${msg}" _
<#
end for
#>
)
End Sub
' PRESERVE code start
' PRESERVE code end
End Module
Todo lo que esté desde una línea que contenga la marca PRESERVE (el tercer parámetro del método Transform), hasta otra línea que contenga PRESERVE, es mantenido de generación a generación.
ATENCION: el algoritmo empleado "matchea" las líneas que coinciden, es decir, si en el template hay un linea
' PRESERVE comment start
ésa es la que busca en el código original para no pisarla. Los bloques se identifican por el CONTENIDO COMPLETO de la línea que inicia el bloque.
Si luego, en el código generado, agrega texto en esos bloques, al regenerarse, esos textos se respetan:
'
' Project HelloWorld
' Automatically generated by AjGenesis
' http://www.ajlopez.com/ajgenesis
'
' PRESERVE comment start
' This is my comment two
' PRESERVE comment end
Module Module1
Sub Main()
System.Console.WriteLine( _
"Hello" _
& "World" _
& "Again" _
)
End Sub
' PRESERVE code start
Sub MyMethod()
Console.WriteLine("My own inmortal method")
End Sub
' PRESERVE code end
End Module
Cuestiones
Analicemos algunos puntos. ¿Por qué ahora hay que especificar un parámetro? ¿Por qué no solamente tomar lo que está entre PRESERVE como código a preservar? Primero, por compatibilidad con