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
Gracias de nuevo a la gente del MUG (http://www.mug.org.ar ), en Abril voy a dar un curso de todo un día (arancelado) en Buenos Aires, ver:
http://www.mug.org.ar/Eventos/3876.aspx
Como vamos a ejecutar y practicar algún código, para aprovecharlo conviene venir con notebook. Se necesitaría tener conocimientos previos HTML y nociones de JavaScript. En la notebook propia instalar previamente: Node y Git.
El instalador de Node (para Windows y otros) está en http://nodejs.org/download/
Git se puede bajar de http://git-scm.com/
Lo que vamos a ejecutar puede usarse en Windows, Linux, Mac OS.
Lugar, horario y temas a tratar:
Jueves, 18 de Abril, 2013
Lugar: Auditorio del MUG, Rivadavia 1479, 1er Piso Oficina A. Ciudad de Buenos Aires
Horario de 09:00 a 18:00 hs.
Contenidos:
1. Introducción a Node.js
1.1. Programación Javascript desde Node sobre el motor V8
1.2. Entrada/Salida asincrónica
1.3. Módulos
1.4. Manejador de paquetes npm
1.5. Elementos de Test-Driven Development
2. Programación Web con Node.js
2.1. Módulo HTTP
2.2. Manejo asincrónico
2.3. Frameworks web con middleware
2.4. Framework MVC: Express
2.5. Acceso a Base de datos
3. Socket.IO
3.1. Comunicación con el browser
3.2. WebSockets y alternativas
3.3. Ejemplo multiusuario en tiempo real
3.4. Usando HTML5 y canvas
3.5. Chat simple
3.6. Juego simple
3.7. Ejemplo distribuido: varios servidores, varios clientes
Es un temario ambicioso. Al principio, veremos algunos temas básicos en detalle, y luego ya iremos más rápido, para tener experiencia concreta de qué aplicaciones pueden hacerse en Node.js. De ahí la inclusión de Socket.IO para soporte de tiempo real y múltiples clientes. Como no podía faltar, veremos algo de TDD, aunque algo mínimo para poder aprovechar el tiempo con el resto de los temas.
JavaScript es muy flexible, y combinado con Node.js y su gran ecosistema, es muy poderoso. Como otras veces (tres jornadas anteriores, en Cuenca (Ecuador), Buenos Aires y Rosario), el material visitado será publicado en este blog.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Cuando investigo un tema, voy anotando qué recursos he utilizado, ya sea libros, notas, enlaces, etc. Es algo que he tomado como hábito, luego de adaptar una recomendación de Clifford Stoll en su libro The Cuckoo’s Egg: llevar una libreta (notebook) con lo que se hace (algo que Stoll recibió del premio nobel Alvarez). Cuando es algo que está público en Internet, desde hace años uso mi cuenta de Delicious para ir anotando esa información:
https://delicious.com/ajlopez
Y sí, también mantengo libretas (de papel) con notas, ideas y lo que fui haciendo para resolver algo.
Cada tanto voy publicado en mi blog en inglés (o en Anglish) lo que me pareció interesante compartir. Siempre pueden entrar en:
http://ajlopez.wordpress.com/category/links
Los temas que más me han importado en estos años:
Test-Driven Development
Artificial Intelligence
Node.js
CQRS
Distributed Computing
Bioinformatics
Smalltalk
Python
COBOL
Game Development
Genetic Algorithms
Socket.IO
Express
MongoDB
y mil temas más.
Aprovecho este post de recuerdo, para agregar otros posts con links de temas que no son de desarrollo de software, pero que pueden interesar:
Teoría de Categorías
Gauss
Fermat
Topología
Teoría de Números
Teoría de Grupos
Geometría
Astronomía
Historia de las Matemáticas
Matemáticas
Cálculo
Teoría de Cuerdas
Richard Feynman
y de nuevo, mil temas más.
Tantos temas interesantes, una sola vida 
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Hace una semana moví mi proyecto de generación de código AjGenesis (la versión .NET) desde Codeplex a GitHub. El sitio de Codeplex tiene una nueva versión publicada AjGenesis 0.6 (no lo puse en GitHub porque hace un tiempo removieron de ahí la posibilidad de tener downloads de binarios). Recuerden que es un proyecto de código abierto, así que aparte de bajarse los binarios se bajan el código correspodiente. Si no conocen AjGenesis, pueden leer mis posts sobre el tema.
La nueva versión es el compilado del trunk de Codeplex. Tiene pequeñas correcciones y alguna mejora, y ha sido usado en proyectos reales. Hasta parece que lo han usado para generar código para Ruby On Rails, pero nadie del proyecto ha publicado un post todavía así que no tengo evidencia para mostrarles.
Es tiempo de pensar la próxima versión. Algunas ideas a implementar, como “roadmap” tentativo:
- Refactorizar los tests, para usar las tools de Visual Studio
- Reescribir AjGenesis Web Studio, en ASP.MVC 3, using C#, Razor, and Bootstrap 2.0
- Un nuevo programa principal de consola, renombrado a ajgen (en vez del actual, AjGenesis.Console, un nombre largo para estos tiempos ;-).
- Soporte de comandos en repositorios. Esto es (algo está implementado en la versión actual, pero es “Work in Progress”), poder usar un nombre/verbo cuando se lanza el programa principal de consola, por ejemplo:
ajgen generate <parameters>
ajgen newentity <parameters>
La forma general es
ajgen <verb> <parameters>
Los verbos estarán definidos en repositorios, y cualquiera podrá escribir nuevos comandos (en principio, serán tareas usuales de AjGenesis). De esta manera, podría soportar generación de código de una forma más fácil y extensible: en vez de especificar archivos específicos de tareas y modelos, éstos podrían ser ubicados en lugares definidos. En las versiones anteriores, yo estuve reluctante a agregar eso, búsqueda automática de tareas: preferí lo explícito a lo implícito. Pero luego de ver cómo se maneja la generación de código en frameworks como Ruby on Rails, Django, Express, me gustaría explorar esta forma.
La manera usual
ajgen <task or model files>
seguirá soportada como siempre, sin cambios. Sólo si el primer parámetro es un nombre, se lo tomará como verbo y se buscará la tarea asociada.
Algunos objetivos para más adelante:
- Soporte de JSON para escribir modelos
- AjSharp/AjBasic como lenguajes de scripting. Ahora, AjBasic está acoplado, interno al proyecto AjGenesis
Ah! Y no se olviden que hay nuevas versiones de AjGenesis: AjGenesisNode implementado en JavaScript usando Node.js, y AjGenesisRuby usando Ruby.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Anteriores posts de la serie:
Escribiendo un Intérprete en .NET (Parte 9)
Escribiendo un Intérprete en .NET (Parte 8)
Escribiendo un Intérprete en .NET (Parte 7)
Escribiendo un Intérprete en .NET (Parte 6)
Escribiendo un Intérprete en .NET (Parte 5)
Escribiendo un Intérprete en .NET (Parte 4)
Escribiendo un Intérprete en .NET (Parte 3)
Escribiendo un Intérprete en .NET (Parte 2)
Escribiendo un Intérprete en .NET (Parte 1)
Hace unos meses que no escribo en esta serie, pero es porque he directamente escrito varios intérpretes, usando TDD, y haciendo “commits” prácticamente por tests en mi cuenta de GitHub, siguiendo las ideas de esos posts.
Intérpretes que estoy escribiendo, parecidos al descripto en los posts, son:
PythonSharp (ver los commits) (lo presenté en la PyCon Argentina 2012)
RubySharp (ver los commits)
Y para un ejemplo de un lenguaje diferente, vean una implementación de Clojure que estoy escribiendo en C#:
ClojSharp
Por ejemplo, hoy escribi un nuevo verbo de ClojSharp, la que se llama “let special form”, tienen los commits por tests de hoy:
https://github.com/ajlopez/ClojSharp/commits/master
Pueden ver uno en:
https://github.com/ajlopez/ClojSharp/commit/51c678ece96d6d1cef92f36afda8d8fc711ffd8c
donde GitHub nos muestra los cambios en el código.
Otro ejemplo, lo que hice ayer, test por test, en RubySharp:
https://github.com/ajlopez/RubySharp/commits/master
Espero que estos ejemplos les sirvan para ir viendo cómo se puede usar TDD para este tipo de proyectos. Tengo más ejemplos de otros tipos de aplicaciones en mis posts de TDD.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Gracias al MUG Argentina podré dar en unos días una gratuita charla sobre TDD con Visual Studio:
Introducción a TDD con Visual Studio
Martes 26 de Marzo
Lugar: Auditorio del MUG, Rivadavia 1479 1er Piso, Buenos Aires.
Horario: 18:30 a 20:30 hs.
Describiremos brevemente lo que es y no es Test-Driven Development, pasando luego a escribir código.
Armaremos un dominio simple, usando TDD, y el ciclo de: test, rojo, verde, refactor. Veremos como entonces va “creciendo” nuestro código de manera orgánica, consiguiendo un diseño adecuado a lo que se necesita.
Los tests nos guían en la construcción del software, siendo más que tests, especificaciones, ejemplos de uso esperado del software en construcción y hasta conseguimos ser más productivos y con código mantenible, evitando la sobre-ingeniería, y arquitecturas complicadas.
Es gratuito, pero hay que registrase aquí.
Ya saben que TDD es uno de mis temas favoritos. Pero ¿por qué? Porque es la disciplina de programación que pone en marco y contexto todas las demás. Si saben SOLID, patrones y “tutti li fiocci” pero no hacen TDD, será hacer lo bueno, pero no lo correcto. Será como alinear las sillas en la cubierta del Titanic ;-)
No quiero aburrirlos más, ya escribí bastante en mis posts sobre TDD. Y cada día publico código que sigue TDD en mi cuenta de GitHub.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
En la última década, al menos tres veces me topé con esta situación: una empresa, que desarrolla software, tiene un sistema “estrella”, desarrollado digamos en los noventa, con una amplia base de clientes. Es un programa que se ejecuta en una red local, con clientes Windows. Tuvo una versión 1.x, y con su éxito, hasta una versión 2.x mejorada. Pueden imaginarse:
- Un sistema contable
- Un sistema de stock
- Un sistema de manejo de personal
- etc…
Pero quiere actualizarlo, y tener una nueva versión, acorde a los nuevos tiempos del tercer milenio.
Se necesita:
- Tener la posibilidad de brindar el servicio como “Software as a Service”, via Internet/Web
- Tener la posibilidad de tener un sistema “on premise”
- Contar con programas clientes ubicuos, desde programas desktop de una plataforma (Linux, BSD, *nix, Windows, Mac, Androir, mobile, etc…)
- Brindar lo mismo que la versión “normal”, o más
- Permitir la evolución (que no pase como con el sistema inicial de los noventa, donde todo anduvo bien, pero que quedó en el tiempo, sin soporte de tecnología, herramientas, etc..)
- Se está en libertad de elegir la tecnología, el equipo y el proceso de desarrollo.
¿Cómo atacar esta construcción de la versión 3.x?
Bien, esta es la presentación del problema. Comentaré algunas soluciones, caminos a explorar en los próximos posts.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Sirva el post de hoy como introducción a un gran tema, que seguramente no podré comentar completamente. Es el tema de la relación entre TDD (Test-Driven Development) y diseño de implementación (no de interfaz o experiencia de usuario, digamos, diseño del código y su arquitectura).
Comienzo con una pregunta:
¿Qué esperamos de un sistema o aplicación?
Lo primero que se me ocurre, es que funcione bien. Imaginemos que estamos usando un procesador de texto, y cuando guardamos el documento se graba nada más que la mitad y lo demás se pierde. No será lo que esperamos. A esta altura de la historia del software, esperamos que una aplicación funcione bien, sin ese tipo de problemas. Yendo más específico, debería:
- Brindar la salida esperada, ante una entrada esperada
- Reaccionar de forma adecuada, ante una entrada no esperada
- Reaccionar de forma adecuada ante una falla en el entorno (por ejemplo, pérdida de conexión con la base de datos)
Seguramente se les ocurriran más puntos de este estilo.
Ahora bien, me puedo imaginar una aplicación así, y que no esté bien diseñada. Muchos de nosotros recordamos (y aún puede ser que tengamos) aplicaciones Visual Fox, o Visual Basic clásico, donde todo está escrito en el botón de aceptar. Conozco aplicaciones así, que funcionan según lo esperado. Y los clientes y usuarios están contentos.
Pero muéstrenme un ejemplo de una aplicación exitosa así, y casi seguro que los creadores de ese sistema tuvieron que lidiar bastante en sacar nuevas versiones, y todavía están viendo cómo migrarlas a la web y dispositivos móviles, impulsados por lo que la gente y el mercado espera hoy.
Entonces ¿qué esperamos de un buen diseño de implementación? No sé ustedes, pero yo espero que el diseño de implementación (el código, su funcionalidad interna, su distribución, su arquitectura) sea simple. ¿Por qué? Porque es la cualidad más importante para conseguir que sea mantenible.
Si un sistema exitoso no necesitara cambios, no buscaríamos mantenibilidad. Pero si un sistema es exitoso, casi seguro que sobrevivirá en el tiempo, y como la realidad cambia, habrá que actualizarlo. Un contraejemplo: si conseguimos escribir un sistema que nos dé el número ganador de la próxima gran lotería en EE.UU. y de sólo esa lotería, con un grandísimo premio, el cliente final no se va a preocupar por la mantenibilidad o nos va a pedir actualizaciones. Pero en general, los sistemas y aplicaciones exitosos necesitan evolucionar.
Por supuesto, podemos conseguir sistemas y aplicaciones exitosos programando sin buen diseño, por ejemplo, para llegar primeros a un mercado. Algunas de las aplicaciones Visual Fox que mencionaba antes, al salir rápidamente, consiguieron que la empresa creadora pudiera llegar primero a un nicho de mercado, y eso fue más importante que el tener un buen diseño desde el comienzo. Luego, se pudo pagar la deuda técnica en la versión 2.x con todo el ingreso y el posicionamiento que se consiguión en la versión 1.x.
Entonces, volviendo a la mantenibilidad, ¿por qué pido que la implementación sea simple? Porque será entonces
- más entendible para quien quiera que venga (individuo o equipo) a escribir la versión 2.0
- tendrá menos piezas, y cada modificación se podrá encarar tocando pocas de esas piezas a la vez
Por añadidura, una aplicación internamente simple, se verá expuesta a menos fallas de las piezas (en general) por tener menos puntos de posibles problemas en ejecución. No es lo mismo tener una aplicación que actualice una sola base de datos, que otra que tenga que actualizar 10 bases de datos distribuidas y heterogéneas.
Hay quien pedirá: no, yo no quiero que el diseño sea simple, sino flexible. Acá llegamos a un punto crucial, para lo que quiero tratar y todavía no apareció: desarrollar con TDD.
Bien, bastante por hoy, veré de escribir en próximos posts:
- Lo simple vs lo flexible
- Cómo TDD promueve lo simple
- Cómo TDD nos ayuda a conseguir lo “flexible” por añadidura y sin gran esfuerzo
- Cómo TDD nos da una mano para conseguir lo primero que mencioné: que la aplicación funcione como esperamos
- Cómo un buen diseñador puede diseñar “mejor” con TDD, y además cómo eso beneficia a quien quiera que venga a mantener el sistema
Vean que pongo “TDD promueve”, “TDD nos ayuda”, porque TDD solo no hace nada. Hay que poner cabeza. Pero desde hace unos años veo que TDD + Cabeza, nos da un sistema mejor que sólo aplicar Cabeza, es decir, sólo con nuestros conocimientos y destrezas.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Esta semana viene movida en el tema de reuniones para programadores. En primer lugar, la gente de Ruby Argentina vuelve al ruedo luego de un merecido descanso de verano, y luego de la Ruby Conf 2012. Como se habían planteado desde el año pasado, hacen un meetup el primer miércoles de cada mes. Se anunció la lista RubySur:
https://groups.google.com/group/rubysur/browse_thread/thread/2c27490fc752a41b#
vamos a hacer el primer meetup de 2013 en las oficinas de SCV Soft.
Para participar, les pedimos que completen el siguiente formulario: http://goo.gl/jOoIv
Quienes quieran proponer una charla, pueden hacerlo mediante el mismo formulario.
Cuando?
Miércoles 6 de marzo de 2013 a las 19:00 hs.
Donde?
Oficinas de SCV Soft
Nicolás Repetto 1841, Ciudad Aut. de Buenos Aires
(mapa: http://goo.gl/maps/EiZT4)
Para conocer la lista de personas anotadas: http://goo.gl/nN1Rr
Por otro lado, el mismo día (!) la gente de Python Argentina PyAr se reúne:
http://python.org.ar/pyar/Eventos/Reuniones/2013/Reunion59
http://listas.python.org.ar/pipermail/pyar/2013-March/023406.html
Reunión 59 - Miércoles 6 de Marzo de 2013 - Buenos Aires, Post Street Bar - 19hs
Temario
-
PyCon 2013
-
PyCamp 2013
-
Manejo de dinero en PyAr
- Mentores de charlas
- Raspberry Pi
-
Sitio de PyAr
- Capacitación introductoria a python
- ¿...?
Fecha y Hora
- Miércoles 6 de Marzo de 2013, 19 hs
Lugar
Post Street Bar, en la terraza
Y para el viernes tenemos la frutilla de la torta, Node.js sobre Raspberry Pi, por la gente de Node.js Argentina:
http://www.meetup.com/NodeJS-Argentina/events/105375852/
Usando Node.js y MongoDB en RaspBerryPI
La idea es instalar Node.js y MongoDB (en cluster) en varias Raspberry Pi.
Bueno, tenemos de todo esta semana. Tendría que comentar también sobre una meetup a la que asistí, de desarrolladores y usuarios de Salesforce, en Buenos Aires. Pero queda para otro posts.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Primero, una revisión de las de Febrero:
- Comenzar SimpleDatabase [completo] ver repo
- Actualizar SimplePermissions [pendiente] ver repo un ejemplo de roles, sujetos, permisos con modelo en memoria
- Actualizar SimpleStorm (implements ack, maybe integrate with MultiNodes) [pendiente] ver repo por ahora el proyecto con más estrellas en mi GitHub
- Actualizar SimpleMapReduce [completo] ver repo
- Actualizar SimpleKeeper, con líder [completo] ver repo falta ejemplo distribuido
- Actualizar AjFabriqNode, integrarlo con el nuevo SimpleMessages, posiblemente agregarle MultiNodes [pendiente] ver repo
- Actualizar MultiNodes [completo] ver repo
- Actualizar AjGenesisNode, para tener un comando global y tareas [pendiente] ver repo me gustaría actualizarlo
- Dar un curso de un todo un día sobre Node.js [completo] ver post
Adicionalmente, estuve trabajando en:
- Update Inmob [completo] ver repo
- Update AjConsorSite [completo] ver repo
- Update AjGroupsJs [completo] ver repo
- Update SimpleBoard [completo] ver repo
- Update SimpleChess [completo] ver repo
- Update SimpleGo [completo] ver repo
- Update NodeSamples [completo] ver repo
Mis resoluciones para este Marzo:
- Comenzar ClojSharp
- Comenzar NodeAima
- Actualizar AjGenesisRb (¿podré hacerlo una gema?)
- Comenzar RubySharp
- Actualizar SimpleGo
- Actualizar SimpleChess
- Actualizar Inmob
- Actualizar AjConsorSite
Más trabajo, pero también diversión ;-)
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Gracias a la organización del Microsoft User Group de Argentina, y al apoyo en el lugar del bueno de @mcomparetto, pude dar un curso de un día en Rosario, Santa Fé, acá en Argentina. Quisiera enumerar rápidamente el material que usamos.
En primer lugar, la presentación la pueden ver en https://skydrive.live.com/redir?resid=9F903F3D6DB0C176!5904
Nos descargamos Node.js desde http://nodejs.org/
No lo usamos mucho, pero si quieren pueden usar el Git que se baja desde https://github.com/ajlopez/NodeSamples
Los ejemplos que usamos al principio estan en mi GitHub:
https://github.com/ajlopez/NodeSamples
Vimos de ahí los del subdirectorio Simple, desde un Hello World, un servidor Web, hasta un simple chat con Socket.io, como ir viendo en qué es bueno Node.js.
Discutimos cómo hacer un módulo, cómo usar algo de TDD. No fue “full TDD”, pero el ejemplo quedó en https://github.com/ajlopez/NodeSamples/tree/master/TDD.
Fue muy importante el ver el uso de require. Ahí apareció el manejador de paquetes NPM. Vimos cómo es un archivo package.json, cómo sirve para instalar las dependencias, dónde se buscan los módulos cuando se hace require, cómo se emplea “npm test”, cómo se puede publicar un módulo.
Para ver cómo se puede hacer un web server y sitio “a mano”, de los ejemplos de arriba vimos el directorio MathWizard, donde vimos cómo se puede implementar un cálculo en forma asincrónica. El tema de asincronía con callbacks fue algo que traté de repetir durante todo el curso, para que quede claro cuál es el precio a pagar para programar en Node.js.
Luego de ver cómo es armar un sitio a mano, discutimos el middleware de Connect, y luego Express. Ver:
http://expressjs.com/
Mostré cómo armar nuestro primer sitio web Express desde la línea de comando (ver la presentación). Quedó en https://github.com/ajlopez/NodeSamples/tree/master/Express/MyApp
Para pasar a un sitio con base de datos, instalamos MongoDb, ver http://www.mongodb.org/. Vimos el ejemplo de https://github.com/ajlopez/NodeSamples/tree/master/Express/Blog basado en el ejemplo original de http://howtonode.org/express-mongodb
Levantamos entonces el ejemplo https://github.com/ccoenraets/nodecellar ver los posts:
http://coenraets.org/blog/2012/10/nodecellar-sample-application-with-backbone-js-twitter-bootstrap-node-js-express-and-mongodb/
http://coenraets.org/blog/2012/10/real-time-web-analytics-with-node-js-and-socket-io/
http://coenraets.org/blog/2012/10/creating-a-rest-api-using-node-js-express-and-mongodb/
Pasamos a ver Socket.io http://socket.io/ Usamos los ejemplos
https://github.com/ajlopez/NodeSamples/tree/master/SocketIO
https://github.com/ajlopez/NodeSamples/tree/master/SocketIO/Canvas
https://github.com/ajlopez/NodeSamples/tree/master/SocketIO/TicTacToe
y los ejemplos distribuidos de algoritmos genéticos de:
https://github.com/ajlopez/SimpleGA
https://github.com/ajlopez/SimpleGA/tree/master/samples
Finalmente, volvimos al nodecellar y lo modificamos para poder tener un “dashboard” de visitas en tiempo real, usando Socket.IO.
No se puede ver todo Node.js en un día, pero espero que las primeras horas hayan servido para tener una idea de cuáles son los primeros pasos, y que la segunda parte, a la tarde, haya servido entonces para tener un panorama rápido de cosas que se pueden hacer en tiempo real, que podrían ser complejas de implementar en otras tecnologías.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Veamos hoy un tema que pone en perspectiva ¿para qué sirve TDD? O por lo menos, trata de responder en gran parte esa pregunta.
Todos conocemos lo que es programar en Java o en .NET. Escribimos el programa, posiblemente usando una IDE (Eclipse, Visual Studio.NET), y llegado el momento, compilamos. Los lenguajes .NET (VB.NET, C#, otros) y Java, son lenguajes tipados. El compilador nos dice cuándo nos equivocamos, ANTES de ejecutar nuestro programa. Por ejemplo, nos dice que nos equivocamos en el nombre de un método, o que escribimos mal el nombre de una clase, o que está mal el tipo del parámetro que tenemos que pasar a una función.
Eso ha sido útil por décadas. Y entonces, es fácil confundir esa solución (detectar en compilación errores), con el problema inicial (que nuestra aplicación funcione como esperamos).
Cuando pasamos a lenguajes dinámicos, como Ruby o Python o JavaScript, algunos se resienten: hey! No tenemos compilador! No podemos asegurarnos que lo que escribimos esté bien. Sólo nos damos cuenta si lo ejecutamos. Esto parece inclinar la balanza de nuestras preferencias a los lenguajes tipados con compilación.
Pero no es así. Todos los compiladores del mundo NO PUEDEN ASEGURARNOS que lo que escribimos esté bien. No pueden asegurarnos, al compilar, QUE NUESTRO SOFTWARE HAGA LO QUE ESPERAMOS QUE HAGA.
Veamos un ejemplo en concreto. Si tenemos un método llamado “incrementar” que recibe un entero, un compilador de Java o de .NET nos va a avisar sin lo llamamos con un nombre incorrecto, o si le estamos pasando un valor real o texto en lugar de un entero. Y eso es útil. PERO NO NOS AVISA NADA sobre si el método “incrementar” cumple con lo que esperamos de él. Bien podríamos tener en ese método código que en vez de incrementar una variable interna se dedica a formatear el disco C: o a borrar todo lo que tengamos en /usr/bin. EL COMPILADOR NO NOS SIRVE para afirmar que el método hace lo que esperamos que haga.
En cambio, TDD, al escribir los tests de lo que esperamos de nuestro método “incrementar” NOS AVISA cuándo las expectativas que tenemos no se cumplen. Entonces, no hay mucha diferencia entre escribir Ruby sin compilar y sin TDD y escribir C# sin compilar y sin TDD: de las dos formas, no sabemos si lo que escribimos HACE LO QUE ESPERAMOS QUE HAGA.
Es por todo eso que veo a TDD como la próxima generación de compiladores: es lo que nos asegura que lo que escribimos esté bien, NO EN SINTAXIS, sino en lo que podemos nombrar como SEMANTICA: lo que escribimos cumple con la conducta esperada.
Accesorio: por eso no tomo tanto en cuenta a los que critican a Ruby, Python o JavaScript por no ser tipados y no poder detectar errores en “compilación”. Si escribimos siguiendo TDD, no importa tanto el lenguaje que usemos: cada línea de código que agregamos está respaldada por un test, y cada test es una condición que cumplir. Cuando TDD nos avise que un test está en rojo, es como cuando el compilador nos avisa “el método inkrementar no existe”. Es más: yo diría que nos das avisos más importantes que lo que nos da cualquier compilador.
Escribir código de producción sin TDD, es como escribir un programa ejecutable, usando un editor hexadecimal sobre el archivo compilado: nada nos asegura que lo que estamos haciendo esté bien. Si quieren escribir código de producción sin TDD, bien, tengo unos folletos para jugar ruleta rusa, si les interesa ;-)
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Ya he escrito bastante en mis anteriores posts, sobre cuánto uso modelos en memoria al desarrollar un sistema. Pero ¿qué pasa cuando tenemos una base de datos? Ya sea porque llegamos al punto de necesitar usarla, o porque la base de datos ya está desde el principio del desarrollo.
Lo que he encontrado que me ha servido en esos casos es tener los tests de TDD como siempre, pero el modelo con persistencia en una base de datos local, del desarrollador. En el repositorio común al equipo debería estar claros los pasos para instalar esa base de datos (por ejemplo, un script de creación e inserción de datos iniciales). Puede que esa misma base de datos la usemos localmente para hacer pruebas manuales y demostraciones. Pero la cuestión es que los tests de TDD debería poder ejecutarse en cualquier momento, una vez o varias veces, sin verse afectado por la base de datos. Entonces, hay varias soluciones (que se pueden combinar):
- Un comando de línea que ponga a la base de datos de TDD en un estado conocido, la “well-known database”
- Tener una base de datos para TDD y otra, también local, para las demostraciones
- En los tests, una vez, al principio, tener una tarea que ponga a la base de datos de TDD en un estado conocido
- Cada test, envolverlo en una transacción y nunca hacer el commit
Con esto, se reduce la fricción de correr los tests locales.
En un servidor de integración continua, seguramente se creará la base y se cargará con los datos iniciales antes de correr los tests (de TDD u otros)
Yendo un poco más en detalle. Supongamos que nuestro sistema debe calcular la retención del impuesto a las ganancias cuando hay que pagar a un proveedor. En Argentina, puede que las reglas sean algo complejas para calcular. No sé el estado actual del tema, pero en su tiempo podía depender del servicio dado por el proveedor, de si el servicio abarcaba varias provincias (por ejemplo, un flete que comenzaba en una provincia y terminaba en otra), de lo que nos había facturado en el último mes, de si el proveedor tenía domicilio en una zona de promoción industrial o no, etc. Sea así o no ahora, me sirve como idea de base.
¿Cómo se encararía programar eso con TDD, y base de datos?
Como siempre, paso a paso, “baby steps”. Seguramente atacaríamos primero algunos casos sencillos y luego otros casos más complicados. Cuando se llegue a estos casos (por ejemplo el proveedor con promoción industrial) ponemos en la base de datos bien conocida, un proveedor X que cumpla con lo que necesitamos para el test que estamos desarrollando. Es decir, a medida que resolvemos los test, va quedando en la base (en scripts de creación con datos iniciales) los escenarios que vamos necesitando. Probablemente, un test solamente necesite crear al proveedor (en la etapa de Arrange). Si lo necesitamos a ese proveedor para varios tests, habrá refactor del test para que haya una rutina que lo cree. Pero cuando ya lo necesitamos para varias situaciones, migrará su existencia directamente a la base de datos bien conocida.
Cada desarrollador del equipo, cuando traer el último código del repositorio, podrá ver si alguien modificó los scripts de creación de la base. Y aún si no se da cuenta, al ejecutar los tests de TDD, seguramente alguno quedará en rojo, adviertiendo que algo de base ha cambiado. Toda esta forma de trabajo también sirve cuando en el desarrollo se va cambiando la estructura de la base. Y les sirve para no tener que adoptar mi consejo de modelo en memoria, si aún no se animan a esa forma de trabajo.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Es tiempo de escribir un post explicando mi interés personal en algunos temas, como lenguajes de programación, mensajería, computación distribuida e inteligencia artificial. Soy varios temas, espero poder transmitir algunas ideas sobre ellos.
Muchos de nosotros estamos interesados en esos temas. Son interesantes por sí mismos, y estudiarlos y explorarlos es divertido e interesante. Como desarrolladores de software, nos gusta jugar con ellos: escribir un nuevo lenguaje de programación, implementar uno existente, armar aplicaciones distribuidas, etc.
Pero en mi caso, hay algo más, una base común a todos estos temas. Por ejemplo, tomemos los lenguajes de programación. Los actuales lenguajes pueden ser extendidos para soportar, con menos fricción, la serialización de objetos simples (sin conducta, simples mensajes) para usarlos en aplicaciones distribuidas. Hay dos formas de hacerlo, en principio: extender los lenguajes con nueva sintaxis para soportar la distribución del trabajo, o agregando nuevas librerías. Ver como ejemplo Scala o Akka. Así que, para tener un mejor entendimiento de lo que se necesita, escribí mis propios proyectos personales: mi lenguaje interpretado (AjSharp), extención de Smalltalk (AjTalk) para ejecutar objetos distribuidos, escribir agentes y demos de actores (AjAgents, y agentes en AjSharp), mensajes distribuidos (en AjFabriq) y en los últimos tiempos, explorando JavaScript con Node.js (SimpleMessages, SimpleQueue, MultiNodes, SimpleRemote, SimpleActors… ), todo esto para tener las piezas necesarias para escribir y ejecutar aplicaciones distribuidas. Claro que hay multitud de proyectos ya existentes que podría usar. Pero escribir mis propias implementaciones me entrena, me hace practicar y obtener un mejor entendimiendo de los problemas y soluciones a implementar. De paso, es muy divertido :-)
Pero ¿por qué computación distribuida? Estoy convencido que es el camino a explorar para implementar una nueva clase de aplicaciones. Fundamentalmente, aplicaciones que resuelvan problemas complicados, que puedan ser abordados usando computación en paralelo y escalabilidad horizontal. No solamente para procesamiento de Big Data. Hay vida más allá de analizar tweets en tiempo real. La idea es abordar problemas de inteligencia artificial, usando computación distribuida y hardware existente.
Esta es, entonces, el gran fondo de mi escenario de desarrollo: lenguajes de programación fexibles; mensajería para soportar programación distribuida; y aplicaciones distribuidas para la siguiente generacièn de problemas a resolver.
Sí, la próxima frontera. Donde jamás hemos llegado ;-)
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Es tiempo de revisar mis resoluciones de Enero:
- Empezar SimpleScript [completo] ver repo
- Empezar SimpleBoard [completo] ver repo
- Empezar SimpleChess [completo] ver repo
- Empezar SimpleGo [completo] ver repo
- Empezar y publicar una versión de SimpleMapReduce, con ejemplo local y distribuido [parcial] ver repo (hay ejemplo local, y un incipiente ejemplo distribuido)
- Empezar y publicar una versión de SimpleFunc, serialización de funciones en objetos [completo] ver repo
- Empezar Memolap, una librería tipo OLAP multidimensional en memoria, escrita en C#, con ejemplo [parcial] ver repo (el ejemplo es Work in Progress)
- Empezar SimpleMemolap, lo mismo que Memolap, pero en JavaScript/Node.js, con ejemplo [completo] ver repo
- Empezar SimpleRules, un motor de reglas con encadenamiento hacia adelante, que compila a JavaScript [completo] ver repo
Adicionalmente estuve trabajando en:
- Actualizar AjConsorSite [completo] ver repo
- Actualizar Inmob [completo] ver repo
- Empezar SimpleKeeper, un servidor tipo Zookeeper [completo] ver repo
- Actualizar y publicar la primera versión de MultiNodes [completo] ver repo
- Actualizar SimpleStorm, publicar nueva versión que usa SimpleQueue 0.0.2 [completo] ver repo
- Actualizar SimpleQueue publicar nueva versión [completo] ver repo
- Actualizar SimpleRemote publicar nueva versión usando SimpleMessages SimpleMessages 0.0.3, y métodos asincrónicos [completo] ver repo
- Publicar la primera versión de AjFabriqNode [completo] ver repo
- Empezar y publicar la primera versión de NodeDelicious [completo] ver repo
- Refactorear SimpleBroadcast para que use SimpleMessages 0.0.3 [completo] ver repo
- Publicar nueva versión SimpleMessages 0.0.3 [completo] ver repo
- Empezar y publicar primera versión de MProc, una capa de encadenamiento de middleware de proceso de mensajes en Node.js, [completo] ver repo
- Empezar y publicar primera versión SimpleTags, motor para manjear items con datos arbitrarios asociados a tags [completo] ver repo
- Empezar y publicar primera versión ObjectStream, stream de objetos, unidireccional y bidireccional, para Node.js [completo] ver repo
- Empezar y publicar primera versión de SimplePipes, otra librería de flujo de datos en Node.js [completo] ver repo
- Empezar y publicar la primera versión de SimpleSudoku, resuelve sudoku en JavaScript/Node.js [completo] ver repo
- Empezar y publicar la primera versión de SimplePermissions, permisos por Sujeto, Rol, Contexto, con modelo en memoria [completo] ver repo
- Empezar y publicar primera versión de SimpleGlobals, inspirado por Mumps Globals [completo] ver repo
- Empezar y publicar la primera versión de SimpleInvoke, invocación encadenada de funciones con callbacks, para JavaScript/NodeJs [completo] ver repo
Para este nuevo mes, me propongo:
- Empezar SimpleDatabase
- Actualizar SimplePermissions
- Actualizar SimpleStorm (implementar ack, puede que integrarlo con MultiNodes)
- Actualizar SimpleMapReduce
- Actualizar SimpleKeeper, agregar nodo líder, ejemplo distribuido
- Actualizar AjFabriqNode, para que use el nuevo SimpleMessages, quizás integrarlo con MultiNodes
- Actualizar MultiNodes
- Actualizar AjGenesisNode, para que use comandos globales y tareas
También voy a dar un seminario de todo un día sobre Node.js en Rosario, Argentina
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Ya saben que TDD (Test-Driven Development) es uno de mis temas favoritos. Y no sólo porque me gusta, sino porque creo que es uno de los temas a difundir para mejorar la calidad de nuestro trabajo, tanto en el código entregado como en la calidad de vida de nuestro día laboral. Soy un convencido de que el código de producción escrito SIN TDD debería estar prohibido, directamente. Y si insisto con el tema, es porque no veo que se aplique y entienda TDD, por lo menos en estos lares, Buenos Aires y Argentina. Por ejemplo, escucho por ahí:
- “TDD es más lento”, no lo veo así, es un caso de “vísteme despacio que estoy apurado”.
- “TDD no es para los programadores junior”, no, cuanto más inexperto es el programador, más va a aprender y mejorar haciendo TDD y usando el cerebro, claro ;-) TDD no produce mejores programadores, pero los hace pensar en lo que están haciendo.
- “TDD es hacer test y code coverage”, por favor, no me presenten a una persona que piense así. O que piense que TDD es aprender a hacer test unitarios, sea lo que sea que “unitario” signifique.
- “TDD es aburrido”, para mí es como un juego, cada test en verde es como superar un nivel de juego.
Una de las actividades que me nacen naturalmente cuando hago TDD, es que lo que escribo va creciendo de a poco, de a “baby steps”, de a pasos de bebé. En vez de hacer un gran salto en la implementación, si uno realmente programa con TDD va agregando poco código en cada test que se agrega. Y no se agrega código que no nazca, que no tenga una traza que lo remita a la necesidad de un test. Esto consiga que el software que vamos creando, crezca como si fuera un organismo vivo, desarrollándose de a poco. Esto trae varias consecuencias:
- Cada código agregado tiene su función específica: hacer que un test pase a verde
- No aparece código “por las dudas” o por casos de uso todavía no implementados.
- No pensamos “por adelantado”, poniendo código que todavía no necesitamos (evitamos romper YAGNI).
- No se adopta tecnología o soluciones (librerías, frameworks, base de datos, etc… ) hasta el momento en el que REALMENTE se necesitan.
Y algo menos evidente:
- El código que vamos armando es pasible de refactorización en cualquier momento
- Y aún puede haber más que refactorización, sino también cambiar algo de nuestro diseño, sin grandes “dolores”
Ahora les advierto: no se puede aplicar todo esto con TDD, si parte del código QUE ESCRIBIMOS NOSOTROS no lo hacemos con TDD. Porque entonces vamos a "sufrir" cuando lleguemos un día a necesitar refactorizar, o rediseñar, y entonces la parte del código que habíamos escrito SIN TDD nos va a pesar y nos va a complicar ese paso de refactor o de rediseño.
Me gustaría mostrarles un ejemplo, pueden ver los posts y series:
TDD Paso a Paso
Escribiendo una aplicación con TDD
Escribiendo un Intérprete en .NET
VAN en Alt.NET Hispano: Desarrollando una Aplicación con TDD
con video en Desarrollando una aplicación con TDD desde cero con código en https://github.com/ajlopez/TddOnTheRocks/tree/master/TddApp
y mis posts de TDD.
Pero cada día, en mi cuenta de GitHub, voy haciendo commits por test, así que pueden entrar a algún proyecto y ver cómo va evolucionando. Por ejemplo, hoy voy a empezar a codificar SimpleKeeper (una especie de ZooKeeper pero en Node.js). Pueden en cualquier momento entrar a ver la lista de commits e ir revisando si cumplo o no cumplo con TDD y “baby steps”.
Algo muy interesante, y relacionado con este post, es:
Kent Beck’s Four Hats
Controlling the size of your checkout is a valuable coding skill. You should be able to take small, baby steps, and check-in at any time. There are a number of benefits. If you check-in frequently the merge to source control becomes trivial. Your colleagues won’t get annoyed, because that change which they need is never far away. Most importantly you are in control of your work.
Vean ahí los cuatro sombreros de Kent Beck.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Hace más de una década, escribí un sitio que sirvió luego de base para mi sitio personal. Estaba basado en tener items heterogéneos (enlaces, páginas tipo wiki, etc…) clasificados en categorías. Las categorías se disponían en árbol, y se soportaba el concepto de enlace simbólico: una rama de una categoría podía ser un puntero a otro rama del árbol (como cuando tienen enlaces simbólicos en la jerarquía de directorios de un sistema de archivos). Un item se podía colocar en más de una categoría. Pero después de conocer a Delicious y al tiempo a Gmail, ahora prefiero organizar los items usando tags (en Gmail son las “labels”). Y en vez de tener categorías y un árbol de categorías, pienso que es más flexible tener conjuntos basados en predicados de tags. Por ejemplo, lo que sería en mi viejo sitio la categoría Programming –> C#, sería ahora todos los items con tags “programming”, “c#”. Algunas veces, necesitaría en vez de simples tags, un par key-value, como “author:unclebob”, o “project:storm”.
Así que hace unos días, puse manos a la obra, y comencé un nuevo proyecto, escrito en JavaScript/Node.js, llamado SimpleTags:
https://github.com/ajlopez/SimpleTags
Leo en el README.md:
var itemId = engine.createItem('http://nodejs.org', [ 'nodejs', 'javascript', 'engine', 'programming' ]);
…
An item has
data: Arbitrary value you supplied
tags: An array of tags. A tag could be a non-empty string or an object with only one property with non-empty value.
Once created, the item has an associated id, supplied by the engine.
…
El proyecto tiene un modelo en memoria. Un conjunto de tags puede ser asociado a un item de datos arbitrario. Ese item podría ser los datos de un proveedor o factura, pero seguramente sería más usual tener como dato asociado el id del proveedor o la factura, y que otro sistema se ocupe de recuperar la entidad. Entonces, el dato arbitrario puede ser un id para una tabla en nuestra base de datos, o una URL, o lo que querramos y necesitemos. Lo importante es: asociar un dato arbitrario con un conjunto de tags, y recuperar items con predicados sencillos de esos tags.
Piensen como ejemplo: podemos tener una gran colección de enlaces, y usar SimpleTags para organizarlos. O documentos, fotos, multimedia. Podemos usar los tags en diferentes entornos. Es una idea poderosa y simple que se puede aplciar en varios dominios y escenarios.
Pienso agrega un sitio web como ejemplo concreto, donde se pueda agregar URLs y asociarles tags, y luego definir categorías o conjuntos, usando predicados. Luego de ese ejemplo general, podría implementar algo más concreto, como una lista de cosas para hacer, con tags, o una lista de tareas pendientes/completas por proyecto, iteración, estado, persona asignada, etc… Usé hace un tiempo un sitio así en un cliente para llevar el estado de los proyectos, y me resultó muy útil y flexible.
Podría ser una excusa para aprender más de Express, o para hacer “dog fooding” y consumir mi proyecto web SimpleWeb. En todo caso, me divierto como loco :-)
Como es usual, escribí SimpleTags usando TDD, pueden consultar el log de commits.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Hace unos años tuve la suerte y el agrado de conocer personalmente a Fernando Aguilar, uno de los mejores jugadores de Go, de Argentina y de Occidente. Pueden leer:
Fernando Aguilar y el Go
Sobre el juego del Go, ver mis posts y links:
http://ajlopez.zoomblog.com/cat/15644
http://delicious.com/ajlopez/go+baduk
Si leen mis posts, ya saben que me interesa la aplicación de la Inteligencia Artificial al juego del Go, ver:
Computer Go y el programa AjGo
AjGo: Hacia un programa que juege al Go
(Nota curiosa: AjGo fue reescrito en 2008 aplicando TDD en cada paso, pueden ver el repo. También pueden vigilar SimpleGo para ir viendo como voy a ir aplicando TDD completo, esta vez en JavaScript).
Pero volvamos al tema. Cuando estuve en la charla de Fernando, le pregunté: cómo piensa la próxima jugada. Quería aprender para poder aplicarlo a mis programas. El go tiene muchas más variantes en cada ply que el ajedrez, y tiene características sutiles, como que una jugada hecha un lugar puede tener grandes efectos en otro lado del tablero. Esto ha impedido que haya programas de go que sean tan avanzados como los que encontramos en ajedrez. Lo que recuerdo de la respuesta:
En determinado momento [cerca de la apertura] no pensé hacia adelante, no me interesó calcular jugadas. Miré el tablero y me dije: Estoy bien. Cualquier cosa que haga el adversario, yo voy a poder contestarle. No tengo debilidades. El futuro no me asusta.
Siempre me quedó esa respuesta (atención, puesta con mis palabras, no tengo las notas que tomé en su momento). También se puede aplicar al ajedrez. No es que no hay situaciones tácticas en go, donde el cálculo de un árbol de jugadas es importante. Pero no se da tanto en la mayoría de los juegos y situaciones, solo por momentos. De ahí que el “approach” Big Blue (atacar con fuerza bruta un gran árbol de búsqueda, con alguna heurística de dónde para en la exploración y evaluaciones parciales) no sea tan aplicable en el caso del go. Hay que trabajar más en buenos algoritmos evaluadores de posiciones estáticas, que me digan “estoy bien”.
Lo mismo nos da TDD, armado con casos de usos, y evitando romper YAGNI. Cualquier cambio que venga (recuerden que en lo ágil abrazamos el cambio, no “luchamos” contra él), cualquier cambio en los requerimientos, cualquier caso de uso nuevo, cuando hago TDD veo que puedo enfrentarlo cuando llegue el caso. No hace falta “pensar jugadas hacia adelante”. Cuando tengo un proyecto armado usando TDD, lo que se va creando crece orgánicamente, sin debilidades grandes. Si alguna vez tenemos que refactorizar en grande, TDD nos da la red de seguridad para enfrentar el cambio con coraje. El aplicar “baby steps” permite que nuestro sistema crezca como un organismo: de a poco. No será un “monstruo” que tenga dos cabezas, o un brazo más grande que otro. Y hasta agregaría que no tendrá cosas insertadas “porque las vamos a necesitar”. No, sólo tendrá lo que habremos necesitado hasta ese punto. Y nuestro código estará preparado para soportar cambios que vengan (que siempre vienen).
Eso nos va a ir dando un sistema que, a cada paso, no tiene mochilas al hombro. Vamos a “estar bien”, y ningún artefacto nos “va a pesar” o nos va a generar fricción. Estaremos en una posición tal como la de Fernando. El sistema y nuestro equipo podrá decir “Estoy bien. No tengo debilidades. El futuro no me asusta” :-)
Bueno, apenas relacionado, pero los otros días veía Enter the Dragon, (1973), la última película de Bruce Lee. Antes de olvidarlo, lo comparto con Uds:
A good fight should be like a small play, but played seriously. A good martial artist does not become tense, but ready. Not thinking, yet not dreaming. Ready for whatever may come. When the opponent expands, I contract. When he contracts, I expand. And when there is an opportunity, I do not hit. It hits all by itself.
Ready for whatever may come.
Dicho esto, que el creador del universo se apiade de los equipos que desarrollan software de producción sin TDD :-)
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Anterior Post
En el anterior post mostré a CobolScript generando salida basada en plantillas. Hoy quiero mostrar que eso se puede usar para generar páginas web. El ejemplo está en:
https://github.com/ajlopez/CobolScript/tree/master/samples/templateweb
El programa a ejecutar es simple:
var cobs = require('../..'),
http = require('http'),
fs = require('fs');
var program = cobs.compileTemplateFile('./factorial.cobp');
http.createServer(function(req, res) {
program.run(cobs.getRuntime({ request: req, response: res }));
}).listen(8000);
console.log('Server started, listening at port 8000');
La parte clave es la llamada a compilar el archivo de plantilla. Esto produce una función JavaScript ya compilada, que puede invocarse varias veces. El llamado program.run ejecuta la plantilla ya compilada, dado un contexto de ejecución (“runtime context”). Ese contexto es armado en cada pedido web, dándole los objectos request y response de ese pedido. El contexto se arma internamente, de manera tal que toda la salida producida por el programa CobolScript se deriva a la salida del response. De esta manera, el programa no sabe nada de web, sólo genera texto. Podemos ver a este contexto de ejecución como un proveedor de servicios para el programa CobolScript. Sus propiedades pueden ser accedidas si definimos una LINKAGE SECTION como en COBOL clásico. Pero eso sería tema para otro post. Ese acceso no fue necesario en este simple ejemplo.
El archivo de plantilla contiene:
<h1>Factorial</h1>
<p>Page generated by CobolScript, using templates</p>
<table>
<tr><th align='right'>n</th><th align='right'>n!
</th>
</tr>
<#
local n.
perform show-factorial using n varying n from 1 to 10.
#>
</table>
<#
.
stop run.
show-factorial section using n.
local result.
perform factorial using n giving result.
#>
<tr>
<td align='right'>${n}</td><td align='right'>${result}
</td>
</tr>
<#
.
factorial section using n.
local m.
if n = 1 then return n.
subtract 1 from n giving m.
perform factorial using m giving m.
multiply n by m.
return m.
#>
Lanzamos el servidor con la línea de comando:
node server
Luego, navegar a localhost:8000, para obtener el resultado:

Próximo post: un sitio web dinámico, escrito en CobolScript, ejecutando sobre Node.js, accediendo a una base de datos MySQL.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
Ya saben que soy un “fan” de los modelos (de dominio) en memoria, claro, cuando el contexto lo justifica. Veo que hay muchos problemas que tendrían una mejor solución si nos olvidamos por un tiempo del “cliché” “usa la base de datos, Luke!”. La base de datos debe aparecer evolutivamente. Y en muchos casos, no se necesita, más que como persistencia, no como lugar al que ir a operar en cada comando de negocio. Por ejemplo, hay muchos proyectos y aplicaciones reales que usan Redis, que usando un solo “thread” termina implementando un completo y poderoso “key-value store” en memoria, con opciones de persistencia (Redis Cluster todavía está en desarrollo).
Estoy divirtiéndome implementando ideas en mis proyectos personales, usando un modelo en memoria. Ver:
SimpleMemolap: Una especie de modelo OLAP multidimensional, con los datos a explorar residiendo en memoria. Escrito en JavaScript/Node.js, tiene un ejemplo web simple.
Memolap: Otro tipo OLAP multidimensional, pero esta vez en C#. Vean que el ejemplo web sigue en progreso (me salió más rápido el de Node.js).
SimplePermissions: Subjects, Roles, Permissions, Contexts, todo en memoria. Ideal para mantener las autorizaciones por usuario, aplicación, país, etc.
AjKeyvs: Una especie de Redis, en C#, en memoria. Tengo que implementar un protocolo cliente, y un servidor correspondiente. Por ahora, es una librería, que se puede usar local in-process. Me gustó implementar los algoritmos internos, con TDD, puedo mejorarlos, tengo todo listo para hacer refactor en cualquier momento.
SimpleStore: Algo parecido, un Redis en memoria, un “key-value store”, pero en JavaScript/Node.js. Trabaja local in-process, pero puedo exponerlo hacia afuera (remoto) usando otros módulos: quiero hacer “dog fooding” de otros proyectos míos.
SimpleQueue: Implementación en memoria, de una cola, en JavaScript/Node.js. Puedo usarla en el mismo proceso o exponerla hacia afuera, igual que comenté arriba.
SimpleTags: En mi sitio personal, coleccionaba items (páginas, enlaces, …) agrupados por categoría. Luego de ver otros sistemas (notablemente Gmail) veo que es muy útil, en lugar de poner los items en carpetas, simplemente asociarles “tags”. Este proyecto maneja items, con datos arbitrarios, asociados a uno o más tags (simples strings o key-value, ver la página de ejemplos). Escrito en JavaScript/Node.js)
Podría incluir también a SimpleRules: un motor de reglas donde los hechos residen en memoria (muchos motores de reglas usan directamente la memoria para representar el estado del mundo).
Y hasta podría mencionar: SimpleBoggle, donde la lista de palabras para resolver un juego/tablero de Boggle se carga en memoria.
Todavía por comenzar:
SimpleDatabase: base de datos en memoria, con un lenguaje de consultas tipo SQL, escrito en JavaScript/Node.js.
Muchos de estos proyectos podrían extenderse para tener persistencia “enchufable”. Pero por ahora estoy interesado en tener algo andando, para mostrar cómo puede usarse en distintas situaciones. Me gusta bastante implementar los algoritmos internos, árboles, búsqueda, índices invertidos, etc. Y todo eso, haciendo TDD a cada paso.
Nos leemos!
Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez
More Posts
« Previous page -
Next page »