jueves, 3 de agosto de 2017

Cómo escribir tu propio intérprete (o compilador)

Interpreter Book

Suelo escuchar varios podcast mientras me muevo por Buenos Aires u otras ciudades en mi trabajo. Uno de los que sigo desde hace años es el de Scott Hanselman, que es quizá una de las personas que más me impactó dentro de lo que se conoce como la "comunidad Microsoft".

Scott, más allá de seguir trabajando para Microsoft en el grupo de ASP.NET y herramientas de Azure, es un tipo inquieto que mantiene varios podcasts e iniciativas, y sobre todo valoro su constante esfuerzo por lograr una industria más inclusiva, recibiendo a a gente de toda edad, raza, identidad u orientación sexual, religión o ideario.

Pero basta de elogios al amigo Scott. El tema que me atrajo especialmente en éste último podcast fue que entrevistaba a Thorsten Ball, quien auto-publicó el libro "Writing An Interpreter In Go", que trata básicamente de eso: recorre todos los pasos de escritura de un intérprete. En su caso del lenguaje Monkey que él diseñó para el libro mismo, y que es bastante similar a JavaScript o un montón de otros lenguajes de la familia de las llaves {}.

Más allá de que es un tema interesante, me gustó que la manera en que lo hace es utilizando lo más básico de Go, sin más que la librería standard, construyendo desde cero el parser y el lexer, y sin usar ninguna librería particular. Y por supuesto, utilizando TDD.

Es un libro que recorre en mayor detalle el camino constante del Maestro Ángel Java López, que como puede verse en su cuenta de GitHub escribe este tipo de intérpretes o compiladores todo el tiempo.

¿Por qué escribir un intérprete a esta altura? Básicamente porque las capacidades y el entendimiento de sus partes nos ayudan a ser mejores programadores en general, como llegado cierto punto un buen automovilista tiene que aprender de mecánica, o un rocker necesita aprender sobre ingeniería de sonido.

jueves, 13 de julio de 2017

Codewars: jugar, practicar, codear

codewarsHace unos días recordé este sitio que conocí hace unos años, al verlo mencionado en un tweet de mi amigo el Maestro.

A raíz de esa mención volví a visitarlo y me alegró ver cuánto progreso mientras yo no estaba mirando.

Codewars es básicamente un sitio de práctica. Está basado en la idea de Code Katas, pero extendido a formas adicionales como el Kumite (una especie de competencia entre desarrolladores), y todo en un entorno colaborativo donde los participantes mismos son quienes agregan y refinan los ejercicios, también votando y comentando tanto los planteos como las distintas soluciones.

Entre las características que más me gustaron es que hay:

  • Diferentes niveles de dificultad
  • Tags que agrupan los ejercicios por temas, niveles, foco
  • Alto nivel de gamification: los participantes tenemos Kyu (niveles), Honor (puntos acumulados), seguidores, clanes y medallas entre muchas otras característica que generan una comunidad vibrante
  • Foros y comentarios bien integrados
  • Un gran contenido gratuito soportado por publicidad, pero que está bien integrada y es relevante (son siempre productos o servicios de desarrollo y los avisos no son molestos), más una oferta paga económica y que más allá de ofrecer unas pocas características avanzadas para quienes realmente le dedican mucho tiempo, es casi una membresía a un club de amigos.
  • Y sobre todo, la chance de aprender y/o practicar en una variedad enorme de lenguajes:
    (en este momento) C, Clojure, CoffeeScript, C++, Crystal, C#, Dart, Elixir, F#, Go, Haskell, Java, JavaScript, Lua, Objective-C, OCaml, PHP, Python, Ruby, Rust, Shell, SQL, Swift, Typescript, y otros que todavía no tienen Katas, pero están en proceso, como: CSS3, D, Erlang, Groovy, Julia, Kotlin, Liso, Perl, R, Racket, Sass y Scala.

Para los que ya saben que soy un enfermo de los lenguajes de programación, se dan cuenta que esto es un picnic para mi.

Recién retomé, y usualmente esto es para mi un equivalente a mirar series o jugar videojuegos: un pasatiempo estimulante. Los que quieran pueden encontrarme en Codewars y eventualmente podemos hacer un Kumite.

jueves, 29 de junio de 2017

Katas de Arquitectura

Un año atrás mi amiga Rox (¡que viva México!) me hizo una consulta por mail que acordamos compartir. Me demoré un poco, pero aquí va.

Primero copio su consulta:

Mañana tengo una sesión de kata de arquitectura con un equipo.  El objetivo principal no es la arquitectura en sí, sino un problema que tienen en partir en historias de usuario porque la mayoría de sus requerimientos son no-funcionales y dicen que no se puede.

Así que pensé en hacer un experimento: mezclar la kata de arquitectura con una kata de User Story Splitting.

Así que estoy en el sitio, pero veo que faltan los requerimientos no-funcionales que se agregan y recuerdo que tenías unas cartas.

¿Son los "normales" (escalabilidad, performance, mantenibilidad, etc)? o ¿cuáles son?

Y ahora mi respuesta (ampliada con algún material extra que no incluí en el mensaje original, que pongo entre [corchetes]):


¡Hola, Rox! 

Tarot de Arquitectura

Te paso el material:

 

Pero... me suena raro que quieran hacer historias de usuario sobre requisitos no funcionales, que es algo que no recomiendo, salvo que esté originado en un problema de negocio concreto (por ejemplo, la App se pone demasiado lenta cuando hay más de N usuarios).

Las cartas de Tarot están pensadas para discutir esos temas con la gente de negocio *en el contexto* de una historia funcional. 

Trataría de que para los atributos que quieren mejorar definan y anoten explícitamente:

Contexto

¿Por qué es importante este tema? Entender la operación detrás de este tema en un proceso concreto. No pensar que la aplicación tiene que escalar a tantos usuarios, sino lo como 'la transacción de pago de una orden' debe poder soportar tantas sesiones concurrentes.

Métrica 

¿Cómo vamos a medir que estamos en el nivel que queremos? Siguiendo el ejemplo anterior, puede ser cuánto tiempo demora para 1, 5, 10 o 30 transacciones concurrentes, y ponerle tiempos JUNTO con la gente de negocio.

Esto luego, idealmente se escribe en pruebas automatizadas que corren al menos en el build nocturno. 

Decisión 

¿Cómo hacemos para lograr esa métrica?

Acá es donde nos concentramos en 'lo técnico'. ¿Hacemos un componente que escale en threads? ¿Usamos una queue? ¿Cuál? Esto se va a convertir en una o más tareas, de una o más historias.

martes, 31 de mayo de 2016

3 dudas sobre Extreme Programming

Esta semana una asistente a uno de mis talleres de Desarrollo Ágil de Software me envío estas consultas, que como acordamos, intento contestar aquí de manera abierta, para ella y para otros que puedan tener esas dudas.

Hola Martín!

Saludos desde Lima.

Disfruté mucho el taller de Desarrollo de software ágil, ya lo estoy recomendando.... al pasar los días me surgieron unas preguntas que cuando tengas oportunidad por fa me escribes...

Vale la pena aclarar que yo voy a dar mi opinión personal. Yo empecé a utilizar ideas de Extreme Programming (XP) a fines de los '90 y a principios de los 2000 me convertí (se ve que no había mucho más para elegir) en XP Coach de varios equipos. En todo ese tiempo he juntado muchas ideas y dudas nuevas, pero trataré de aportar alternativas y vías de exploración, ya que no creo en que haya UNA respuesta para estos temas.

 

1- Una vez que se decide adoptar XP. El pair programming se aplica todo el tiempo? O se da cabida a espacios para programar individualmente y mob programming?  

Aunque en los orígenes de XP esa era la idea, en la práctica y a medida que ha pasado el tiempo la práctica se ha vuelto más pragmática. Recordemos siempre que a pesar del nombre, XP está basado en principios y valores que son los que buscamos, y las prácticas son solo un reflejo adaptable de ellos.

Cuando la solución más sencilla (recordemos que la Simplicidad es primordial en XP) es escribir el código de a uno, no vale la pena buscar un par. Los casos típicos son los que son triviales: construir otra pantalla, adaptador o función que es una variante particular de otras que ya están hechas.

Cuando el desafío es bajo y las tareas son de muy bajo riesgo, podemos obviar el par. Ahora, cuando nos encontramos realizando tareas repetitivas pero que pueden ser críticas, podemos al menos mantener un criterio de revisión de a pares. Lejos de la programación, en Kleer siempre hacemos revisión de a pares para propuestas o presupuestos.

Mob Programming es todavía una técnica relativamente experimental como práctica continua, pero en varias oportunidades en distintos equipos en los que trabajé pasamos de programar de a pares a tríos o cuartetos. Cuando uno pasa ese límite es difícil trabajar con un monitor usual y el salto a un proyector o una pantalla grande  implica un reacomodamiento mayor. Un paso intermedio usual es realizar workshops de diseño en conjunto para definir componentes de arquitectura, refactorizaciones importantes a nivel de framework o para ensayar alternativas de diseño con todo el equipo.

En todos los casos lo que funciona es probar y aprender. Una de las premisas es que si no experimentamos en la búsqueda de mejores maneras de trabajar como equipo, siempre estaremos ocupados pero probablemente desperdiciando esfuerzo.

 

Working Effectively with LEgacy Code

2- Se puede aplicar TDD o BDD a proyectos que ya han empezado de la manera tradicional (sin metodologia de desarrollo agil o casos de prueba?) o tiene que ser proyectos que aún no hayan arrancado?  

Claro que si. Lo más sencillo es usar TDD para código nuevo aunque la solución sea vieja. Un poco más complejo es construir la infraestructura de pruebas en el código antiguo. Para eso utilizamos una serie de técnicas especiales para romper dependencias fuertes en el código. La referencia canónica para esto es el excelente libro de Michael Feathers, Working Effectively with Legacy Code.

Básicamente, mientras haces TDD para el código nuevo, vas necesitando desacoplar la parte del código viejo con el que hay que interactuar, y para eso hay que ir logrando desarmarlo e ir dejando algunas pruebas que nos ayuden en esa tarea.

Algo que si desaconsejo es generar proyectos de "refactorización pura". Cuando nos ponemos exquisitos en cuanto a la calidad del código sin tener en cuenta las necesidades reales de la organización o sus clientes, nos arriesgamos a entrar en un proyecto con objetivos poco claros. Mejor que eso es comprometernos a usar estas técnicas para mejorar el código relacionado con la funcionalidad que necesitamos modificar, y esa manera, con el pasar del tiempo, las partes del código que requieren más cambios (lo que de alguna manera demuestra que son más valiosas) irán mejorando y serán más fáciles de entender, probar y extender.

 

3- Algunas empresas no les agrada mucho el aplicar Pair Programming porque tienen la idea que es menos productivo y que así los programadores charlarán entre ellos y no programaron. ¿ Qué argumentos se pueden utilizar para cambiar esas ideas? Y Cómo hacer para que los programadores efectivamente no se pongan en ese plan (pudiera pasar)  

Lamentablemente todavía hay organizaciones que dejan pasar las oportunidades de mejorar porque se enfocan en que la gente (a a que suelen llamar recursos) cumple un horario haciendo lo que suponen que es su tarea.

Si pensamos que la tarea de un desarrollador de software es programar, y no hablar, casi seguro obtendremos como resultado código que hace lo que el programador interpreta de un documento, sin entender lo que hace, y sin preocuparse por que lo que hace agregue valor. Para un desarrollador en esas situaciones siempre recomiendo tratar de generar evidencias de que hay maneras mejores de trabajar, y en último lugar recuerdo siempre el dicho "si no puedes cambiar tu trabajo, cambia tu trabajo". No me parece bien tomarse livianamente la ida de que la organización "es así", porque en muchos casos vi gente desde las posiciones más humildes e inesperadas generar una ola de cambio. 

Un buen desarrollador tiene que charlar con el resto del equipo y buscar soluciones apropiadas a las necesidades planteadas, y debe lograr entender el contexto de negocio y aportar su visión. Si limitamos a los desarrolladores a programar lo que otros le indican sin nada más, llegaremos siempre a soluciones mediocres o pobres. De la misma manera, si el equipo no entiende y no está conectado con los problemas que tiene que resolver, su motivación será obviamente más baja, y eso no lo compensa trabajar de a pares o no. 

Al revés, si el equipo está conectado con el negocio, al trabajar de a pares encontrarán mejores soluciones que trabajando solos. El principal problema de trabajar solo para un desarrollador es la facilidad para perder el foco o bloquearse en detalles menores, cosas que casi no suceden al trabajar de a pares.

En resumen, para mi un argumento fundamental es si queremos "cantidad de código" o "buenas soluciones".

lunes, 16 de mayo de 2016

El Kyū-Dan de la Integración Continua

Cinturones de Judo

En algún momento del 2014, tuve una consulta de mi amigo Sebis Henzenn, que generó (estaba lejos y tenía un rato)  un mail con una explicación bastante larga de lo que se me ocurrió en ese momento como una metáfora aproximada de los pasos de aprendizaje respecto a prácticas relacionadas con Integración Continua y sus derivaciones.

El mensaje quedó guardado unos años, pero lo recordé recién hablando con otro amigo, Edson Chávez, de Kleer Perú, donde estoy en este momento.

Así que aquí va mi elucubración de esa vez, que no sufrió mucho cambios en el ínterin. Sólo aclararía que no es una categorización exhaustiva, sino un recorrido posible, que espero que le sirva a alguien para formular sus planes al respecto.

Aquí el texto original:

Mi recomendación es empezar por el build server, e ir evolucionando. Por ejemplo:

Cinturón blanco:
- instalás Team City (o Jenkins, o el que te guste -salvo TFS que yo no recomendaría).
- empezás haciendo que cada equipo aprenda a configurar su proyecto (es importante que sepan hacerlo ellos)
- lo básico es que en cada commit el proyecto compile, por lo menos
- que se acostumbren a no tener el proyecto en rojo NUNCA. Si queda en rojo, arreglarlo antes de seguir con nada.

Cinturón amarillo:
- pueden empezar a hacer tests (si no los hacen) y correrlos en el build en cada commit.
- de nuevo: nunca dejarlo en rojo, y aprovechar los arreglos para entender más lo que los demás están haciendo y nivelar la calidad de las pruebas.

Cinturón naranja:
- empezar a hacer TDD y ATDD, y elevar el número de pruebas
- seleccionar alguna manera de medir code coverage y hacer que el build falle si ni se alcanza el 1% (pruebas mínimas)
- cada tanto medir el coverage promedio de la solución e ir subiendo el límite casi hasta ahí (incrementalmente)
- cada vez que se reporta un incidente o bug (en testing o producción), no puede arreglarse si no se escribe la prueba primero que demuestra el problema, y se da por resuelto una vez que se corrige la aplicación para que pase ese test

Cinturón verde:
- empezar a ejecutar analizadores estáticos, y que el build server muestre el informe.
- concentrarse en los problemas más importantes; cuando ya no existen en la solución, hacer que rompan el build
- seguir con el problema más importante, y así sucesivamente; alcanza con eliminar un tema o dos por sprint

Cinturón azul:
- empezar a versionar junto al código migraciones de bases de datos, configuraciones y scripts de instalación de componentes o librerías
- hacer que si el build server compiló con éxito y ejecutó todas las pruebas y validaciones, genere desde cero un entorno nuevo de testing

Cinturón marrón:
- trabajar en conjunto con el equipo responsable de despliegue para que valide y adopte los scripts y métodos de generación de ambientes
- lograr que el build server genere en cada commit un ambiente de prueba desde cero, y otro incremental
- lograr que si se detecta un problema en el ambiente incremental, se pueda volver a la versión anterior de la aplicación con el script de reversión

Cinturón negro:
- cada vez que un desarrollador hace un commit que pasa todo el pipeline de pruebas y validaciones en csda uno de los ambientes de prueba, potencialmente puede llegar a producción de manera automática, aunque se opte por decidir manualmente el momento de despliegue
- trabajar en el diseño de la solución para que soporte el desplliegue sin interrupciones de servicio (hot deploy)

Cinturón rojo:
- cada vez que un desarrollador hace un commit, llega a producción sin interrupción de servicio

 

Cada uno de esos saltos puede llevar de 1 a 9 meses, dependiendo del equipo, el proyecto, y de dónde arrancar en cada parte, pero creo que te das una idea. :)