Hace tiempo que llevo pendiente compensar el desequilibrio en artículos técnicos que últimamente tengo en el blog, así que aquí va éste.
El pasado día 22 de diciembre celebramos el segundo aniversario del primer coding dojo que organizamos como AGILISMO.es. Luis Rivera, siempre disponible para echarnos una mano, nos prestó las instalaciones de Okuri, también conocidas como Tetuan Valley porque allí tiene la sede esta iniciativa de incubación y aceleración de startups en Madrid. Echamos de menos a Alejandro y Roberto, de Autentia, a los que tanto tenemos que agradecer durante estos dos años. Pero junto a los habituales también estuvo gente nueva. Eso es buena señal.
Hasta aquí no parece un artículo técnico, ¿verdad? Bueno, pues al grano. Durante el desarrollo del coding dojo, con la PomodoroKata como ejercicio, surgió un debate sobre si dejar el número 25 en los primeros pasos del desarrollo es aceptable o no. Xavi defendía la sustitución del 25 por una constante por tratarse de un número mágico mientras que @mikelodeon opinaba que era suficientemente expresivo y que el refactor era prematuro.
Como podeis comprobar en el video de la kata que grabé hace ya dos años, yo también prefiero sustituir el 25 por una constante (minuto 1:40 aprox) por las siguientes razones:
* el método minutesLeft devolviendo 25 es menos expresivo que minutesLeft devolviendo DEFAULT_DURATION
* en el test también hago este refactor aunque el título del test es incorrecto y debería decir "Un pomodoro tiene una duración por defecto", porque realmente me es indiferente cuál sea esa duración
* si realmente hubiera querido probar que la duración por defecto es 25 entonces debería haber tenido un test del tipo: assertEquals("La duración por defecto es 25", 25, Pomodoro.DEFAULT_DURATION), lo que nos habría llevado a pasar esa constante de privada a pública.
Como veis, mis argumentos están basados en la expresividad del código y en que se ajusten a lo que se quiere probar. El trabajo más difícil es siempre elegir bien los tests porque, dependiendo de ellos, nuestro diseño y posterior implementación tomarán un rumbo u otro.
Hacía tiempo que quería hacer un ejercicio interesante (al menos para mi) que consiste en hacer una codekata muy sencilla a pequeños pasos o, como dice Kent Beck en su libro “TDD: By Example“, con baby-steps. Me interesa estudiar cuáles son las fuerzas que empujan a refactorizar hacia un mejor diseño y para eso verlo en un ejercicio de laboratorio me parece ideal. En este sentido, también me interesa ver cómo se aplica la “Premisa de la Prioridad de las Transformaciones” expuesta recientemente por UncleBob.
FizzBuzz en Github (pasito a pasito)
Así pues, he creado un proyecto vacío con Jeweler (mi lenguaje de elección ha sido Ruby porque necesito practicarlo más) y he trabajado sólo en el fichero de test por simplicidad. Jeweler crea el esqueleto y te lo deja todo muy fácil para ejecutar los tests sin más que ejecutar:
rake test
De hecho, Jeweler te hace hasta el primer commit en git y lo deja listo para subirlo a github. Bueno, el resultado de este experimento lo he dejado en Github y veréis que se trata de la kata FizzBuzz, que es lo suficientemente sencilla como para no alargar demasiado el ejercicio. Si alguien tiene ganas de empezar con GitHub, también recomiendo este tutorial de primeros pasos de Adictos al Trabajo.
Así que fui haciendo commit con git para cada uno de los pasos, incluso en aquellos en los que estaba en rojo, porque la idea era tener todos los comentarios que explicaban ese paso en la historia de los commits y así, quizás algún día, tener una herramienta que me permita visualizar ese “paso a paso” a modo de slideshow.
De paso, en el camino, he puesto en práctica mi kung-fu con Git y he aprendido a:
Cambiar el comentario del último commit
Como los comentarios en este ejercicio son fundamentales, no podía permitirme que no pusieran exactamente lo que quería poner. Así que busqué y encontré esto:
git commit --amend
Esto lo que hace es proponerte el editor por defecto para modificar el mensaje del commit.
Deshacer los últimos commits
Más adelante me encontré con que había ido haciendo unas refactorizaciones que no me gustaban nada, así que quise volver atrás. Normalmente habría deshecho los cambios en el editor y hecho un nuevo commit, pero eso habría dejado un poco sucio la historia.
git reset <el hash del commit hasta el que queremos volver>
Esto nos pone apuntando justo a ese commit al que hemos hecho referencia. Si no sabéis cómo conocer el hash, “git log”, aunque hay maneras de abreviarlo y también vale.
Hacer push a github sin haber hecho clone antes
Pensaba que ya había hecho creado el repositorio en github y que había hecho clone (que es lo que se suele hacer), pero como había empezado directamente desde el esqueleto que me ofrecía Jeweler, ni me acordé de todo eso. Así que creé el repositorio en github y, claro, ya no se parecía a lo que Jeweler había dejado configurado por defecto. El nombre del proyecto en local era “fizzbuzz” y en Github era “fizzbuzz-babysteps”. Además, al hacer git push me daba un error. Así que de nuevo recurrí a Google y Stackoverflow y encontré esto otro:
La primera vez que usé Git lo hice siguiendo el tutorial GitImmersion. Allí vi que se podían definir alias muy útiles para simplificar muchas de las tareas habituales. Los amigos de Emergya también nos recomiendan algunos. En particular el hacer “commit -a” parece una tontada, pero a mi me da mucha pereza hacer “git add” todas las veces.
LA FOTO: La encontré a través de “Google images” y, la verdad, no he pedido permiso. Espero que como es bastante inocentona y no busco lucrarme, no haya ningún abogado americano que me denuncie. Si alguien tiene interés en la fuente original (la que me da Google), es ésta. Ya véis, nada interesante.
Los que me conocen de cerca saben que siempre estoy intentando aprender cosas nuevas. Es la única manera que conozco para no quedar desactualizado en un sector tan exigente como el nuestro, sobre todo si quieres seguir viviendo de él hasta los 67 o más allá. Y la juventud viene con mucha fuerza. Empieza a dar un poco de respeto ver a gente como @jacegu, @kinisoftware, los @hermanosSoto y otros muchos. Programan en lenguajes que me son completamente desconocidos y están constantemente aprendiendo cosas nuevas. Pero lo peor de todo es que ¡¡tienen mucho tiempo libre!! Así que no tengo más remedio que ponerme las pilas si no quiero quedar definitivamente arrinconado junto a los libros de “Aprende Java en 15 días” o, peor aún, junto a los de “Guía Práctica de dBase III” (todos enmohecidos y arrugados por el paso de los años). ¡Qué demonios! Hace mucho (muuuuucho) yo programaba en BASIC, en C, en C++, en COBOL, en LISP… así que simplemente porque mi lenguaje para programar en los últimos ¿diez? años haya sido prácticamente sólo uno (Java) no quiere decir que no pueda aprender cualquier otro. Así que vamos a ello. Vamos a aprender otra cosa: por ejemplo, Ruby.
Ya me he hecho las RubyKoans (que, por cierto, las tengo que volver a hacer porque con una sóla vez no me es suficiente). También me he comprado el libro “Programming Ruby 1.9″ (pero sólo con comprarlo no es suficiente). Necesito practicar. Y para practicar necesito un mínimo ecosistema. No, no es una excusa: vamos a ver cómo lo voy aprendiendo y construyendo.
RSpec
Entorno: Ubuntu 10.10 + Ruby 1.9.2
Antes que nada he de reconocer que no sé bien qué hice para tener Ruby 1.9 en Ubuntu. El que viene por defecto es 1.8 y yo me lié bastante intentando poner “rvm”. Al final lo conseguí con la ayuda de @ecomba, pero lo cierto es que no sé bien qué hice. #FAIL
Pero si consigues instalar “rvm” el resto es mucho más fácil. Puedes instalar cualquier versión de Ruby y todo el entorno es mucho más controlado.
$ rvm install 1.9.2
$ rvm use 1.9.2
$ rvm gemset create tdd
$ rvm use gemset 1.9.2@tdd --default
Para empezar con RSpec hay que instalar la gema “rspec”.
$ gem install rspec
En ~/.rspec tengo:
--colour
--format documentation
De esta forma se ve mucho mejor el resultado de la ejecución.
Autotest
Con esto ya podríamos empezar con RSpec, pero ya que hay una utilidad llamada autotest que nos permite evitar tener que ejecutar los tests cada vez y, dado que soy muuuuuuuuuuuuuuy vago (como buen programador)
Escribo un poco de memoria y echando mano de mi .bash_history, así que es posible que se me haya pasado algo.
De esta manera configuro las notificaciones para que aparezcan como una nota emergente, al estilo “growl”. Desgraciadamente no he conseguido en Ubuntu nada parecido a Growl (sólo en Mac)
En spec vamos a poner el test que escribiremos con RSpec
En lib vamos a poner el código que escribiremos en Ruby
Y además en ejemplo/autotest/ hay que incluir un fichero discover.rb que diga:
Autotest.add_discovery { "rspec2" }
De esta manera, autotest puede encontrar las specs y ejecutar rspec sin decirle nada explícitamente.
Arrancamos autotest para no tener que andar ejecutando rspec cada vez. Una notificación emergente me dice “1 example, 1 failed”. Bien. Está funcionando correctamente. En la consola donde se está ejecutando autotest veo:
Rspec Greeter
should say 'Hello RSpec!' when it receives the greet() message (FAILED - 1)
Failures:
1) Rspec Greeter should say 'Hello RSpec!' when it receives the greet() message
Failure/Error: greeting = greeter.greet
NoMethodError:
undefined method `greet' for #<RSpecGreeter:0x00000001a48e80> # ./spec/greeter_spec.rb:6:in `block (2 levels) in <top (required)>'
Finished in 0.00042 seconds
1 example, 1 failure
Editamos greeter.rb para pasar el test.
Al guardar la modificación, autotest ejecutará rspec por nosotros y en la ventana donde se ejecuta autotest aparecerá el resultado de la ejecución y una notificación emergente aparecerá en verde indicando que hemos pasado “1 example”, es decir, que se ha ejecutado 1 test correctamente.
Rspec Greeter
should say 'Hello RSpec!' when it receives the greet() message
Finished in 0.00038 seconds
1 example, 0 failures
De momento sólo estoy conociendo la herramienta. Hay que conocer las herramientas, claro, pero no es lo principal. Tengo que aplicarme con la lectura de “The RSpec Book”, aprender bien cómo usar RSpec y Cucumber y, sobre todo, practicar mucho para escribir buenas especificaciones ejecutables. Ése es mi objetivo. En eso quiero destacar y ser lo mejor que pueda.
Por supuesto, si veis alguna incorrección o tenéis cualquier sugerencia o comentario, estoy deseando leer vuestros comentarios.
FOTO: La imagen que ilustra este artículo es de Enrique Comba y representa el respeto que me dan esos chavales que vienen por detrás pisando fuerte y que, afortunadamente, me estimulan a no relajarme. <ironic_mode>El personaje fotografiado he de reconocer que, afortunadamente, no me suena de nada. Seguro que a @amaliahern tampoco.</ironic_mode>
ACTUALIZACIÓN:
La verdad es que ni me acordaba de dónde había sacado la mayoría de la ayuda para configurar. Creía que había sido de Enrique, pero Alberto @sharpbites Rodríguez me lo acaba de recordar. La mayor parte de la culpa de esta configuración tan chula es suya. Lo dicho, ¡¡esta gente dan verdadero miedo!!