January 2012 - Posts
En este nuevo año, estoy participando en la creación de una aplicación, en un equipo ágil, usando un Scrum-like (iteration reviews, planning, standups, iteration backlog, etc..). Tecnologías: .NET, C#, ASP.NET MVC, Azure, SQL Server, y más (en cualquier momento aparece JSON, REST, Javascript, jQuery, algún NoSQL, cache en memoria, etc…). Pero lo interesante de esta aplicación es que ha nacido prácticamente como “green field”. Si bien el proyecto completo tiene casi un año de existencia (y hasta tiene proyectos antecedentes que se remontan a 3 años atrás), la aplicación que le ha tocado a mi equipo es nueva: nace desde un File, New Project.
El proyecto es privado, así que no hay repositorio público para mostrar avance. Pero quería comentar en este post algunas de las estrategias que estamos usando para avanzar en el proyecto.
Primero: buscar basarnos en casos de uso. Anteriormente, el proyecto se basó demasiado (en mi parecer) en solucionar temas técnicos, sin llegar a hacer pie en lo que realmente se necesita. Entonces, desde la primera iteración (son semanales) nos concentramos en mostrar algo que funcione. Si bien hay varios riesgos técnicos a tomar en cuenta, no fueron (todavía) el centro de atención. Nos parece que para el cliente final lo mejor AHORA es mostrar algo andando, para que pueda explorar si es lo que necesita.
Veamos un ejemplo de estrategia: en vez de modelar el dominio con persistencia en la base de datos, lo principal del mismo ESTA EN MEMORIA, en objetos que solamente viven en memoria: persistencia, concurrencia, transacciones no están en la agenda actual, porque por las características del sistema (disculpen no dar más detalles, es privado) NO SON EL TEMA a tratar AHORA. Es mejor explorar una base de solución ahora, que tener todas las piezas en su lugar.
Como el cambio es constante (al aparecer nuevas historias, al reflexionar el cliente final sobre cómo quiere que quede el producto final, sus casos de uso), todo se ha ido construyendo con TDD (Test-Driven Development). El Code Coverage es > 85%, en general (incluido los controladores de vistas web, estamos usando ASP.NET MVC). Cuando hubo que cambiar algo en la segunda iteración (un refactor de los que yo llamo “quirúrgico”) todo esta en su lugar para que los tests nos ayudaran a comprobar que al cambiar la implementación interna todo siguiera funcionando como se esperaba.
Otro ejemplo: esta semana pasada, gran parte del dominio paso a estar persistida en SQL Server (y en Azure SQL Server). El lunes completamos la implementación de almacenamiento/persistencia en esa tecnología, usando TDD, luego la inyectamos en los lugares apropiados, y prácticamente no se rompió ningún test. En la entrega del viernes, tenemos parte del dominio en memoria (para hacer cambios rápidos) y parte en SQL Server (para ir explorando algo más cercano al producto final). Pero estamos preparados para cambiar esa persistencia a Azure Table Storage, si hace falta, y por qué no, al nuevo DynamoDB de Amazon. El desarrollo ágil y TDD nos da el “courage” (coraje) de abrazar el cambio.
TDD, en vez de ser un gasto de tiempo, es un gran avance: primero, nos sirve en el diseño de lo que implementamos. Luego, nos sirve en ir armando algo sin gastar tiempo en pruebas manuales o sesiones de depuración. Vamos avanzando de a “baby steps” (pasos de bebé): cada nueva característica se agrega con TDD, y la vamos integrando. Desplegamos en Azure más de una vez al día, para que el cliente final pueda ir viendo los avances. Las nuevas características se van anunciando en la lista del proyecto.
Otro ejemplo: el jueves se comenzó a implementar temas de seguridad (autorización en particular, con usuarios y grupos). ¿Acaso implementamos eso usando alguna tecnología? ¿Fuimos e instalamos Azman o cualquier otra cosa? ¿Fuimos a usar Access Control System, tokens y claims? No. Armamos los tests e implementamos la lógica (permisos, reglas) en memoria. El viernes ya estaba listo para la demostración, con distintos usuarios (de nuevo, definidos en memoria). De ahora en más, podemos tener retroalimentación del cliente y usuarios finales, sobre qué es lo que funciona o no del “approach” que adoptamos. Sabemos que alguna parte de la implementación puede sufrir en escalabilidad. Es parte de lo que tenemos en el radar. Pero, como digo, “no cruzar el puente antes de llegar al puente”. No es (en este proyecto en particular, cada uno de Uds. analizará su caso y contexto) lo PRIORITARIO ahora. En vez de estar semanas viendo cómo implementar eso con Azman, o con claims, o lo que sea, ya en dos días tenemos algo funcionando, listo para refactorizar a tecnología PORQUE TENEMOS los tests.
Claro que no todo tiene que ser un lecho de rosas. Pero, por lo menos yo, estoy muy contento y entusiasmado por este camino que tomamos. Espero que todo esto permita llevar a buen puerto un proyecto que ya lleva muchos meses dando vueltas.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Hoy me entero, en la lista rubysur, gracias a un mensaje del bueno de @etagwerker, de la próxima reunión de Ruby en Buenos Aires. Este es el mensaje:
Quería anunciar el meetup de Febrero:
Jueves 9/2 @ Vurbia - Guatemala 5000 (y Uriarte)
Si van a ir, por favor anotense acá:
https://docs.google.com/spreadsheet/viewform?formkey=dDNjZzhfV2RZQnN0WDJRNllaWFV5Nnc6MA#gid=0
Acá van a poder ver las charlas propuestas:
https://docs.google.com/spreadsheet/ccc?key=0AiLxWdzFG7oWdDNjZzhfV2RZQnN0WDJRNllaWFV5Nnc
Si quieren sponsorear o hostear el próximo meetup, escriban a meetup@ruby.com.ar
La anterior reunión había sido en diciembre. A pesar de haberme comprometido a concurrir en mi semana sabática, no fui: estuve bastante concentrado programando y estudiando. Haber ido hubiera sido tener como casi 3 horas de ida y vuelta más 2 horas de actividad, seguramente interesante. Esta vez, para no faltar, me comprometo a dar una charla de AjLisp en Ruby: no sé si a alguien le va a interesar, pero por lo menos me pone en compromiso público para ir :-)
[Incidentalmente, un intercambio de mensajes en esa lista (sobre activity feeds y redis) fue el disparador de dos proyectos de los que tengo que escriibir posts: AjActivity (implementando activity feeds) y AjKeyvs (simple key value store). Ambos implementados en C#]
En otro email, @etagwerker informó en la lista sobre la actividad de la reunión del 15 de diciembre pasado:
Tuvimos 2 charlas:
1. Yo hablé de la gema de templates Liquid y cómo lo estamos usando en mi emprendimiento para que diseñadores web puedan customizar sus tiendas online.
Un par de enlaces:
- http://liquidmarkup.org/
- https://github.com/Shopify/liquid/wiki/ES-Home
- http://www.ombushop.com/liquid-api/index.html
2. @lucasefe habló de Grape y cómo le sirvió para construir una API REST JSON para su plataforma de donaciones de marca blanca (https://mycharitybox.com/)
- https://github.com/intridea/grape
- http://rubygems.org/gems/rack-jsonp
- https://github.com/apotonick/roar
Al final, no recuerdo quién trajo regalitos de @schacon de Github, calcomanías y una remera, para regalar.
Quedan calcomanías para los que vayan al próximo meetup y además vamos a sortear la remera entre los participantes.
Hmm… alguien se había propuesto hablar sobre Amazon Web Services, creo, con Ruby. Pero parece que no se hizo esa charla.
Vean en https://docs.google.com/spreadsheet/ccc?key=0AiLxWdzFG7oWdDNjZzhfV2RZQnN0WDJRNllaWFV5Nnc las charlas propuestas.
Mis posts sobre Ruby.
Nos leemos!
Angel "Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Anterior Post
En el anterior post, mostré el procesamiento del juego en el Windows Azure Toolkit for Social Gaming (versión 1.1.1, hay una nueva 1.2.0 pero aún en beta). Ahora, es tiempo de ver cómo agregar Node.js como servidor de juego a nuestro simple juego de Ta Te Ti.
Vean que todo el código client de Game Service es agnóstico del juego, es decir, no depende del juego que se está implementando. Y vean también que ese Game Service en javascript puede ser cambiado para usar otros servicios. En este post, veremos cómo cambiar el procesamiento de las jugadas para usar una instancia del servidor Node.js.
Primero, bajarse el código a agregar de mi GitHub:
https://github.com/ajlopez/SocialGamingExtensions
Entonces:
1 – Bajar e instalar el Windows Azure Toolkit for Social Gaming versión 1.1.1, desde:
http://watgames.codeplex.com/releases/view/77091
1 – Instalar Node.js para Windows, desde http://nodejs.org/#download
2 – Cambiar al subdirectorio server de mi código, y ejecutar el comando:
npm install socket.io
La librería socket.io se bajará e instalará en el subdirectorio node_modules:
Vean que baja bastante:
3 – Iniciar el servidor de node:
node gameex.js
El servidor comienza a escuchar:
4 – Copiar el directorio client de mi código al directorio del proyecto SocialGaming.Web. Los archivos Web.config, BaseController.cs, TicTacToeController.cs serán reemplazadas. Hay nuevos archivos: Scripts\game\GameServiceNodeJs.js, Areas\Samples\Views\TicTacToe\NodeJs.cshtml.
5 – Abrir la solución de Microsoft en el Visual Studio 2010 (run as administrator) y agregar esos nuevos archivos al proyecto SocialGaming.Web. El nuevo GameService a usar para Node.js:
La nueva vista TicTacToe que usa al Node.js:
La nueva acción en el controlador TicTacToe:
Y la nueva entrada en el web.config:
El reemplazado BaseController lee esa nueva configuración, que queda disponible para ser usada por la vista:
6 – Iniciar la aplicación, debería ejecurtarse como http://127.0.0.1:81 (en puerta 81) para ser aceptada por la seguridad federada configurada en el portal de Access Control Service.
7 – Navegar a /Samples/TicTacToe/NodeJs. Ver la URL de invitación:
8 – El cliente se conecta con el servidor de Node.js. Dependiendo de las capacidades del cliente, socket.io usará WebSockets o XHR long polling:
9 – Abrir un nuevo explorador, en una sesión privada, y navegar a la URL provista en el paso 7
10 – Hay dos jugadores. El de la derecha (el invitado) jugó en la celda del top izquierdo. El primer jugador (el de la izquierda) recibe la nueva movida y actualiza su tablero.
11 – Ver la consola del servidor Node.js: la movida fue recibida y enviada a todos los participantes de esta instacia de juego:
Bien! Trabajo para el hogar: agreguen el Node.js para publicarse en un worker role. Vean el post de @ntotten NodeJS on Windows Azure).
Próximos temas: explicar en detalle el código del servidor que ejecuta Node.js (por ejemplo, soporta sockets TCP además de socket.io; de esta manera podemos programar un cliente en otras plataformas, desde Silverlight a IPhone a Android, sin depender de tener que usar una librería Socket.io en esos clientes).
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Anterior Post
Quiero en este post presentar el procesamiento de las jugadas del ejemplo simple de Ta Te Ti. Involucra varias partes, desde la vista Razor que usa Javascript, hasta el Web Role, hasta el Azure Blob Storage.
Estos son los archivos javascript referenciados en la vista TicTacToe (en el archivo SocialGame.Web/Areas/Samples/Views/TicTacToe/Index.cshtml):
<script src="@Url.AreaContent("Scripts/jQuery.tmpl.js")" type="text/javascript"></script>
<script src="@Url.AreaContent("Scripts/knockout-1.2.1.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/game/ServerInterface.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/game/GameService.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/game/UserService.js")" type="text/javascript"></script>
<script src="@Url.AreaContent("Scripts/game/TicTacToeBoard.js")" type="text/javascript"></script>
<script src="@Url.AreaContent("Scripts/game/TicTacToeGame.js")" type="text/javascript"></script>
<script src="@Url.AreaContent("Scripts/game/TicTacToeViewModel.js")" type="text/javascript"></script>
<script src="@Url.AreaContent("Scripts/game/TicTacToeController.js")" type="text/javascript"></script>
Como escribí en el aterior post, tanto ServerInterface, GameService como UserService son agnósticos del juego, pueden reusarse para cualquier juego. Para cada nuevo tipo de juego X, lo que tenemos que programar son los XBoard, XGame con la lógica del juego, el XViewModel y el apropiado XController.
Al final de esa vista, se encuentra la creación de los servicios agnósticos del juego a usar desde el cliente:
var apiURL = "@this.ViewBag.ApiUrl";
var blobURL = "@this.ViewBag.BlobUrl";
var si = new ServerInterface();
var gs = new GameService(apiURL, blobURL, si);
var user = new UserService(apiURL, blobURL, si);
Las propiedades @this.ViewBag son llenadas en el servidor, en el controlodor de ASP.NET MVC (ver BaseController.cs)
La creación del controlador del juego:
// check for canvas, show an "Upgrade your browser" screen if they don't have it.
var canvas = document.getElementById('board');
if (canvas.getContext == null || canvas.getContext('2d') == null) {
$("#game").toggle();
$("#notSupported").toggle();
return;
}
var board = new TicTacToeBoard(canvas);
var game = new TicTacToeGame();
var controller = new TicTacToeController(viewModel, gs, board, game);
controller.setGameQueueId(gameQueueId);
controller.start();
Pero la parte interesante está en el constructor del controlador:
function TicTacToeController(viewModel, gameService, board, game) {
this.viewModel = viewModel;
this.gameService = gameService;
this.board = board;
this.game = game;
this.started = false;
var controller = this;
this.board.onMove = function (x, y) { controller.onMove(x, y); };
};
Notemos el this.board.onMove: el controlador se registra a sí mismo para procesar las nuevas movidas detectadas por el componente que maneja el tablero. En su método start(), el controlador se registra a sí mismo para procesar las actualizaciones detectas por el servicio de gameService:
controller.gameService.process(
gameQueueId,
function (queue) { controller.processGameQueue(queue); },
function (action) { controller.processAction(action); }
);
Examinemos el procesamiento de las jugadas.

1 – El componente del tablero detecta un click, determina la casilla, y envía una nueva movida al controlador, usando el callback onMove
2 – El controlador envía la nueva movida para la lógica del juego, para actualizar el estado (he omitido el view model en este gráfico)
3 – El controlador envía la nueva movida al game service.
4 – El game service envía un nuevo comando al web role, usando el server interface
5 – La API del web role recibe el nuevo comando
6 – La información del comando es agregada al blob que refleja el estado del juego, almacenado en el Azure Storage
Ahora, veamos el procesamiento en el otro cliente:

1 – El game service, usando un timer, va leyendo reiteradamente el stado del juego, usando la service interface
2 – La service interface, usando JSONP, recupera el estado actual del juego, desde un blob de Azure Storage
3 – Si una nueva movida es detectada en ese estado, el game service llama a una función callback provista por el controlador (el game service no tiene referencia al controlador).
4 – El controlador envía la nueva movida a la lógical de juego, que actualiza su estado (omití el view model en este gráfico)
5 – El controlador envía la nueva movida al componente de tablero, para actualizar el canvas
Un punto clave: el controllador no conoce NADA acerca de la service inteface, la API de WCF Web, el blob storage. Entonces, podemos cambiar el game service para que procese las movidas de otras maneras. Próximo post: modificar el game service para usar a Node.js como servidor de las movidas del juego.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
El martes 6 de Diciembre de 2011 asistí al:
Introducción a jBPM5 (Drools Platform)
organizado por el JBoss User Group Argentina. Me enteré de estas reuniones gracias al Java User Group de Argentina (y a gracias a @HernanHHT):
http://www.jugargentina.org/
Esta fue la primera reunión, y se realizó en las oficinas de Red Hat en Puerto Madero, Buenos Aires. Pueden seguir a @JBUGArgentina en Twitter. Los “slides” de la presentación pueden verlos en:
jBPM5 Introduction – Spanish – Extended Version
Fue una muy buena presentación (duró una hora y media) dada por Mauricio Salatino (http://salaboy.com/ @salaboy) y Marianao De Maio (@marianbuenosayr). Fueron tal vez muchos temas, en el tiempo disponible, pero fue muy interesante. El principal tema fue jBPM5, ver:
jBPM – JBoss Community (solución de process/workflow)
Que es parte de la plataforma abarcativa:
Drools – JBoss Community (que incluye un Business Rules Manager, un procesador de eventos complejos, un rule engine, y más)
Puntos a destacar, en este primer post:
- Se expuso la Community Edition, que está escrita en Java, y es de código abierto. Pueden ejecutarla en varias plataformas (incluso Windows)
- La gente de Red Hat tiene una versión con soporte (pago). Pero comentaron, que al contrario de otras iniciativas que liberan como código abierto versiones que ya quedan en el tiempo, RedHat basa su estrategia de innovación en el soporte de la comunidad: la versión Community ES LA VERSION avanzada, con más “features” experimentales, etc. La de soporte es una versión algo anterior, con el valor agregado de RedHat, vigilando su estabilidad.
- Como caso de éxito de esta estrategia, apareció en esta charla el caso de la evolución de jBPM, para llegar a la versión presentada, la 5. La gente de RedHat había avanzado con jBPM hasta la versión 3. Mientras, el grupo Drools, que trabajaba produciendo código abierto, empezó Drools Flow, un sistema de manejo de procesos y flujo de trabajo. Ya jBPM (el producto comercial original) tenía sus clientes en todo el mundo, cuando se preparó la versión 4. Pero no prendió en el mercado. El grupo de desarrollo original de jBPM abandonó RedHat, y formó otra empresa, basada en lo que habían hecho en jBPM. Mientras tanto, el producto comunitario Drools Flow venía creciendo con buena aceptación y con una nueva forma de encarar el tema de workflow. RedHat vió la potencialidad de ese producto, y por razones de marketing, lo rebautizaron jBPM5. Pero no tiene nada que ver con los jBPM anteriores: las ideas y el código base es totalmente distinto. De todo Drools, es lo único que fue rebautizado.
Luego de la presentación, nos agasajaron con comida (excelente las medialunas rellenas (sólo superadas por las idem de la RubyConf de Argentina, que venían con queso recién derretido ;-), los sandwiches de miga de varios gustos, y algo que llamaría canapé, un delicatessen.. varias heladeras con distintas bebidas… a ver si aprende Microsoft ;-) mensaje para @masaez ;-). Ahí (cerca de las 20:30hs) me tuve que ir. Iban a comenzar un taller, con práctica en Notebook, usando JDK 1.6, Eclipse (y creo que Maven… ooopss .. me dió cosita ;-) tanto en Linux como en Windows y hasta creo Mac. Me pareció que se extendió mucho entonces, porque la gente se fue tarde. Pero fue una impresión, no me quedé, tenía que volver a mi cubil principal.
Tomé varias notas de la charla, ya las presentaré en próximos posts (este es el primero de una serie). Una idea rondando (que comenté en mis resoluciones del nuevo mes; hubiera querido comenzarla en mi semana sabática, pero no la incluí en mis “commitments” porque veía que necesitaba más tiempo): comenzar un rule engine basado en algo parecido al algoritmo Rete, supongo que en C#, practicando TDD.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
En mi opinión, usar un año para planear objetivos es demasiado tiempo. Prefiero tener periodos más cortos para iteraciones de vida. Un año da demasiado tiempo para la pereza, pérdida de foco y “procratination”. Mi propuesta: tener objetivos mensuales. Ayer domingo, escribí sobre mis resoluciones públicas del nuevo mes. Ahora, es tiempo de escribir una lista corta de resoluciones del nuevo mes, casi todas con entregables públicos:
- Implementar Id en los nodos de AjCoRe (simple Content Repository)
- Implementar Server/Client en AjKeyvs (Key Value Store)
- Comenzar una nueva versión de mi framework simple PHP, rejuveneciendo uno viejo de principios de siglo, a publicar en mi cuenta de GitHub
- Publicar un ejemplo de servidor web simple en mis ejemplos Node.js
- Publicar un juego simple en HTML5/Canvas game usando Node.js como servidor del juego (en Node.js samples)
- Continuar trabajando en AjLang, intérprete con sintaxis tipo Ruby, que maneja tipos y objetos .NET
- Continuar trabajando en AjLisp en Java
- Jugar con Clojure REPL
- Comenzar a escribir AjRools.Expert, un “rule engine” en C#, a la JBoss Drools Expert, pero con el algoritmo desarrollado desde cero, usando TDD, a publicar en mi GitHub)
Podría agregar publicar posts de algunos de estos items, pero casi todos tienen repositorios públicos, así que los “commits” que haga en ellos serviran como prueba del avance.
Después de este primer mes de resoluciones (Enero de 2012), escribiré otra nueva lista, posiblemente mejor, con mejores definicies de trabajos y salidas esperadas. Muchas de estas resoluciones están motivadas por estudiar cosas nuevas, y practicar, practicar, practicar, practicar.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez