Angel "Java" Lopez

NET, Java, PHP y Desarrollo de Software

This Blog

Syndication

Search

Tags

Community

Email Notifications

Archives

.NET

ASP.NET

Windows Form

VB.NET

C#

Sitios

Blogs

March 2009 - Posts

Primera semana sabática del año

El viernes pasado, comencé mi primera semana sabática del año. Esta "semana extendendida", debería termina el lunes 6 de Abril. Pero el proyecto en el que estoy trabajando fue extendido una semana más. Usualmente, no doy clases ni charlas, pero esta vez, debido a reordanimientos en mi calendario, estaré dando un curso de Scrum y una clase de .NET.

Así, que decidí esta vez compromenterme a una lista de objetivos, pero a cumplir en dos semanas, de acá al lunes 13 de Abril.

La lista incluye:

- Escribir un post explicando las motivaciones e ideas iniciales a implementar en AjProcessor.

- Mejoras menoras (soporte de acceso e invocación a objetos .NET), refactoring mediano, y primera versión publicada de AjCat, y post.

- Agregar soporte de bloques y variables indexadas a AjTalk, y post.

- Publicar un post explicando lo hecho en AjPepsi.

- Código inicial de proyecto de código abierto, en Java, y post.

Bien, eso es todo. Me gustaría ponerle más foco en un a sola semana, pero esta vez, tendré que ocuparme de otros temas.

Como siempre, tendré que publicar un post de cierre, con lo efectivamente entregado.

Nos leemos!

Angel "Java" Lopez
http://www.ajlopez.com/
http://twitter.com/ajlopez

Posted Mon, Mar 30 2009 10:14 by lopez | 1 comment(s)

Que rrriiicaa está la mocosa (Azure en Run09)

El miércoles pasado, tuve el gusto de presentar, en el Paseo La Plaza, en Run09, junto a Matías "El Pibe" Woloski (@woloski), y Pablo "Lito" Damiani (@litodam), conceptos y código de Azure, la propuesta de Cloud Computing de Microsoft. Se presentó una aplicación de subasta, albergada en la nube, y una lista de deseos ("wishlist") compartida. En la aplicación de subasta, cada usuario puede subir una foto del item a subastar.

Por ahora, dejo una foto, de lo que subastamos en el medio de la conferencia, una de nuestras programadores Assembler preferida, esta chica desnutrida, pobre, la Luisana Lopilato:

 

Para los que son de Argentina, recordemos al inefable Roberto Galán y su frase inolvidable: "Que rriiiicaaa que está la mocosa.... " ;-)

No me digan nada. Lo mío es un apostolado... ;-)

(Gracias a @sebarenzi por la foto)

Nos leemos!

Angel "Java" Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Posted Fri, Mar 27 2009 4:17 by lopez | 1 comment(s)

Filed under: , ,

Primer Programa con Azure

Hace unos días apareció la nueva versión de Azure SDK, que pueden bajar desde:

Windows Azure Software Development Kit (March 2009 CTP)
Windows Azure Tools for Microsoft Visual Studio March 2009 CTP

Yo instalé el segundo, que incluye al Azure SDK.

Armemos una simplísima aplicación, para ver que podemos programar para la nube y probar en nuestro propia máquina, sin tener que tener una cuenta en Azure, para publicarlo. El Azure SDK viene con las herramientas para simular lo que Azure en línea nos da. Exploraremos en otros posts estos nuevos conceptos, veamos hoy armar una primera aplicación.

Al instalarlo, nos queda en el menú de programas:

Al instalar los Tools para Visual Studio, al crear un proyecto tenemos nuevas opciones:

Elegí Web Cloud Service, quedando una solución

El segundo proyecto es el que define una aplicación web, con una simple página. El primer proyecto tiene definiciones sobre la configuración de la nube, como las instancias de distintos servicios, servidores a levantar.

Al lanzar por primera vez a la aplicación, Azure levanta algunos servicios y acceso a base de datos local:

Levantan dos servicios, dos íconos nuevos aparecen en la barra de tareas:

Y la página que aparece, es un clásico, como comentaba ayer, desde Kernighan y Ritchie:

Pueden levantar desde el menú de programas, o desde el ícono del engranaje en la barra de tareas, al Development Fabric, que es el sistema lo que luego tendríamos en la nube:

En la particular nomenclature de Azure, hay Roles, y de dos tipos: Web Role, y Worker Role. Cada Role es, digamos, un servicio (interactivo en el caso de Web Role, no interactivo en los Worker Role) que se estará ejecutando en una o varias instancias de la nube. Nuestra aplicación, al crearse con el wizard, tiene un sólo WebRole, con una sola instancia.

Es interesante ver que Azure se basa en un principio simple: Roles, divididos entonces Web Roles y Worker Roles. Un worker permite que le enviemos trabajo y se ejecute en forma asincrónica al rol llamante. Tengan siempre en cuenta, que si bien los roles son lo que programamos, luego los podemos desplegar de distintas formas en la nube, por ejemplo, un mismo web role, puede estar ejecutándose en varias instancias de la nube.

El próximo post será sobre

Nos leemos!

Angel "Java" Lopez
http://www.ajlopez.com/
http://twitter.com/ajlopez
Escrito mientras escuchaba Buddy Guy Sweet Home Chicago

Posted Wed, Mar 25 2009 12:00 by lopez | with no comments

CodeRun plataforma de desarrollo en línea

El bueno de Martín Salías (@MartinSalias) me avisa de este sitio y aplicación notable:

http://www.coderun.com/

Pueden registrarse, el servicio básico es gratuito.

Al ingresar, se encuentran con algo parecido al Visual Studio:

Si vamos a crear un nuevo proyecto, vemos los distintos tipos de soluciones soportadas:

Hasta tienen para desarrollar una aplicación para Facebook. Eligiendo el ejemplo de Hello World, clásico desde el Kernighan y Ritchie, obtenemos:

Lo podemos compilar y ejecutar:

Era algo que yo estaba esperando: tener un entorno de desarrollo en línea (no solamente una máquina a la que pueda acceder, sino todo instalado para cumplir con una función). Veremos hasta dónde llega esta tendencia, pero veo que tendremos cada vez más poder de procesamiento, sin tener que actualizar el hardware local o el software nuestro. En vez de menú de programas, iremos a favoritos en el browser.

Ya me veo programando un Code Kata desde un ciber, como en mis tiempos de PHP ... ;-)

Debe haber un Eclipse en línea, ¿conocen algún enlace?

Nos leemos!

Angel "Java" Lopez
http://www.ajlopez.com/
http://twitter.com/ajlopez

Posted Tue, Mar 24 2009 12:54 by lopez | with no comments

Modelo, decisiones, inteligencia artificial y AjGenesis

En el recientemente creado grupo de Google AltNet-Argentina, el bueno de Fabio Maulo planteó una pregunta en el thead:

ORuM

donde escribía

Quien me conoce un poco, o me ha leido en algún lado, conoce ya la acronimo
ORuM.La realida es que nunca tuve la ocasión de una buena confrontación
sobre el tema.

Para titular la mesa sería:
Object Relational unMapping
Mas allá del ORM.

Quisiera compartir, confrontar, ampliar algunas ideas y verificar la
factibilidad.

La idea es tener en claro, cómo se toman algunas decisiones, en el caso de tener un dominio de clases, y llegar al mapeo de en una base de datos, no preexistente. Es un caso tipo, como escribía el propio Maulo:

Yo quisiera llegar a : "che, yo tengo este dominio que tendría que persistir en ORACLE, fijate vos! a mi lo que me interesa es que persista."

El DSL sería:

Che.Tengo("MiDominio.dll").Que.TieneQuePersistirEn("ORACLE").FijateVos();

Para mí, esto es parecido a lo que trato muchas veces de resolver con AjGenesis:

"Tengo X quiero resolverlo con Y", donde X puede ser un dominio de entidades, un dominio más tipo DDD, una lista de servicios, lo que sea, e Y sería JSP, Struts2, JSF, ASP.NET MVC, NHibernate, Hibernate, MySql, SQL Server, y demás. Es lo mismo que hace un programador: toma decisiones, ante lo que tiene que hacer.

Es por eso que en AjGenesis tomé algunas decisiones tempranas, para poder ir avanzando en un camino, que menciono en:

Sobre la generación de código

... el modelo a usar ... PUEDE SER GENERADO por el propio sistema, más un sistema experto. No imagino una aplicación más inmediata de la "inteligencia artificial". Imagino agentes inteligentes, que colaboren en una red compartida, cada uno generando parte del modelo, cada uno consumiendo algo que otro produce, y colaborando, para generar un sistema... Sí, ya sé, tengo que tomar la píldora verde, en lugar de la roja... ;-)

Esa es una de las razones de tener en AjGenesis:

- un modelo
- más que sólo un lenguaje de templates
- aplicar el lenguaje en tasks, que modifican y completan el modelo

Si sólo tuviera templates, sólo haría transformaciones X -> Z, de una forma, digamos, lineal, desde, para poner un ejemplo, una clase o un modelo que describe una clase, a un código o archivo de configuración de persistencia.

A lo que voy, es que el camino que quiero para AjGenesis, en algún momento (no para que todos lo usen así), es que sea un sistema experto, que tome decisiones. De ahí que, desde el principio:

- tenga un lenguaje completo, con toma de decisiones, que pueden ser complejas
- tiene acceso al framework de .NET, para poder ser extendido de cualquier manera.
- invoque a tareas, no simplemente a transformar el modelo X usando el template T

Eso explica también, algunos caminos que estoy explorando, como AjLisp, y AjProlog (aunque son más para entrenarme, que para aplicarlos directamente en AjGenesis). Habrá que investigar si este camino es posible, pero me parece que está relacionado con el tema planteado en el grupo. Veamos, volvamos al problema inicial.

De clases a persistencia

Las opciones de mapeo que podemos considerar, son las mostradas por el bueno de Martin Fowler:

Single Table Inheritance

Class Table Inheritance

Concrete Table Inheritance

En una situación ideal (no costo en tiempo de queries o de update, sin limite de memoria en disco), todo seria igual.

Como la situación no es ideal, me imagino que los costos de cada decisión se mediran en:

- Rendimiento de actualización y consulta

- Espacio de almacenamiento

A primera vista, me imagino que el primer punto es el mas peliagudo.

Para concretar, tomemos un modelo sencillo. Sea clase Empresa, subclases Cliente, Proveedor.

Habría que ver qué consecuencias tiene entonces, el tener una tabla empresas, con un campo discriminador de si es cliente o proveedor. ¿Qué pasa si hay muchos campos en comun? ¿O si hay muchos campos de diferencia? Pienso que mas va a influir el tema: ¿pero queda ahí el dominio? Si el día de mañana aparecen más subclases, ClienteExtranjero, ProveedorExterno, ¿no se complicará el haber adoptado una sola tabla?

Si ponemos tablas Empresa (con los datos comunes), Clientes (con los datos adicionales), Proveedor (con los datos adicionales), habrá que hilar fino en las consultas. No sólo está el tema del rendimiento de actualización y consulta. Tambien esta la frecuencia de algunas operaciones. Es decir, si una consulta determinada tarda X tiempo, habrá que ponderarla tambien por la frecuencia de esa consulta en la operación normal del sistema.

Con tablas Clientes, Proveedores, habra que comprobar que la actualizacion sea mas rapida que en el anterior caso. Y vigilar que pasa, y con cuanta frecuencia, se necesita una consulta sobre Empresas (que imagino debera implicar un UNION).

Entonces, no sólo es el modelo de clases, sino cómo se usa, lo que puede influir en cómo hagamos el mapeo.

ESTO ES LO QUE YO VEO EN MUCHOS MODELOS ya existentes, que no tienen todo LO QUE SE NECESITA DE UN MODELO. Un modelo de clases se queda corto, para tomar algunas decisiones. Lo mismo, si partimos desde una base ya diseñada. Partir de esos modelos, implica que en algún momento lo tenemos que enriquecer, con anotaciones en el modelo de clases, o agregando información en metadata o en algún momento, si partimos desde la base de datos.

Partir de un modelo de clases o de la base de datos, tiene la ventaja de partir de algo conocido. Pero para muchas de las operaciones que quisiéramos hacer (en este caso "simple", mapeo a relacional, imaginen otros casos como servicios distribuidos, seguridad, cache en el cliente, etc.), hace falta más información de contexto.

De ahí, que yo esté a favor de un modelo distinto, más enriquecido.

De Aristóteles a Kant

En los noventa, en una revista Byte, leí una breve reseña, sobre gente que estaba armando algo que lo llamaban KANT. En honor a las categorías del filósofo alemán (yo diría que se referían más a categorías de Aristóteles), ellos planteaban que todo en, lo que hoy llamaríamos, modelo, está incluído en alguna categoría como:

- Persona
- Organización
- Bien Físico
- Lugar Físico
- Documento
- Suceso
- Lapso

y demás. Por ejemplo, un Empleado entraría en la categoría Persona, un Cliente o Proveedor, en la categoría Organización. El que un Empleado estuviera contratado por una Empresa, era un Lapso (un intervalo, posiblemente abierto, de tiempo) establecido entre una Persona y una Organización. A partir de las categorías, se podía inferir que toda Persona tiene fecha de nacimiento, y otros atributos, que un Lapso puede tener tiempo de inicio y tiempo de final. (Escribo sin tener la referencia, de memoria).

Esa reseña siempre influyó en lo que quiero hacer con un modelo rico, abstracto. Sirve para poner más semántica sobre lo que estamos describiendo, más de lo que daría un modelo de código o de base de datos. Sigo pensando que algo así debe ser el modelo del que partir, en la generación de código o en otras ideas.

Apenas una punta de eso (el tener categorías llamadas prototipos, que sirvan de base para generar un modelo simple), está desde hace tiempo en AjExamplesExamples3.zip, en el directorio Prototypes, y Seeds. Es una idea con implementación mínima, a explicar en detalle en otro post.

Nos leemos!

Angel "Java" Lopez
http://www.ajlopez.com/
http://twitter.com/ajlopez
En estos días, revival de los 80s en mi vida http://www.youtube.com/watch?v=dgwmErO_nlQ

Posted Sun, Mar 22 2009 21:28 by lopez | 1 comment(s)

Libro electrónico Plastic Logic

El año pasado, Plastic Logic presentó su tecnología de libro electrónico. Vean el video de Septiembre de 2008:

Lo que parece mejor de esta tecnología es su costo. Está construido con un circuito basado en polímeros, en vez de microchips de silicona, más caros de fabricar. El display va a tener la capacidad de enrollarse. Piensan entrar en el mercado en la segunda mitad de este año, 2009.

Visiten el sitio de Plastic Logic

http://www.plasticlogic.com/

donde verán que la empresa va más allá: quieren tener un programa de edición, donde autores pueden sumarse a este nuevo medio de publicación.

Por otro lado, veremos si el producto prende en el tema libros, donde Kindle de Amazon es un gran competidor. Alguna vez, Plastic Logic declaró que querían concentrarse en otro nicho, el de los diarios y revistas.

Yo preveo que, si las tecnologías se estabilizan y bajan los costos, todas las superficies planas (paredes, puertas, muebles, muros...) podrán transformarse en una ventana a contenido variable. Pero más interesante, para mí, es la capacidad de tener acceso a información, a texto e imagen y otros medios, sin tener el problema físico de almacenamiento. Me gustaría acceder a mi biblioteca personal, o a cualquier biblioteca pública, desde un simple aparato. La web va camino a proveer ese contenido. Veremos qué pasa, en la confluencia del contenido en la web, y nuevos aparatos, formas de distribución, que van apareciendo.

Pueden leer sobre el Acuerdo Google, para digitalizar libros de autores que se sumen al acuerdo, y publicarlos en la web:

Google se convierte en una librería virtual

Nos leemos!

Angel "Java" Lopez
http://www.ajlopez.com/
http://twitter.com/ajlopez

Posted Thu, Mar 19 2009 11:12 by lopez | 1 comment(s)

Filed under:

Test-driven development en acción, usando Visual Studio

Estoy preparando una charla para el jueves de la semana que viene, 26 de Marzo, en el Microsoft User Group de Argentina. Pueden inscribirse en:

MEDIA JORNADA "Test-driven development en acción, usando Visual Studio".

El horario es de 18:30 a 21:30. La idea es ir armando ejemplos usando los principios de TDD, con código que muestre:

  • Documentar el código con tests, en vez de en papel
  • Usar listas de test para generar requerimientos explícitos
  • Refactorear y mejorar el diseño del código
  • Test bajo una UI delgada
  • Test para cambios incrementales, minimizando la depuración
  • Entregar software que sea verificable y robusto

Lo que veremos estará basado en .NET y Visual Studio, pero se puede aplicar a otros entornos, lenguajes y tecnologías. Las ideas de base son las mismas.

Como siempre, preparar una charla sirve para aclarar los puntos que uno va aplicando en el día a día. Explicar algo, nos permite entenderlo mejor.

Es gratis PARA LOS SOCIOS DEL MUG. Los demás, ¿qué esperan para asociarse? ;-)

Como en otras ocasiones, publicaré en mi sitio el material que utilice en el curso, y probablemente, aparecerán posts por este blog, explicando algunos puntos.

¿Sugerencias a incluir en el temario? ¿Otros temas interesantes para armar una charla-serie de posts?

(Gracias a la gente del MUG, en especial a Gustavo Bachrach, que me han pedido un post para publicar en la revista que entregan a los socios).

Nos leemos!

Angel "Java" Lopez
http://www.ajlopez.com/
http://twitter.com/ajlopez

Posted Wed, Mar 18 2009 10:09 by lopez | with no comments

TDD and Code Kata: Writing a Lexer for AjRuby

Muchas veces, escribo programas tipo code kata, para entrenarme en algún tema de desarrollo de software. En estos últimos meses, escribí varios mini intérpretes, usando TDD, code coverage, y C#. La semana pasada, estuve trabajando en el lanzamiento de otro pet project, AjRuby. El punto de inicio: el analizador léxico, el lexer.

Un lexer es un programa que analiza el código fuente de un programa, y retorna sus tokens, las “palabras” que componen el programa. En el caso de AjRuby, escribí un lexer que sigue la gramática de Ruby. No está completo aún, pero funciona.

Pueden ver el progreso del proyecto, en el repositorio de Google Code:

http://code.google.com/p/ajcodekatas/source/browse#svn/trunk/AjRuby

La solución tiene un proyecto de librería de clases, y otro de tests:

Hay una clase Token, que representa cada token:

public class Token { public string Value { get; set; } public TokenType TokenType { get; set; } }

El TokenType es una enumeración:

public enum TokenType { Name, Integer, Real, Boolean, String, Operator, Separator }

Hay una clase LexerTest.cs, conteniendo tests como:

[TestMethod] public void ShouldProcessName() { Lexer lexer = new Lexer("name"); Token token; token = lexer.NextToken(); Assert.IsNotNull(token); Assert.AreEqual(TokenType.Name, token.TokenType); Assert.AreEqual("name", token.Value); token = lexer.NextToken(); Assert.IsNull(token); }

Hay un test para cada tipo de token a ser procesado. Otro ejemplo:

[TestMethod] public void ShouldProcessNameWithInitialUnderscore() { Lexer lexer = new Lexer("_name"); Token token; token = lexer.NextToken(); Assert.IsNotNull(token); Assert.AreEqual(TokenType.Name, token.TokenType); Assert.AreEqual("_name", token.Value); token = lexer.NextToken(); Assert.IsNull(token); }

Escribí los tests usando ideas TDD: escribir el test, compilar con error, arreglar los problemas de compilación, ejecutar los tests en rojo, arreglarlos, conseguir el verde para los tests. No estuve haciendo tanto refactoring. El código merece algún refactor, pero por ahora, estoy tratando de conseguir un lexer que trabaje. Los tests quedaron en verde:

Mi objetivo es tener más del 80% de code coverage, en cualquier momento del desarrollo del proyecto:

Es bueno escribir algo sólo por diversión y aprendizaje. Para mí, es parte de la mejora continua que todo desarrollador de software debe perseguir.

Nos leemos!

Angel "Java" Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Posted Thu, Mar 12 2009 6:11 by lopez | 1 comment(s)

Web Crawler distribuido usando AjMessages

En Enero pasado, actualicé mi proyecto AjMessages para que soporte comunicación usando DSS/CCR y Windows Communication Foundation. AjMessage puede ejecutarse de forma distribuida, enviando mensajes desde un nodo lógico a otro. Los nodos lógicos pueden albergarse en una o más máquinas física. Más información sobre AjMessages en:

AjMessages- a message processor
Distributed Applications with AjMessages using DSS/CCR
Aplicaciones Distribuidas con AjMessages usando DSS/CCR
AjMessages- hacia un procesador de mensajes

Pueden descargar el código fuente desde

http://www.codeplex.com/ajmessages

Tenía la idea de escribir un procesador de mensajes distribuidos. Hace unos años, escribí mi primer intento, llamado AjServer

Hacia el AjServer

Luego, encontré al proyecto Fabriq, estudiando sus ideas e implementación. En ese proyecto, hay manejadores (handlers) lógicos de mensajes, que pueden instalarse de modo distribuido, de forma transparente, cambiando la información de configuración:

En el 2007, escribí la primera versión de AjMessages, como prueba de concepto: pude reproducir bastante de las ideas de Fabriq, y a la vez, elevar el nivel de abstracción de algunos puntos, para conseguir mayor flexibilidad. Fabriq estaba más orientado a SOA. AjMessages se orienta a mensajes arbitrarios, que coordinados, pueden funcionar en una aplicación en grilla.

La solución actual de AjMessages es:

Hay un proyecto núcleo, y dos proyectos de transporte: uno para soporte de WCF, y otro que se basa en DSS/CCR (tecnologías de Microsoft Robotics). Si no tienen DSS/CCR instalado, pueden remover los proyectos que lo referencia. El núcleo de AjMessages está lib de dependencias de esas tecnologías.

AjMessages.SampleApp contiene un simple manejador de mensajes: un decrementador de enteros, que toma un mensaje de entrada, con un contenido entero, lo decrementa, y produce un nuevo mensaje.

En cambio, AjMessages.WebCrawler implementa el mensaje y manejadores de mensajes para armar un web crawler distribuido. Pueden ejecutarlo desde una sola máquina, o en varias.

Cara AjMessages tiene:

Body: un contenido arbitrario
Headers: información adicional, por clave/valor.
Action: describe el destino del mensaje, usando un patrón Aplicación/Nodo/Acción

(más detalle en AjMessages- hacia un procesador de mensajes)

Exploremos el ejemplo de web crawler. Esta aplicación está compuesta de nodos, que pueden ser orquestado para visitar una página web, tomar de esa página todos los enlaces relacionados, y volver a tomar esas páginas. Para que no sea un proceso infinito, la visita de páginas se limita al sitio inicial, y hasta un nivel de profundidad. La aplicación puede ser descripta lógicamente con este diagrama:

El primer mensaje se envía al nodo Controller, a su acción Dispatch. Ese primer mensaje contiene la dirección de la página a visitar. El mensaje es enriquecido, y pasado al nodo Controller, acción Resolve. Este nodo está a cargo de mantener la lista de páginas ya visitadas, y de controlar la profundidad de exploración. Si el enlace recibido es aprobado, entonces el mensaje es enviado al nodo Downloader, acción Download. El contenido de la página es recuperado, agregado al mensaje, y reenviado al nodo Harvester, a su acción Harvest. Esta acción analiza el contenido de la página, y emite varios mensajes, uno por cada enlace encontrado. El receptor de esos nuevos enlaces es el nodo Resolver, en su acción Resolve. Así, el proceso continua hasta visitar todas las páginas (con un límite en la profundidad a explorar).

Esta aplicación se puede describir en un archivo de configuración XML, como por ejemplo:

<?xml version="1.0" encoding="utf-8" ?> <AjMessages> <Application Name="WebCrawler"> <Node Name="Dispatcher"> <Handler Name="DispatcherHandler" Type="AjMessages.WebCrawler.Handlers.Dispatcher, AjMessages.WebCrawler"/> <Action Name="Dispatch" Handler="DispatcherHandler"/> </Node> <Node Name="Harvester"> <Handler Name="HarvesterHandler" Type="AjMessages.WebCrawler.Handlers.Harvester, AjMessages.WebCrawler"/> <Action Name="Harvest" Handler="HarvesterHandler"/> </Node> <Node Name="Downloader"> <Handler Name="DownloaderHandler" Type="AjMessages.WebCrawler.Handlers.Downloader, AjMessages.WebCrawler"/> <Action Name="Download" Handler="DownloaderHandler"/> </Node> <Node Name="Controller"> <Handler Name="ResolverHandler" Type="AjMessages.WebCrawler.Handlers.Resolver, AjMessages.WebCrawler"/> <Action Name="Resolve" Handler="ResolverHandler"/> </Node> </Application> </AjMessages>

Un aplicación, entonces, está compuesta de nodos lógicos. Cada nodo puede ser visto como una clase lógica. Cada nodo puede manejar acciones, que son los puntos destinos de los mensajes. Una acción puede estar compuesta de uno o varios pasos. Este es el punto de extensibilidad de la aplicación: deben proveer los pasos, el manejador de mensaje, y escribir el archivo de configuración que orquestre el procesamiento de los mensajes.

Pero una cosa es la aplicación, y otra es su distribución en máquinas físicas. Pueden tener dos hosts, e instalar diferentes nodes en cada uno:

En este diagrama, el Dispatcher y el Resolver están en un hosts, mientras que el Downloader y el Harvester están en otro. Pero Uds. pueden poner Harverstes en cada hosts, o en veinte máquinas. Queda en Uds. cómo distribuir la carga del trabajo. Cuando un mensaje es enviado a un destino (Aplicación/Nodo/Acción),  AjMessage lo reenvía a un host apropiado, que contenga un nodo capaz de procesar el mensaje.

La distribución de nodos lógicos en un host físico se define via configuración, por ejemplo:

<?xml version="1.0" encoding="utf-8" ?> <AjMessages> <Host Name="Server1" Address="http://localhost:50002/AjMessages" Activate="true"> <Application Name="AjMessages"> <Node Name="Administration"/> </Application> <Application Name="WebCrawler"> <Node Name="Controller"/> <Node Name="Dispatcher"/> <Node Name="Harvester"/> <Node Name="Downloader"/> </Application> </Host> <Host Name="Server2" Address="http://localhost:50003/AjMessages"> <Application Name="AjMessages"> <Node Name="Administration"/> </Application> <Application Name="WebCrawler"> <Node Name="Dispatcher"/> <Node Name="Harvester"/> <Node Name="Downloader"/> </Application> </Host> </AjMessages>

Ejecutando el ejemplo Web Crawler

Pueden probar el programa, lanzando dos hosts, en la misma máquina. Hay que ejecutar el programa de consola AjMessage.Console. Al comenzar esta aplicación, podemos ingresar el comando

fork

Este comando lanza un segundo host. Ahora, podemos configurar los dos hosts. En el primero, ingresamos:

load ConfigurationServer1.xml

Este archivo carga la aplicación AjMessage inicial (es una aplicación más dentro de "la grilla"), y define un endpoint WCF para escuchar mensajes de otros posibles hosts. Ahora, en la misma consola, ingresamos:

load ConfigurationWebCrawler.xml

Este comando carga la definición de la aplicación Web Crawler, con sus nodos lógicos (no hay información de deploy todavía). El tercer comando, define la distribución física de hosts:

load ConfigurationWebCrawlerNode1.xml

Ahora, volvamos a la segunda consola. Ahí, ingresamos los comandos:

load ConfigurationServer2.xml
load ConfigurationWebCrawler.xml
load ConfigurationWebCrawlerNode2.xml

Estamos listos para lanzar el primer web crawling. Vamos a la primera consola, e ingresamos:

send WebCrawler/Dispatcher/Dispatch http://ajlopez.zoomblog.com

El programa comienza a trabajar, en AMBAS consolas. Una típica salida de la primera consola:

Próximos pasos

Debería arreglar algunos problemas en el transporte DSS/CCR (actualmente, puede ejecutar una aplicación simple como el decrementador de enteros, pero no con el web crawler). Dos puntos para implementar:

- Configuración remota de nodos
- Distribución de los manejadores de mensajes (sus .dlls) a los nodos remotos
- Una configuración para todos los nodos (ahora, cada nodo es configurado separadamente)

Comencé un experimento con un proceso más abstracto de mensajes, que quisiera que pudiera implementar casos de uso como:

- Un simple hello world
- El ejemplo de decrementar enteros
- Web crawler distribuido
- Una especie de Enterprise Service Bus

Pueden ver mis primeros pasos en:

http://code.google.com/p/ajcodekatas/source/browse#svn/trunk/AjProcessor

Todavía en desarrollo.

Nos leemos!

Angel "Java" Lopez
http://www.ajlopez.com/
http://twitter.com/ajlopez

Posted Tue, Mar 10 2009 2:07 by lopez | 3 comment(s)

Locura en la configuración de Windows Communication Foundation

Windows Communication Foundation fue creado para permitir la creación de aplicaciones distribuidas, dándonos una librería de herramientas de comunicación que podemos reusar, sin necesidad de escribir el Service Interface y el Service Gateway desde cero. Tecnologías como servicios web han evolucionado, tienen varias versiones y detalles a tener en cuenta si queremos una comunicación segura, confiable y que soporte interoperabilidad.

El concepto de un Service Model, es ungran avance. Pero hoy, quiero levantar mi mano, para apuntar a algo que hace a WCF una solución"convoluted". Me refiero a la configuración de WCF.

Si uno quiere usar cualquier característica de WCF, más allá de las más simple, se encontrará rápidamente peleándose con las opciones de configuración de esta bestia. ¿Un síntoma? Si Ud. se olvida de una mínima parte, el canal no funcionará. Si Ud. omite alguna opción de configuración cuando crea un certificado, y se olvida de hacer un paso, entre una docena de pasos de una "to do list", la llamada via WCF no podrá ser completada. Y tendrá que manejar una cantidad de conceptos, como certificados, tokens, issers, chain of trusts, behaviors, bindings, endpoints, identities, custom bindings, factories, service hosts, channel factories, security options, enumeration types, extensions methods, and... Podría continuar enumerando por horas.

Un ejemplo mínimo. Buscando por la web, encuentro el artículo

WCF (Windows Communication Foundation) Example

Leo ahí:

Being able to switch the transport layer from TCP (Secure SSL) into HTTP with some simple code, that's amazing!

Sí, correcto, pero

I did have some problems, though. The tcpBinding.Security.Mode = SecurityMode.None; is very crucial on both sides. I'm not sure what it does, but it does not turn off the security completely as I have read in my references. There is still SSL encryption, but on a lower level. It is possible to add certificates to the connection, which also makes the connection more secure.

Acá está el problema. Si uno juega explorando las distintas propiedades y métodos de los bindings y endpoints disponibles, entraremos en un laberinto sin salida visible. Notemos que el autor del artículo no está seguro sobre una de las opciones de configuración que está usando. Y eso que es una sola opción: hay docenas más para configurar, si uno quiere hacer ajuste fino del servicio.

Claro, hay configuración declarativa, no por código. Y hasta podemos usar el  WCF configuration wizard:

Ok, ¿pueden ver los tres tabs, a la derecha? ¡Son más opciones para llenar y entender! ¿Pueden ver el árbol a la izquierda? Es sólo la punta visible de un iceberg. Si expandimos la rama de bindings, entraremos en nuevo mundo de Narnia:

Más propiedades para llenar, ¡y más tabs! Empezará a sentirse incómodo. Si tiene coraje, cree y expanda cualquier cosa en el branch advanced:

El árbol comienza a parecerse a una selva amazónica. Podría tomar capturas de pantallas de cada una de las ramas que el wizard expone, en tal cantidad que podría publicar un volumen completo.

Mucas de estas opciones SON REQUERIDAS si queremos asegurar la comunicación de nuestro servicio, usar tokens emitidos por otras máquinas, definir la autenticación del cliente que invoca y el servicio que atiende, y más. Mi punto es: si Ud. falla en llenar y definir una mínima parte de todo esto, su sistema será un castillo de arena, una torre de cartas en delicado equilibrio. Parace un efecto mariposa: el vuelo de una mariposa en un archivo de configuración, podría crear una tormenta en el resto del sistema. Deberá prestar atención a DEMASIADOS detalles. Es común tener que prestar atención a los detalles en el desarrollo de software. Pero en este caso, pienso que es demasiado: es insano para cualquier mente humana, o para un equipo de desarrollo y despliegue.

En otros sistemas, también tenemos multitud de opciones (¿recuerdan las propiedades un control de formulario?). Pero uno no conocerlas en profundidad a todas (ni siquiera a la mitad), para conseguir algo útil. No es el caso con la configuración de WCF. Este estado de las cosas, apesta. Y si uno quiere escribir directamente en el XML de configuración, terminará con quizás cientos de líneas como:

 

Hay pocas cosas más feas que haya encontrado en mis treinta años de desarrollo (podría enumerar: configuración de EJB, ideas de Cocoon, el Job Control Language en los mainframes IBM...).

Tengo una teoría. Enrico Fermi preguntaba: si los extraterrestres existen, ¿dónde están? ¿por qué no vemos ninguno? La historia es: ellos existen. Comenzaron a estudiar nuestro planeta hace décadas (recuerden, los primeros avistamientos se dieron cerca del Monte Rainier, ¡sí! cerca de Seattle, ya comenzaban a darse cuento que por ahí comenzaba a haber algo raro). Por años, leyeron nuestra literatura, vieron nuestra producción fílmica, hicieron experimentos controlados con seres humanos elegidos. Pero cuando hace unos años comenzaron a estudiar la configuración de EJB y WCF, nuestro planeta estuvo condenado: lo declararon en cuarentena, nadie puede contactarnos, estaremos aislados del resto de la galaxia por diez mil años. La humanidad es una loca civilización, no esperanza sobre nuestro futuro. Nadie puede visitarnos, para que la locura de EJB y WCF no se expanda.

Ok, paro de quejarme. WCF tiene un gran modelo de servicio: ahora, puede manejar JSON, XML, y está preparado para ser flexible y extensible. Pero algunas veces, debemos parar la pelota, y poner en la balanza, no sólo la flexibilidad, sino también la complejidad de la que viene acompañada. Espero escribir posts más positivos, con ejemplos concretos, pero este post ha sido el resultado de días de lucha con WCF, ejemplos, documentación y guías de implementación.

Nos leemos!

Angel "Java" Lopez
http://www.ajlopez.com/
http://twitter.com/ajlopez

Posted Thu, Mar 5 2009 10:16 by lopez | 8 comment(s)