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

Un Buen Proyecto (1)

En mis charlas de TDD (Test-Driven Development) comento algunas características de lo que tendría que ser un proyecto bien terminado. Algo ya comenté en TDD y Diseño de Implementación (1). Hoy quiero escribir (es decir, pasar en limpio, compartir, explicar un tema para ver si lo entiendo) sobre un tema más amplio: lo que considero un buen proyecto. Pensé inicialmente que bastaría un solo post, pero nones: éste va a ser el primero, y luego seguiré escribiendo.

Pongo algo de contexto. Voy a escribir sobre un proyecto:

- Profesional

- Con desarrollo ágil en equipo, con iteractiones, backlog, etc..

- Cliente externo, con un representante

- Para ejecutar en producción

Es decir, no necesariamente tiene que ser de código abierto (en mi caso en general no es), no es algo que armamos en nuestro tiempo libre (no, es un proyecto de nuestro trabajo de desarrollo de software), no es una demo, va a estar en producción y tendrá un ciclo de vida (no necesariamente apoyado por nosotros: el proyecto tiene una terminación y una entrega final). Igual admito que es difícil abarcar todos los proyectos profesionales. Pero creo que con lo que voy a describir varios proyectos serán incluidos en esta exposición.

Entonces, en este marco, ¿cuáles son las características que tendría que tener un proyecto terminado para que digamos: “es un buen proyecto”? En el sentido de sentir y pensar que lo que entregamos es bueno. Claro, depende de bueno ¿para quién? Como estamos en un proyecto profesional, lo principal es que sea bueno para el cliente (empresa) que nos contrata. Puede ser bueno para nosotros (“uy, aprendí un montón de MVC”), para el equipo (“nos integramos y conocimos”), para nuestra consultora (“uy, con lo que ganamos podemos comprar nuevas oficinas”, o “ahora podemos ser conocidos por haber trabajado en este gran proyecto”), para el mundo (“ahora hay un nuevo framework que todos podrían usar para ser más productivos, etc… “). Pero lo que importa es:

TIENE QUE SER BUENO PARA EL CLIENTE

Vean que más arriba escribí “cliente (empresa)”. Es decir, tiene que ser bueno para la empresa o sector de la empresa que nos contrata. No hay que medir (en principio) que sea “bueno para Charles”, por ser Charles nuestro contacto principal en la empresa. A no ser que sea Charles el que pague la factura, no es el “cliente”. Es un representante del cliente.

Para ponerlo en claro: no es QUE NO IMPORTA absolutamente que nosotros encontremos que el proyecto haya sido bueno para Charles, para el equipo, o para nosotros mismos. No, estoy tratando de encontrar cuál es lo MAS importante.

Pues bien, después de haber participado en este siglo en varios proyectos ágiles, y también viendo el resultado de otros varios más proyectos, con casos de éxitos y fracasos, lo mejor que puedo decir es:

Un proyecto es un buen proyecto terminado y entregado, SI SOLUCIONA EL PROBLEMA DEL CLIENTE

No nos piden simplemente “necesitamos el sistema X”, sino, “necesitamos el sistema X que solucione el problema P”. Otras veces, nos dan más libertad “necesitamos una solución S que solucione el problema P”, pero es menos frecuente el caso. Pero muchas veces (la mayoría de ellas) nos piden “necesitamos el sistema X” sin poner muy en claro el problema que tiene que solucionar.

Para poner un ejemplo. Supongamos que nos piden “Necesitamos un Sistema de Producción”. Puede ser que el contexto del cliente sea:

“Somos una empresa productora familiar, que en los últimos años, con la entrada de la tercera generación en la gerencia, ha podido expandir el mercado en el exterior”

Entonces, puede el problema a solucionar puede ser uno de éstos, entre tantos:

1 - “Se nos ha ido de las manos la producción, necesitamos un sistema que nos permita manejar mejor la asignación de las máquinas. Hoy las desaprovechamos”

2 - “Las máquinas las asignamos bien, pero tenemos problemas en el seguimiento de los insumos que necesitamos y cuándo los necesitamos. No queremos tener stock de esos insumos en estos tiempos de cambio”

3 - “Nuestros principales clientes del exterior nos piden trazabilidad norma (y aquí viene una sigla desconocida para nosotros) de acá a fin de año, sino perdemos nuestro principal contrato con China”

4 – etc

Vean que entendiendo el problema podemos poner distinto énfasis en lo que vamos a construir, y con el representante del cliente, podemos tener más en claro qué es lo que aporta más valor al cliente. En el caso 1, tendremos que poner mayor esfuerzo en un plan de asignación de máquinas, y no tanto en el stock de insumos. En el caso 2, es al contrario. Y en el caso 3, tendremos que estudiar qué es eso que piden de trazabilidad.

Pero vean a lo que voy: podemos entregar el mejor sistema de producción, que asigne con algoritmos de inteligencia artificial las máquinas de la mejor forma posible, escrito con todos los patrones encima, con la mejor UI para desktop, web, tablet, y hasta TV,  pero no es la solución del problema del cliente, si estamos en el caso 3.

ESO ES LO QUE HAY QUE ENTENDER PRIMERO.

A ver, de nuevo:

EL ENTREGABLE DEL PROYECTO DEBE SOLUCIONAR EL PROBLEMA DEL CLIENTE

Y acá entra la capacidad del representante del cliente para ponernos más en claro cuál es el problema real.

No quisiera terminar el post, sin comentar algo. Hay diferencia entre problema y solución. Como escribía arriba, muchas veces nos piden el sistema. Pero tenemos que esforzarnos, como profesionales, para ver si el sistema inicial pedido soluciona o no el problema, o si es el mejor camino para solucionar el problema. En general, eso ya se definió antes de llegar el proyecto a nuestro equipo. Pero igual deberíamos tenerlo en cuenta. Tal vez, en vez de hacer sistema S, podemos hacer sistema S’ que tenga algunas características sugeridas por nosotros que mejoren alcanzar la solución del problema.

Siempre recuerdo a Henry Ford, diciendo: “Si le hubiera preguntado a mis potenciales clientes qué querian, me hubieran pedido ‘caballos más rápidos’”.

Nos leemos!

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

Posted Thu, May 16 2013 11:41 by lopez | 1 comment(s)

Aprendiendo Ruby

Como ya había anunciado, ayer dí una charla de introducción a Ruby, pueden ver y descargar la presentación en mi Skydrive.

En la presentación hay tres slides todavía en blanco, y slides al final de temas que quedaron expresamente afuera. Pero lean más abajo donde está toda la presentación explicada en detalle, y los ejemplos que usamos.

Para la instalación de Ruby, comenté:

http://www.ruby-lang.org/en/downloads/
En Windows http://rubyinstaller.org/
Dev Kit https://github.com/oneclick/rubyinstaller/wiki/Development-Kit
Mingw, Minimalist GNU for Windows
http://www.mingw.org/

Para esta charla usé Ruby 2.0.0, y aclaré que lo más usado todavía es 1.9.x. Igual, los cambios son evolutivos, no hay grandes “roturas” en 2.0.0, pero como hay algunas gemas y frameworks que todavían corren solamente en 1.9.x, les conviene revisar cuál quieren usar. Al menos en Windows, se pueden instalar las dos versiones, y luego agregar al PATH cuál es directorio binario que queremos usar.

Estuvimos viendo temas de Ruby como lenguaje dinámico e interpretado, sintaxis básica, todo es un objeto, todo es un valor, módulos (comentando al pasar include, faltó extend), evaluación dinámica, su relación con Smalltalk, clases abiertas, ejemplo de Domain-Specific Language, y levantamos un sitio con tres páginas simples, con Sinatra y ERB.

Algunos temas más:

Mencioné que Sinatra usa WeBrick http://www.ruby-doc.org/stdlib-2.0/libdoc/webrick/rdoc/WEBrick.html incorporado desde hace un tiempo directamente en Ruby.

Mencioné Rack http://rack.github.io/ que habría que estudiar alguna vez para entender la infraestructura web de Sinatra y Ruby On Rails (no es necesario pero es intersante). Rack se inspira en trabajos anteriores, principalmente en Python ver http://en.wikipedia.org/wiki/Web_Server_Gateway_Interface

Los ejemplos (tres páginas en Sinatra, y un DSL), quedaron en:

https://github.com/ajlopez/AprendiendoRuby/tree/master/ejemplos

El ejemplo de DSL fue una simple traducción a español del ejemplo de http://jroller.com/rolsen/entry/building_a_dsl_in_ruby

Si les interesa el tema DSL, estoy publicado enlaces en mi otro blog: http://ajlopez.wordpress.com/category/domain-specific-languages/

Y finalmente, la presentación me sirvió para ir escribiendo las primeras páginas de mi tutorial de Ruby en línea:

https://github.com/ajlopez/AprendiendoRuby#aprendiendo-ruby

Lo voy a ir completando con más capítulos, detalle, referencias, fuentes consultadas, ejercicios. También tengo que poner en línea lo que armé alguna vez en PHP: sitio con exámenes por preguntas y respuestas. Tengo también material (si recuerdan este blog, publicado hace ya un tiempo) de PHP y Java para poner en páginas GitHub. Algo más demandante sería escribir sobre Node.js, pero es candidato. Y sobre Clojure. Como mencioné en otro post, al explicar terminamos entendiendo ;-)

Nos leemos!

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

Posted Tue, May 14 2013 12:46 by lopez | 1 comment(s)

Mass Lenguaje de Programación (4) Lexer y Parser

Anterior Post

En la implementación del lenguaje Mass, tengo una enumeración y una clase:

Un Token representa una palabra del código a procesar. El encargado de separar el código en palabras es el Lexer. Y con el Parser se transforma esa corriente de Tokens en expresiones y comandos:

El constructor de Lexer recibe un string:

public Lexer(string text)
{
    this.text = text;
}

Y ese string es procesado para separarlo en tokens. Vean que el Lexer distingue entre operadores (como +) y separadores (como los paréntesis). También toma en cuenta al fin de línea como token (en otros lenguajes, como C, un fin de línea se puede tomar como un espacio en blanco en muchas situaciones). El principal método de Lexer es NextToken, que devuelve el próximo Token del texto. En algunas pocas situaciones, se hace necesario devolver el Token consumido, y para eso está PushToken y varianes.

El Parser interamente maneja un Lexer. Le podemos pedir el próximo comando con ParseCommand, y la próxima expresión con ParseExpression. Cuando el texto en proceso se acaba, esos métodos devuelven null.

Voy a modificar el Lexer para consumir un stream de texto, para poder procesar, por ejemplo, entrada de consola

Tengo que seguir pensando si internamente, unifico comandos y expresiones, como pasa en Ruby, donde cada “comando” tiene un valor (en Mass también es así), y no solamente eso, sino que puede ser usado como expresión en el contexto de un comando.

Nos leemos!

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

Posted Sun, May 12 2013 9:40 by lopez | with no comments

Introducción a Ruby, en Buenos Aires

Gracias a la gente del Microsoft User Group de Argentina, el próximo lunes daré una charla sobre

Introducción a Ruby para Programadores .NET (o para programadores)

http://www.mug.org.ar/Eventos/3893.aspx

(vean de visitar la página porque hay que inscribirse)

El evento es gratuito, y es el lunes 13 de Mayo, desde las 18:30 hasta las 20:30. La idea es explicar algo de Ruby, introductorio, para programadores (sean de .NET o de otros lenguajes/tecnologías) que no sepan Ruby.

Los temas a visitar:

- Sintaxis básica
- Valores básicos: números, string, arreglos, hashes
- Comandos if, for, ciclos
- Clases y objetos
- Herencia
- Creación de objetos
- Variables de instancia y de clase
- Módulos
- Elementos de metaprogramación
- Definiendo DSL (Domain Specific Languages) internos en Ruby
- Gemas (paquetes de Ruby)
- Ecosistema de desarrollo
- Desarrollo Web, especialmente Sinatra, que usa Rack

Espero poder explicar en dos horas cuál es el panorama de desarrollo Ruby, para cualquier programador interesado en comenzar con este lenguaje.

Nos leemos!

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

Posted Tue, May 7 2013 17:37 by lopez | 1 comment(s)

Resoluciones del Nuevo Mes: Mayo 2013

Primero, una revisión de mis resoluciones de Abril:

- Actualizar Mass [completo] ver repo
- Comenzar NodeAima [completo] ver repo
- Dar curso de un día de Node.js [completo]
- Actualizar AjGenesis [pendiente]
- Actualizar AjGenesisRuby [pendiente]
- Actualizar SimpleGo [pendiente]
- Actualizar RubySharp [completo] ver repo 
- Actualizar ClojSharp [pendiente]

Tambié estuve trabajando en:

- Actualizar AjFabriqNode [completo] ver repo
- Actualizar NodeSamples [completo] ver repo (ver Distributed Fractal)
- Actualizar SimpleStorm [completo] ver repo
- Actualizar SimpleBus [completo] ver repo
- Actualizar SimpleBroadcast [completo] ver repo
- Actualizar SimpleGA [completo] ver repo
- Comenzar SharpAima [completo] ver repo ver post Inteligencia Artificial en C# (1)
- Dar charla de Aplicaciones Distribuidas y Node.js [completo] ver post
- Actualizar AjErl, mi implementación de Erlang en C# [completo] ver repo

Mucho de ese trabajo adicional estuvo relacionado con el material que presenté en Aplicaciones Distribuidas y Node.js.

Ahora, las resoluciones para Mayo:

- Actualizar Mass
- Update RubySharp
- Dar una charla, Introducción a Ruby
- Actualizar AjGenesis
- Actualizar ClojSharp
- Nuevos posts sobre Mass
- Nuevos posts sobre Aplicaciones Distribuidas y Node.js
- Nuevos posts sobre TDD

Nos leemos!

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

Posted Sun, May 5 2013 11:34 by lopez | with no comments

Aplicaciones Distribuidas y Node.js

Como ya lo había anunciado, el martes pasado estuve dando una charla de aplicaciones distribuidas y Node.js, gracias a la gente de Node.js Argentina,  en el auditorio del Microsoft User Group de Argentina, en Buenos Aires.

Pueden ver y bajarse la presentación desde mi Skydrive

La idea fue mostrar algunos conceptos, y experimentos que estuve haciendo con Node.js, convirtiendo anteriores trabajos en otras tecnologías. Y mostrar código con ejemplos concretos.

Primero, expliqué lo que era una aplicación distribuida en el contexto de esta charla. Una aplicación distribuida es una aplicación que se ejecuta en varias computadoras, conectadas en red, que interactúan para resolver un problema. Ver http://en.wikipedia.org/wiki/Distributed_computing

Es decir, va más allá del clásico cliente servidor. Podemos tener varias computadoras para hacer web crawling de un sitio, o resolviendo la renderización de escenas de una película 3d. Las computadores que intervienen en el trabajo no necesariamente tienen el mismo software o programa: puede que algunas se ocupen solamente de algún paso del problema. Tampoco tienen que tener la misma plataforma o lenguaje de programación.

Lo que quise destacar, entonces, en la charla, son las facilidades que nos da Node.js y JavaScript para construir este tipo de aplicaciones. Ya en otras charlas afirmé “JavaScript es una manteca”, para destacar su flexibilidad. Y ahora, en esta charla, tuve la oportunidad de mostrar un tópico donde Node.js brilla: tanto por su soporte de red en los módulos “built-in”, como por su ecosistema, como por la filosofía de combinar módulos (como en Unix, ver Unix philosophy and Node.js de @izs)

Mencioné una entrevista a Alan Kay (ver su Dynabook)


I thought of objects being like biological cells and/or individual computers on a network, only able to communicate with messages

Until real software engineering is developed, the next best practice is to develop with a dynamic system that has extreme late binding in all aspects

The big idea is “messaging”

Es interensante que Kay mencionara células biológicas: nuestros nodos en ejecución pueden tomarse como células, que forman el organismo de nuestra aplicación distribuida. Como dice Kay, el gran tema es el “messaging”, el envío de mensajes entre las partes. Las aplicaciones distribuidas nos dan la oportunidad de olvidarnos del concepto de función/rutina a la que llamamos con parámetros y esperamos que termine de ejecutar para dar un resultado, y aún de una llamada con callback: un elemento de nuestra aplicación distribuida enviará un mensaje, desentendiéndose de obtener una respuesta.

También mencioné a Richard Feynman (algún post de mis enlaces), ver

http://boards.straightdope.com/sdmb/showthread.php?t=159936

Feynman was once asked by a Caltech faculty member to explain why spin 1/2 particles obey Fermi-Dirac statistics. He gauged his audience perfectly and said "I'll prepare a freshman lecture on it." But a few days later he returned and said, "You know, I couldn't do it. I couldn't reduce it to the freshman level. That means we really don't understand it."

Adaptando su frase a “si no lo podemos explicar, es que no lo entendemos” como motivación personal para dar charlas. Recordé su trabajo de estudio “por su cuenta” de la física cuántica según Feyman por Dyson, como justificación lejana a experimentar con un tema, en vez de tomar lo que ya está hecho directamente.

Pues lo que presenté luego, son experimentos sobre Node.js para aplicaciones distribuidas. Pero ¿por qué Node.js? En JavaScript, un mensaje puede ser un simple objeto serializable a JSON (un objeto sin ciclos, o sea, un árbol). Y para el transporte del mensaje podemos elegir multitud de módulos en el ecosistema de Node, como usar el require(‘net’) o require(‘http’) que vienen “built-it” en el núcleo de Node.js

Preguntas que tenemos que hacernos en cada caso de aplicación distribuida:

¿Qué elementos de nuestra aplicación producen mensajes?

¿Qué elementos consumen mensajes?

Un mensaje ¿es consumido por un solo elemento? ¿o puede ser procesado por varios elementos interesados?

Las máquinas y programas que ejecutan ¿están determinados desde el comienzo? ¿o pueden variar con el tiempo? Por ejemplo, me gustaría sumar a mi aplicación distribuida unas cuarenta máquinas que a la noche están ociosas. ¿Se puede hacer? ¿Necesitamos esta característica?

Un mensaje producido en un elemento de una máquina ¿se consume localmente? ¿o puede viajar a otra máquina? ¿quién decide eso? ¿el programador, el programa supervisor?

Y dado un mensaje que tiene que llegar a otra máquina ¿cómo llega? ¿con qué transporte?

Si un mensaje tiene que ser procesado remotamente ¿cómo se selecciona la máquina destino? ¿por programa? ¿por algún balanceo de carga?

Esas preguntas se contestarán diferente en cada experimento o ejemplo que tengamos.

Uno de los experimentos (repetido de distintas formas) es un web crawler, compuesto lógicamente (partes lógicas, luego a implementar de distinta forma según el ejemplo/experimento):

Cuando tengamos que recuperar las páginas de un sitio, primero enviamos una URL inicial a un elemento Resolver. Este elemento mantiene la lista de páginas ya visitadas. Si la URL es una página no procesada aún, se envía la URL a un elemento Downloader (elemento lógico que puede estar implementado en varias máquinas). Es el encargado de conseguir el contenido de la página. Luego le pasa ese dato al elemento Harvester, que extrae los enlaces que consigue encontrar en la nueva página. Los enlaces se envían al Resolver, que examina si corresponde o no procesar esas URLs.

Un módulo que escribí (no fue el primero, sino que surgió de refactor y extracción de otros casos de uso) es ObjectStream

https://github.com/ajlopez/ObjectStream
https://github.com/ajlopez/ObjectStream/tree/master/samples/broadcast

que me permite enviar un objeto JavaScript (serializable a JSON) a un Object Stream, un stream que recibe objetos. Este stream puede enviar ese objeto, ya serializado a texto, por otro stream. Y hay un Object Stream que toma esas líneas de texto y las reconstruye como objetos. Esto me permite usar, por ejemplo, un stream de socket para enviar objetos JavaScript de una máquina a otra. Vean en los enlaces de arriba el ejemplo de Broadcast que mostré en la charla.

Basado en ObjectStream, me animé luego a armar

https://github.com/ajlopez/SimpleMessages
https://github.com/ajlopez/SimpleMessages/tree/master/samples/Broadcast

Permite que dos procesos establezcan canales bidireccionales de envío de mensajes, que arrivan en cualquier momento. Desde el punto de vista del código, uno puede exponer un servidor (o varios) o crear clientes que se conectan a otros servidores. Pero luego de efectuada la conexión, el intercambio de mensajes es simétrico: cualquiera de las partes puede enviar un mensaje en cualquier momento. Ya con esto podemos entretenernos bastante, escribiendo aplicaciones distribudas basadas en mensajes.

Pero a veces, necesitamos más que enviar un simple mensaje. Por ejemplo, se nos puede presentar la necesidad de llamar a un objeto que está ejecutando en otra máquina. Podemos implementar un Remote Procedure Call. Lo hice en:

https://github.com/ajlopez/SimpleRemote

Basado en SimpleMessages, tanto el cliente como el servidor pueden exponer un objeto “hacia afuera”, y la otra parte lo puede invocar, como si fuera un objeto local. Solamente que como el retorno de la respuesta no es inmediato, el programador que llama al método agrega un callback para procesar la respuesta cuando ésta llegue.

Para alternativas pueden ver:

http://stackoverflow.com/questions/5010814/whats-the-best-way-to-make-one-node-js-server-talk-to-another
http://stackoverflow.com/questions/7986088/rpc-and-messagequeues-in-node-js
https://github.com/substack/dnode
https://github.com/Flotype/now
https://code.google.com/p/protobuf-for-node/
https://code.google.com/p/protobuf/
https://github.com/Frans-Willem/IPCNode

Vean dnode, cómo tienen clientes para distintos lenguajes. O vean también algo más agnóstico, http://en.wikipedia.org/wiki/JSON-RPC

Tuve un caso de uso donde necesitaba repartir mensajes, no solamente enviar un mensaje desde A hasta B. Entonces nació:

https://github.com/ajlopez/SimpleBroadcast
https://github.com/ajlopez/SimpleBroadcast/tree/master/samples/Broadcast

De esta manera, un cliente puede enviar un mensaje a un servidor, y éste repartirlo en los demas clientes conectados. Vean que el mensaje no se transmite al cliente que lo originó, sólo a los demás. Hasta puede haber una “estrella” de servidores, donde cada servidor atiende a sus clientes, y actúa como cliente de los otros servidores:

Esto permite la escalabilidad agregando servidores a la estrella. También tiene un concepto algo más sofisticado, el servidor repetidor (ver el código y tests). En este software tuve colaboración de Fernando Lores.

En otros casos de uso, en vez de enviar mensajes, necesité que los que iban a procesar mensajes los pidieran explícitamente. Como quería realizar todos estos experimentos en Node.js, sin depender de software externo, escribí:

https://github.com/ajlopez/SimpleQueue
https://github.com/ajlopez/SimpleQueue/tree/master/samples/DistributedProducerConsumer

Al principio, implementé una cola en memoria, local. Y luego la expuse hacia otras máquinas usando SimpleRemote.

Otro caso de uso con el que me encontré es: necesito publicar mensajes, pero no sé de antemano a quién le interesa. Es similar a los eventos de Node.js: uno emite un evento, pero no sabe quienes se suscribieron a ellos. Llevado eso a algo distribuido escribí:

https://github.com/ajlopez/SimpleBus
https://github.com/ajlopez/SimpleBus/tree/master/samples/Market

Tanto los que publican como los que se suscriben a mensajes pueden estar en máquinas distintas.

En el ejemplo de Market que mostré en la charla (ver el enlace de arriba) la suscripción a los mensajes se puede hacer dando un mensaje ejemplo: todos los mensajes que tengan las mismas propiedades que el ejemplo, serán tomados para procesar por el subscriptor. También puedo enviar un predicado, y notablemente, ese predicado puede “viajar” desde el suscriptor a la maquina que tiene el servidor de bus (que podrían ser varias máquinas en estrella usando SimpleBroadcast).

Muchos de estos casos de uso fueron motivados por implementaciones que tuve que escribir en otras tecnologías. El trabajo que más influyó es lo que hice cuando trabajé para @asehmi:

Ver Remember Fabriq.

Basado en su proyecto Fabriq, reescribí algo en AjFabriqNode:

https://github.com/ajlopez/AjFabriqNode
https://github.com/ajlopez/AjFabriqNode/tree/master/samples/WebCrawler

AjFabriq se basa en tener varios nodos ejecutándose, cada uno declara un árbol de procesadores de mensajes. En base al contenido del mensajem se determina qué procesador de mensaje puede atenderlo. Cada nodo se puede conectar a otro de la red, y entre varios se intercambian cuáles procesadores de mensajes tiene cada uno. Entonces, podemos tener un Web Crawler distribuido donde en un nodo tenemos el resolver, y en otros tenemos downloaders y harvesters.

Otros prefieren enviar los mensajes directamente a un elemento específico. Basado en la implementación de actores en Akka/Scala, ver:

http://doc.akka.io/docs/akka/snapshot/general/actor-systems.html
http://doc.akka.io/docs/akka/snapshot/general/actors.html
http://doc.akka.io/docs/akka/snapshot/general/addressing.html

implementé algo más simple:

https://github.com/ajlopez/SimpleActors
https://github.com/ajlopez/SimpleActors/tree/master/samples/DistributedWebCrawler

Pero vean que en Akka, un mensaje se envía en general a un actor, identificado por su dirección.

Hay un proyecto Java, Storm Project en:

http://storm-project.net/

donde se puede armar una topología con los elementos lógicos que van a recibir, procesar y emitir tuplas (lo que para esta charla es mensajes). Hay productores de mensajes, los Spout, y procesadores de mensajes, los Bolt. Luego cada elemento puede ejecutarse en varias máquinas. Así, podemos tener una topología de Web Crawler con Resolver, Downloader y Harvester. Pero luego poner 20 downloaders en 10 máquinas, y 5 harvesters en las mismas máquinas u otras.

Así que, ni lerdo ni perezoso, escribí algo simple en Node.js:

https://github.com/ajlopez/SimpleStorm
https://github.com/ajlopez/SimpleStorm/tree/master/samples/DistributedWebCrawler

Lo que ví en mis experimentos, es que muchas veces necesito levantar varias máquinas, indicarles qué hacer, que aplicaciones lógicas ejecutar (por ejemplo, el web crawler), y que puedan intercambiar mensajes entre ellos. Mostré:

https://github.com/ajlopez/MultiNodes
https://github.com/ajlopez/MultiNodes/tree/master/samples/collatz

Lo interesante es que un nuevo nodo que se incorpora a la red, puede ser instruido dinámicamente a ejecutar algo (como instalar y lanzar una nueva instancia del web crawler).

Dos ejemplos finales:

Una implementación de algoritmo genético distribuido:

https://github.com/ajlopez/SimpleGA
https://github.com/ajlopez/SimpleGA/tree/master/samples/tspdistr

Y un fractal que se puede calcular en el browser, o en un servidor Node.js/Express, solo o ayudado por nodos worker adicionales:

https://github.com/ajlopez/NodeSamples/tree/master/Fractal
https://github.com/ajlopez/NodeSamples/tree/master/Fractal/html
https://github.com/ajlopez/NodeSamples/tree/master/Fractal/server
https://github.com/ajlopez/NodeSamples/tree/master/Fractal/distributed

Al final, mencioné varias razones para investigar con aplicaciones distribuidas: desde lo interesante del tema, como lo práctico (para Big Data, cálculo distribuido y en paralelo, etc). Pero resalté que tenemos que seguir investigando sobre aplicaciones distribuidas e inteligencia artificial. Nuestro sistema nervioso funciona con varios nodos, surgiendo una aplicación distribuidas en neuronas (¿recuerdan a Alan Kay hablando de células con mensajes?)

Otro de los temas que me interesan es tener lenguajes dinámicos que puedan distribuirse fácilmente entre nodos distribuidos (de hecho, me gustó JavaScript con Node.js, porque me libera de implementar eso). Ver:

Lenguajes de Programación, Computación Distribuida, Inteligencia Artificial
Experimentos Distribuidos

Nos leemos!

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

Posted Sat, May 4 2013 20:36 by lopez | 1 comment(s)

Mass Lenguaje de Programación (3) Comandos

Anterior Post  
Siguiente Post 

Veamos hoy cómo están implementados los comandos en Mass (ver repo). En el proyecto de librería de clases, tengo:

Hay comandos para if, while, for, for each, etc…. Todos implementan la interfaz ICommand:

public interface ICommand
{
    object Execute(Context context);
}

Vean que es muy parecido a IExpression. Igual quise mantener comandos y expresiones por separado, por lo menos en esta primera implementación, para tener un claro delineamiento de los conceptos de base del lenguaje.

Un ejemplo típico de comando es el WhileCommand (parte del código):

public class WhileCommand : ICommand
{
    private static int hashcode = typeof(WhileCommand).GetHashCode();

    private IExpression condition;
    private ICommand command;

    public WhileCommand(IExpression condition, ICommand command)
    {
        this.condition = condition;
        this.command = command;
    }

    public object Execute(Context context)
    {
        for (object value = this.condition.Evaluate(context); 
            value != null && !false.Equals(value);
            value = this.condition.Evaluate(context))
        {
            this.command.Execute(context);
            if (context.HasContinue())
                context.ClearContinue();
            if (context.HasBreak())
            {
                context.ClearBreak();
                break;
            }
        }

        return null;
    }
}

Para Mass: cualquier valor null o false es falso. Todo lo demás es verdadero. Un tema a refactorizar: poner un método IsFalse para se usado tanto en la implementación de While como de If.

Otro ejemplo es el ForEachCommand (parte del código):

public class ForEachCommand : ICommand
{
    private string name;
    private IExpression expression;
    private ICommand command;

    public ForEachCommand(string name, IExpression expression, ICommand command)
    {
        this.name = name;
        this.expression = expression;
        this.command = command;
    }

    public object Execute(Context context)
    {
        var values = (IEnumerable)this.expression.Evaluate(context);

        foreach (var value in values)
        {
            context.Set(this.name, value);
            this.command.Execute(context);
            if (context.HasContinue())
                context.ClearContinue();
            if (context.HasBreak())
            {
                context.ClearBreak();
                break;
            }
        }

        return null;
    }
}

Vean que para Mass, todo lo que sea IEnumerable se puede usar para ser consumido por este comando. Tuve que poner algunos datos en el contexto, para saber si se había hecho un break o un continue.

Y como siempre, todo esto desarrollado con TDD: pueden ver los commits del repo.

Próximos posts: Lexer y Parser, ejemplos de Mass para scripting.

Nos leemos!

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

Posted Sun, Apr 28 2013 12:24 by lopez | 1 comment(s)

Mass Lenguaje de Programación (2) Primeras Expresiones

Anterior Post  
Siguiente Post 

Antes de ver cómo usar el lenguaje Mass (ver repo), quisiera tratar algunos temas de implementación. Primero, una novedad: ahora hay una solución (en https://github.com/ajlopez/Mass/blob/master/Src/Mass.sln) que puede compilarse con algún Visual Studio C# Express, de libre bajada e instalación.

La solución Mass tiene un proyecto de librería de clases. Ahí hay un namespace dedicado a expresiones:

Una expresión es algo que cumple con IExpression:

  
public interface IExpression
{
	object Evaluate(Context context);
}
  

Un Context mantiene un diccionario de nombre/valor, para guardar las variables actuales:

  
public void Set(string name, object value)
{
	this.values[name] = value;
}

public object Get(string name)
{
	if (this.values.ContainsKey(name))
		return this.values[name];

	if (this.parent != null)
		return this.parent.Get(name);

	return null;
}
  

(vean de refilón, que soporta contextos anidados: cada contexto puede “heredar” de un contexto parent).

La expresión más simple es la que devuelve una constante, que puede ser cualquier valor/objecto .NET:

  
public class ConstantExpression : IExpression
{
	// ...

	private object value;

	public ConstantExpression(object value)
	{
		this.value = value;
	}

	public object Evaluate(Context context)
	{
		return this.value;
	}

	// ...
}
  

La siguiente expresión más simple es la evaluación de un nombre de variable en el contexto actual:

  
public class NameExpression : IExpression
{
	// ...
	
	private string name;

	public NameExpression(string name)
	{
		this.name = name;
	}

	public object Evaluate(Context context)
	{
		return context.Get(this.name);
	}
	
	// ...
}
  

Es necesario especificar el contexto (por ejemplo, el contexto de la función actual, de una clausura, del objeto actual, del módulo actual, etc), porque un mismo nombre puede tener distintas variables asociadas, como pasa en otros lenguajes.

Como siempre, cada una de estas clases (Expresiones, Contexto, …) fue armada usando el flujo de trabajo de TDD (ver el proyecto de tests, y la historia de commits del repo donde dejé evidencia de cómo fue el desarrollo en el tiempo).

Próximos posts: algunas expresiones adicionales, comandos, usando Mass para scripting, usando Mass desde nuestro programa .NET, etc..

Nos leemos!

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

Posted Sat, Apr 27 2013 14:26 by lopez | 1 comment(s)

Node.js, Charlas en Buenos Aires: Aplicaciones Distribuidas; Introducción a ZMQ

La gente de Node.js Argentina prepara una nueva reunión para el próximo martes 30 de abril:

http://www.meetup.com/NodeJS-Argentina/events/112809892/

Revisen el horario, la idea era que fuera de 18:30 a 21hs en la zona de Congreso, Buenos Aires, cerca de subtes y multitud de colectivos.

Además de reunión, habrá dos charlas. Una de Fernando Alonso, sobre Introducción a ZMQ con Node, no tengo el temario en detalle. Y además, estaré dando otra charla, sobre uno de mis temas preferidos: aplicaciones distribuidas, en este caso con Node.js. Puede ver mis posts sobre aplicaciones distribuidas en general. Pero esta vez, trataré el tema desde Node.js, que me parece una plataforma excelente para experimentar y trabajar con este tipo de aplicaciones. Algo ya adelanté el año pasado en mi charla del Día del Programador:

Experimentos distribuidos

Ahí encontraran algunos enlaces sobre lo que estoy probando y armando. Algo más lateral, pero para explicar mi interés en el tema distribuido y su relación con otros temas que ven que trato frecuentemente por acá:

Lenguajes de Programación, Computación Distribuida, Inteligencia Artificial

Espero poder transmitir algo de todo esto en la charla del Node.js meetup. Recuerden de revisar la página del grupo, que se vienen más reuniones con otros temas (por ejemplo, la anterior fue sobre Node.js y Raspberry Pi).

Nos leemos!

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

Posted Wed, Apr 24 2013 11:16 by lopez | 1 comment(s)

Nuevo Podcast de 32minutos.net: Agilidad con Martín Salías

El sábado pasado apareció publicado un podcast en el que participé con @martinsalias, conversando sobre agilidad en general. Fue gracias a la gente de http://www.32minutos.net/, @roundcrisis, @dvilchez, @jorgegamba.

El podcast en:

07×03 Agile con Ángel Java López y Martín Salias

Hemos charlado de todo, los principales temas:

  • Disposición al cambio
  • Entrega continua
  • Retrasar la toma de decisiones
  • Product owner
  • Empresas y administración
  • Equipos
  • Stand up
  • Retrospectiva
  • Equipos remotos

 

Vean que Martín toco varios de esos temas, contando experiencias en proyectos y equipos reales. Yo continué sobre la facilidad que da lo ágil para abrazar el cambio, y tomar decisiones ALAP (“as late as possible”). Si tienen alguna duda, le preguntan a @martinsalias ;-)

Gracias a 32minutos!

Nos leemos!

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

Posted Mon, Apr 22 2013 11:21 by lopez | with no comments

Inteligencia Artifical en C# (1) Primeros Agentes

Ayer comencé a implementar ejemplos del libro Artificial Intelligence: A Modern Approach, de Stuart Russell y Peter Norvig. Ver el sitio del libro

http://aima.cs.berkeley.edu/

Hay implementaciones en distintos lenguajes:

http://aima.cs.berkeley.edu/code.html (hay en Python, Java, C#, Prolog, Lisp, … )

Mi implementación en

https://github.com/ajlopez/SharpAima

Quiero ir armándola con TDD. Por ahora me baso en la versión en Python, pero puede que también vea la versión en Java, debido a las diferencias de los lenguajes: C# y Java son lenguajes tipados.

La versión que presento hoy es la 0.0.1

https://github.com/ajlopez/SharpAima/tree/0.0.1

Por cada post iré “taggeando” una nueva versión. Mi primer código trata de implementar los primeros agentes descriptos en el capítulo 2. Me basé en el código de:

http://aima-python.googlecode.com/svn/trunk/agents.py

Tengo una solución con dos proyectos: uno de clases y otro de tests:

La idea es tener agentes en un ambiente:

(Adaptado de la figura 2.1 del libro)

El agente recibe percepciones y genera acciones. La primera implementación es:

public abstract class Agent<TLocation, TPerception, TAction>
{
	public TLocation Location { get; set; }

	public int Performance { get; set; }

	public abstract TAction GetAction(TPerception perception);
}

Y las implementaciones en concreto son de un agente robot máquina aspiradora (VacuumAgent y variantes).

Vean la historia del proyecto, cómo fue evolucionando desde TDD. Primero implementé un agente concreto, y luego fue surgiendo la abstracción de arriba. Noten que en C# tenemos que apelar a algo tipado, y de ahí el uso de tipos genéricos: un tipo de agente concreto se define dando el tipo de lugares (location) que maneja (por ejemplo, una posición X, Y, a implementar en la próxima versión), el tipo de percepciones que recibe (ej: “estoy en lugar A y el lugar está limpio”), y el tipo de acciones (“Limpiar”, “Ir a la Derecha”, … ). En Python es más simple, por no tener tipos.

Nos leemos!

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

Posted Sun, Apr 21 2013 10:04 by lopez | with no comments

TDD Kata (4): La cortadora de césped

Anterior Post

Como comentaba en el anterior post, hace una semana participé de la ronda preliminar del Google Code Jam.

El ejercicio B fue el Lawnmover:

https://code.google.com/codejam/contest/2270488/dashboard#s=p1

Problem

Alice and Bob have a lawn in front of their house, shaped like an N metre by M metre rectangle. Each year, they try to cut the lawn in some interesting pattern. They used to do their cutting with shears, which was very time-consuming; but now they have a new automatic lawnmower with multiple settings, and they want to try it out.

The new lawnmower has a height setting - you can set it to any height h between 1 and 100 millimetres, and it will cut all the grass higher than h it encounters to height h. You run it by entering the lawn at any part of the edge of the lawn; then the lawnmower goes in a straight line, perpendicular to the edge of the lawn it entered, cutting grass in a swath 1m wide, until it exits the lawn on the other side. The lawnmower's height can be set only when it is not on the lawn.

Alice and Bob have a number of various patterns of grass that they could have on their lawn. For each of those, they want to know whether it's possible to cut the grass into this pattern with their new lawnmower. Each pattern is described by specifying the height of the grass on each 1m x 1m square of the lawn.

The grass is initially 100mm high on the whole lawn.

Lo pude solucionar, ver:

https://github.com/ajlopez/TddOnTheRocks/tree/master/Lawnmover

Como siempre, la historia, prácticamente por test:

https://github.com/ajlopez/TddOnTheRocks/commits/master/Lawnmover

Pude resolver el primer “set” pequeño de problemas que me entregó Google. No pude resolver el “set” grande, porque me equivoqué de algoritmo a seguir, y no cumplí en resolverlo en 8 minutos. Mi algoritmo inicial (pueden ver los commits) resolvía el problema partiendo de los números mayores. Lo cambié para que comenzara a resolver los números menores primero, y ahí anduvo más rápido. Un tema que aprendí: algunos problemas de Google Code Jam son difíciles de probar a mano, como no tenemos los casos de uso (entrada y salida esperada), hay que trabajar con cuidado en esos temas.

Nos leemos!

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

Posted Sat, Apr 20 2013 18:42 by lopez | with no comments

TDD Kata (3): TaTeTíTomek

Anterior Post  
Siguiente Post 

El sábado pasado estuve participando del Google Code Jam. El ejercicio A fue TicTacToeTomek:

https://code.google.com/codejam/contest/2270488/dashboard

Problem

Tic-Tac-Toe-Tomek is a game played on a 4 x 4 square board. The board starts empty, except that a single 'T' symbol may appear in one of the 16 squares. There are two players: X and O. They take turns to make moves, with X starting. In each move a player puts her symbol in one of the empty squares. Player X's symbol is 'X', and player O's symbol is 'O'.

After a player's move, if there is a row, column or a diagonal containing 4 of that player's symbols, or containing 3 of her symbols and the 'T' symbol, she wins and the game ends. Otherwise the game continues with the other player's move. If all of the fields are filled with symbols and nobody won, the game ends in a draw. See the sample input for examples of various winning positions.

Given a 4 x 4 board description containing 'X', 'O', 'T' and '.' characters (where '.' represents an empty square), describing the current state of a game, determine the status of the Tic-Tac-Toe-Tomek game going on. The statuses to choose from are:

  • "X won" (the game is over, and X won)
  • "O won" (the game is over, and O won)
  • "Draw" (the game is over, and it ended in a draw)
  • "Game has not completed" (the game is not over yet)

If there are empty cells, and the game is not over, you should output "Game has not completed", even if the outcome of the game is inevitable.

Se nos da un archivo de entrada con distintas posiciones de tablero, y tenemos que producir una salida diciendo si X ganó, O ganó, empate, o todavía falta completar el juego.

Lo resolví usando TDD, y pueden ver el resultado en:

https://github.com/ajlopez/TddOnTheRocks/tree/master/TicTacToeTomek

Y la historia, prácticamente con commits por tests, en:

https://github.com/ajlopez/TddOnTheRocks/commits/master/TicTacToeTomek

Fue un ejercicio sencillo, y bien adaptado para TDD. Google me aceptó tanto la solución de un archivo de entrada pequeño, y de otro grande. Tengo que escribir sobre los otros ejercicios (B, C, D), que se complican por:

- Hay que resolver el problema en un tiempo adecuado

- El algoritmo a implementar no es evidente, o no se puede implementar “de a poco”, con “baby steps”, con lo que a veces hay grandes refactor

- A veces, dada la entrada, es difícil calcular la salida correcta, aún manualmente. Entonces, muchos de mis intentos fueron rechazados al subir el archivo solución a Google.

Nos leemos!

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

Posted Mon, Apr 15 2013 11:41 by lopez | 1 comment(s)

TDD Kata (2): Lenguaje Alienígena

Anterior Post 
Siguiente Post 

En la lista TDDev en español se mencionó hace poco el Google Code Jam. Uno de los pasados desafíos de esa competencia, es el Alien Language.

After years of study, scientists at Google Labs have discovered an alien language transmitted from a faraway planet. The alien language is very unique in that every word consists of exactly L lowercase letters. Also, there are exactly D words in this language.

Once the dictionary of all the words in the alien language was built, the next breakthrough was to discover that the aliens have been transmitting messages to Earth for the past decade. Unfortunately, these signals are weakened due to the distance between our two planets and some of the words may be misinterpreted. In order to help them decipher these messages, the scientists have asked you to devise an algorithm that will determine the number of possible interpretations for a given pattern.

A pattern consists of exactly L tokens. Each token is either a single lowercase letter (the scientists are very sure that this is the letter) or a group of unique lowercase letters surrounded by parenthesis ( and ). For example: (ab)d(dc) means the first letter is either a or b, the second letter is definitely d and the last letter is either d or c. Therefore, the pattern (ab)d(dc) can stand for either one of these 4 possibilities: add, adc, bdd, bdc.

Me gustó como problema. Vean en la página que también se pide leer un archivo de entrada con las palabras y los patrones a procesar. Se pueden bajar archivos de entrada desde la página del problema, y se debe entregar un archivo de salida para que Google nos diga si está bien. Hoy escribí una solución usando TDD:

https://github.com/ajlopez/TddOnTheRocks/tree/master/AlienLanguage

Pueden ver la historia de los commits, prácticamente por test:

https://github.com/ajlopez/TddOnTheRocks/commits/master/AlienLanguage

Una de las últimas cosas que hice fue refactorizar, para mejorar, si fuera necesario, la detección de palabras que cumplen con un patrón. Podría mejorarlo más, por ejemplo, haciendo que en vez de tener una lista de palabras, mantener un árbol de palabras con ramas por letra, como hice en SimpleBoggle.

Al final, escribí un programa de consola que acepta un archivo de entrada y produce un archivo de salida como pide Google. Me bajé un archivo grande de Google, lo procesé, y la salida obtenida lo subí a Google, para que lo revise automática. Y dió bien:

Otro triunfo de TDD ;-)

Nos leemos!

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

Posted Fri, Apr 12 2013 14:03 by lopez | 1 comment(s)

TDD Kata (1): Piedra Papel Tijera Lagarto Spock

Siguiente Post

En estos días, leí en la lista de TDDev en español una nueva kata publicada en el blog de Aprendiendo TDD:

Piedra Papel Tijera Lagarto Spock

basado en el problema publicado en

http://www.solveet.com/exercises/Kata-Piedra-Papel-Tijera-Lagarto-Spock/20

Tomé la descripción del artículo de la Wikipedia:

http://en.wikipedia.org/wiki/Rock-paper-scissors-lizard-Spock

The rules of Rock-paper-scissors-lizard-Spock are:

  • Scissors cut paper
  • Paper covers rock
  • Rock crushes lizard
  • Lizard poisons Spock
  • Spock smashes (or melts) scissors
  • Scissors decapitate lizard
  • Lizard eats paper
  • Paper disproves Spock
  • Spock vaporizes rock
  • Rock breaks scissors

Y entonces me puse a codificarla usando TDD. Pueden ver el resultado en:

https://github.com/ajlopez/TddOnTheRocks/tree/master/SpockGame

La historia, casi por tests:

https://github.com/ajlopez/TddOnTheRocks/commits/master/SpockGame

Vean el primer test/commit: todavía no compilaba. Luego, comenzó a compilar pero con estado rojo. Luego, lo pasé a verde y así.

También decidí ter dos tests por cada combinación de arriba: una que prueba que Scissors cut Paper, y otra que prueba Paper is cut by Scissors

El diseño inicial fue basado en:

- Tener una instancia de Game (la alternativa era tener la clase, sin instancia)

- Tener una enumeración para las opciones de juego (Play.Scissors, etc…)

- Tener una enumeración para el resultado (PlayResult.Tie, PlayResult.FirstPlayer…)

En vez de tener resultado de juego, podría haber puesto un método que comparara dos opciones de juego, y devolviera cuál es la que gana. Incluso hoy podría poner este método como refactorización.

Vean la última refactorización: podría haber dejado el código de implementación tal como estaba, con if para decidir cuándo gana el primer jugador:

Por esta otra forma:

sugerida por el artículo de la Wikipedia:

One way to remember the rules is to remember the standard "rock-paper-scissors" ordering, where each gesture defeats the one before it, and is defeated by the one after. But then add the two novel gestures near the word they approximately rhyme with:

  1. Rock
  2. Spock
  3. Paper
  4. Lizard
  5. Scissors

In this expanded list, each gesture is defeated by the following two options, and defeats the preceding two.

Nos leemos!

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

Posted Wed, Apr 10 2013 15:43 by lopez | 1 comment(s)

Mass Lenguaje de Programación (1) Orígenes

Siguiente Post

Durante estos días, estuve trabajando en la implementación de un lenguaje interpretado, sobre C#, llamado Mass (dedicado al bueno de @MArtinSaliaS):

https://github.com/ajlopez/Mass

La solución actual se compone de tres proyectos: una librería de clases, sus tests, y un programa de consola, mass.exe, para lanzar programas Mass

Pueden lanzar un programa escrito en un archivo hello.ms con

mass hello.ms

El clásico Hello world es entonces

println("Hello, world")

Un ejemplo con clases y objetos

class Person
	define initialize(firstname, lastname)
		self.firstname = firstname
		self.lastname = lastname
	end
	
	define getName()
		return self.lastname + ", " + self.firstname
	end
end

adam = new Person("Adam", "TheFirst")

println(adam.getName())

Un ejemplo con acceso a tipos y objectos .NET:

dirinfo = new System.IO.DirectoryInfo(".")

for fileinfo in dirinfo.GetFiles()
	println(fileinfo.Name)
end

La idea es (como en AjSharp y otras implementaciones) tener un lenguaje dinámico montado sobre un lenguaje/librería de clases. Y poder acceder a esa librería de clases desde el nuevo lenguaje. Me llevó a escribir Mass de la forma en que lo hice, el haber trabajado antes en:

- Implementar Python en C# (ver PythonSharp)

- Implementar Ruby en C# (ver RubySharp)

- El ya mencionado AjSharp (ver repo y posts)

Pero esta vez quería implementar algo que tuviera sintaxis y semántica simple. Ya estuve pensando en eso de “simple” para implementar un compilador de lenguaje simple a JavaScript ver SimpleScript

Entonces con Mass me propuse evitar:

- Múltiples comandos en la misma línea (descarté el ‘;’ de Ruby)

- Sintaxis basada en espacios en blanco, indentación (descartado Python)

- Llamadas a funciones con simplemente el nombre: se necesita explícitamente los paréntesis (descartado el Ruby clásico)

- Que las clases/valores de base (por ejemplo, enteros, strings, arreglos, etc…) tuvieran multitud de métodos (tienen los dados por la librería de clases de implementación, en este caso .NET) (descartado Ruby, que tiene casi tantos métodos nativos como PHP)

Y quise tener:

- Valores funcionales, como ciudadanos de primera clase, como en JavaScript. Vean que al tener que invocar una función con paréntesis, si o si, entonces la variable func tiene el valor funcional, y func() es la invocación explícita

- Objectos dinámicos: cada objeto puede extenderse en cualquier momento, con nuevas variables de instancia, funciones propias del objeto, como JavaScript

- Sintaxis basada en líneas: cada comando va en una línea distinta

- Sintaxis basada en palabras claves: para los comandos compuestos se usa ‘end’ para terminar un bloque

- En lo posible, una sola forma de hacer algo, en vez de múltiples maneras

- Palabras claves completas, ‘define’ en vez de ‘def’

- Clases con herencia simple (aunque la esencia de Mass bien puede expresarse sin clases, y usar librerías de clases ya escritas en .NET)

- Modificación explícita de variables fuera del alcance local (para explicar en próximos posts)

- Alcance de variables por archivo, como en JavaScript/NodeJs/CommonJS

- Módulos por archivo, con un require que permite buscar en directorios automáticamente, como en NodeJs/CommonJS

- Empaquetamiento, manejo de dependencias e instalación de esos módulos usando algo ya dado, como NPM, el manejador de paquetes de Node.js

En próximos posts, más detalles de implementación, ideas que guiaron el diseño, ejemplos. Pero ya pueden ver el código, y los ejemplos que están en los tests (sí, está todo construido paso a paso usando TDD).

Nos leemos!

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

Posted Mon, Apr 8 2013 11:43 by lopez | 1 comment(s)

Escribiendo una Aplicación usando TDD (Part 6) Modificando Vistas

Anterior Post

El post de hoy va a mostrar que, al haber usado MVC (Model-View-Controller) podemos modificar nuestras vistas, sin necesidad de tocar el código. Ni siquiera tenemos que recompilar, en muchos casos.

Primero, una novedad: he pasado el ejemplo, paso a paso, a ASP.NET MVC 4, usando Visual Studio 2010. Y también lo pasé a mi cuenta de GitHub

https://github.com/ajlopez/TddAppAspNetMvc

Vean que cada versión (cada entrega por post) está señalada por tags. La de este post es la 0.0.5. Siempre pueden ver en

https://github.com/ajlopez/TddAppAspNetMvc/commits/master

Una de las cosas nuevas que me dió esta versión de ASP.NET MVC es el soporte de Razor, ahora las vistas están escritas con Razor. Como en el anterior post, use los “wizard” de creación de vistas del propio Visual Studio, y luego las modifiqué un poco (apenas algun texto).

En el paso de este post, lo que hice fue agregar Twitter Bootstrap:

Agregué estilos y javascript que necesita Bootstrap, y armé un _viewstart.chtml que le indica a Razor que todas las vistas usan un _Layout.cshtml

Vean cómo se ve ahora la página de Subjects:

Notablemente, no toqué nada de código ni de tests. Esto muestra que hasta se puede trabajar en paralelo, o en distintos tiempos: primero se arma el código de los controladores y acciones con tests. Luego, al mismo tiempo o en algun momento, se agregan y mejoran las vistas.

Próximos posts: agregar libros, aparición de primeros servicios, modelo de negocio, etc.

Nos leemos!

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

Posted Sun, Apr 7 2013 12:33 by lopez | with no comments

Resoluciones del Nuevo Mes: Abril 2013

Un nuevo mes comienza. Paso a revisar mis resoluciones de Marzo:

- Comenzar ClojSharp [completo] ver repo
- Comenzar NodeAima [pendiente]
- Actualizar AjGenesisRuby [pendiente]
- Comenzar RubySharp [completo] ver repo
- Actualizar SimpleGo [completo] ver repo
- Actualizar SimpleChess [pendiente]
- Actualizar Inmob [completo] ver repo
- Actualizar AjConsorSite [completo] ver repo

En lguar de trabajar en AjGenesisRuby, estuve ocupado en

- Actualizar y publicar AjLispRuby como gema [completo] ver repo
- Migrar y actualizar Todocontenidos a GitHub [completo] ver repo
- Publicar versión actual de AjGenesis, y migrarlo a GitHub [completo] ver downloads, ver repo, ver post 

Adicionalmente a ClojSharp y RubySharp, escribí un nuevo lenguaje interpretado sobre C#

- Comenzar Mass [completo] ver repo

y también

- Dar una charla sobre TDD [completo] ver post

Para este Abril, se viene:

- Actualizar Mass
- Comenzar NodeAima
- Dar un curso de un día sobre Node.js
- Actualizar AjGenesis
- Actualizar AjGenesisRuby
- Actualizar SimpleGo
- Actualizar RubySharp
- Actualizar ClojSharp

Bien, más trabajo divertido y con TDD ;-)

Nos leemos!

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

Posted Wed, Apr 3 2013 11:09 by lopez | 1 comment(s)

Introducción a TDD con Visual Studio

Gracias a la gente del MUG Argentina (http://www.mug.org.ar), dí una charla de dos horas sobre cómo es TDD, con un ejemplo en Visual Studio.

Desarrollamos algunos tests, cumpliendo con el ciclo rojo, verde, refactor, sobre una Factura con Productos y Cantidades. Pueden ver el código en:

https://github.com/ajlopez/TddOnTheRocks/tree/master/Ventas

Los commits, con la evolución paso a paso, están en

https://github.com/ajlopez/TddOnTheRocks/commits/master

Mencioné algunos posts en la charla. Son mis posts sobre TDD, pero destaqué:

Escribiendo un intérprete en .NET (Parte 10) donde van a ver un caso distinto y más extenso

TDD y Diseño de Implementación (1) donde voy a escribir sobre cómo queda simple el diseño de implementación usando TDD y la cabeza

TDD como Compilador para ver cómo TDD es el compilador de estos años: nos avisa cuando algo está mal, mucho mejor que los compiladores de lenguajes tipados

TDD y Base de Datos sobre alternativas de qué hacer cuando tenemos bases de datos en nuestros tests

TDD y Baby Steps sobre ¿cómo comerse un elefante? Pedacito a pedacito

TDD y el juego del Go sobre “el sistema está en buena forma” a cada momento, listo para abrazar el cambio y los próximos casos de uso.

TDD, Test Unitarios y Mocks sobre usar mocks solamente cuando es necesario.

TDD y Casos de Uso sobre cómo ir acompañando la implementación de casos de uso con TDD. Lean el post de “Uncle Bob” No DB

Escribiendo una Aplicación usando TDD (parte 5)  sobre algunos pasos que se pueden dar con ASP.NET MVC

Para los que quieran ver cómo desarrollo partiendo de los controllers, en vez que desde el dominio de negocio, ver

Desarrollando una aplicación con TDD desde 0

donde por temas de tiempo, me salteé la evolución guiada por casos de uso. Pero ahí se ve cómo van surgiendo patrones, arquitectura, reparto de responsabilidades, pero PRIMERO LOS TESTS!

Para practicar, coleccioné algunos enlaces en:

http://delicious.com/ajlopez/tdd+codekata

Para aprender más:

https://delicious.com/ajlopez/tdd+tutorial

Para ejemplos en video:

https://delicious.com/ajlopez/tdd+video

Nos leemos!

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

Posted Wed, Mar 27 2013 11:03 by lopez | with no comments

Entrevista y Podcast

Hoy paso a comentar dos entregables que se publicaron: una entrevista, y una charla como podcast.

El año pasado, el bueno de @santiagobasulto (desarrollador de software, emprendedor, programador Python, colaborador en proyectos de código abierto) tuvo la paciencia de hacerme una entrevista en persona, acá en Buenos Aires, tomándose el trabajo de viajar desde su La Plata en un día atareado. Estuvimos charlando como dos horas (en un bar histórico de la ciudad, donde se filmó la escena del billete y el mozo, de la película “Nueve Reinas”, les dejo como trabajo para el hogar averiguar cuál es). Justamente, ese bar tiene también algo que ver con la entrevista, porque he pasado por él varias veces en las décadas que llevo de programar.

Santiago la pasó en limpio, la pueden leer en:

http://charliedontcode.com/entrevistas/2012/08/12/entrevista-angel-java-lopez.html

Algo más de contexto, lo escribí hace algo más de cuatro años:

http://msmvps.com/blogs/lopez/archive/2008/12/31/treinta-a-241-os-en-desarrollo-de-software.aspx

Visiten el blog de Santiago:

http://charliedontcode.com/

Muy buena la escena de cine de donde toma el nombre (ya me imagino a @santiagobasulto cruzándose con Robert Duvall, acá en Buenos Aires, supongo que en otro bar histórico, La Biela ;-).

Y también tuve una charla, esta vez a distancia, con los buenos @roundcrisis @dvilchez, publicada hoy como podcast:

http://www.32minutos.net/?p=106

Ah! Pusieron una foto mía, debe ser la “clásica” ;-) (no me saco muchas fotos). Tratamos temas de desarrollo de software, algo de desarrollo ágil, insistí bastante sobre el tema TDD, también sobre generación de código como sistema experto, y “ver la luz”. Y hasta apareció algo de Anglish ;-).

Vean que han producido varios podcast en:

http://www.32minutos.net/

como el de Programación Funcional con el bueno de @martinsalias, o el de Node.js con @woloski, @jfroma y @theprogrammer. Hace unas semanas grabamos otro podcast, esta vez con Martin, para 32 minutos, y se conversó bastante sobre agilidad. Veremos si queda publicado en estos días. Estén atentos.

Les agradezco a los tres haberme permitido conversar y expresar algunas ideas, que pueden servir o no.

Pero lo bueno que están haciendo, es dejar entregables consumibles. Eso es importante. Internet (y la Web en particular) está permitiendo la generación de contenido y compartirlo con todos los interesados, de una forma accesible. Pienso que es una revolución tan grande como la de Gutenberg, y los primeros libros de Manuccio.

Nos leemos!

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

Posted Sat, Mar 23 2013 11:47 by lopez | with no comments

More Posts Next page »