martes, 30 de noviembre de 2010

Una retrospectiva en Eden

Ya se que os tengo que hablar de los valores de Eden, pero hoy he podido asistir a una retrospectiva con un cliente y prefiero contaros como se lo montan :D Sobre los valores os prometo una entrada el fin de semana.

Antes de entrar en harina, hoy he conocido a Frances y bueno, super amable y encantadora. Además, nos ha traido una tarta de chocolate hecha por su hermana que estaba muy rica. Parece ser que mañana nos va a traer unos mince pies caseros que, por lo que dicen, son de chuparse los dedos :)

Hablemos de la retro
La retro de hoy la ha facilitado Aimee y han participado, por parte del cliente, las 4 personas que hay ahora mismo en Eden, y por parte de Eden, Enrique, Steve (via Skype porque sigue enfermo), Aimee y yo (Yo por parte de Eden, ¿qué os parece? Alucino :P ), aunque básicamente he ido a curiosear.

La retro ha empezado de una forma muy chula. Los implicados hemos entrado en la sala y nos hemos sentado alrededor de una mesa redonda. Delante nuestra teníamos una nota que decía:


Regardless of what we discover, we understand and truly believe that everyone did the best job they could, given what they knew at the time, their skills and abilities, the resources available, and the situation at hand.
Independientemente de lo que descubrimos, entendemos y creemos firmemente que todo el mundo hizo el mejor trabajo que pudo, teniendo en cuenta lo que sabían en ese momento, sus destrezas y habilidades, los recursos disponibles, y la situación actual.

Actualizado: Aimee me ha pasado el enlace a la cita original :D

Todo el mundo ha leido la nota y se ha mostrado de acuerdo :) (uno por uno hemos dicho "estoy de acuerdo")

Después, se han fijado unas reglas básicas (no se como traducir ground rules) para la retro entre todos los asistentes. Por ejemplo, hay que pedir la palabra levantando la mano, o queda prohibido faltar al respeto a la gente, o hacemos media hora, paramos y luego otra media hora.

Una vez fijadas las reglas, Aimee nos ha pedido que escribieramos en postits eventos importantes que han ocurrido en las dos semanas de proyecto que se iban a retrospectivar (un evento por postit). Algunos ejemplos, Enrique ha escrito que el 14 de noviembre estaba en Madrid en un curso de TDD (que es igual que escribir que no estaba en Inglaterra pero mola más :D), que el 23 fueron a las oficinas del cliente, etc. Supongo que os hacéis una idea. Una vez escritos los postits, los hemos que colocarlos en un calendario en su correspondiente día. Ha quedado algo parecido a esto:


Luego hemos puesto en común los eventos que ha escrito cada uno y hemos dibujado nuestra línea de "sentimiento" del proyecto. Os lo enseño y después os lo explico:


La línea punteada representa el estado "neutral", ni frio ni calor. Cada línea continua representa el sentimiento de un miembro del equipo durante las dos semanas de proyecto.
Una vez que todos los miembros del equipo han dibujado su línea (la mía es la roja :P) cada uno explica por qué la línea es como es, lo que da lugar a que todo el mundo sepa como se siente cada uno de los implicados.
No se ha vosotros, pero a mi me ha parecido una forma muy chula de expresar el bien y el mal del proyecto y, lo que es más importante, de compartirlo :)

Esto nos ha consumido la primera media hora, así que hemos parado para beber un poco, ir al baño, lo típico. Cinco minutos después hemos vuelto al ataque.

La segunda parte de la retrospectiva la hemos dedicado a tratar los problemas que más han afectado al proyecto. Para decidir que temas eran los que más importaban hemos juntado los postit-evento por temas y hemos votado los temas (7 puntos y puedes asignar tantos puntos como quieras a cualquier tema). Se han seleccionado los tres más votados y se ha charlado un rato de cada uno. En el momento en el que la discusión dejaba de tratar sobre como trabajar mejor para centrarse en detalles muy específicos del proyecto, alguien pedía tiempo muerto y cortaba la conversación. Esto mantenía enfocada la reunión.

Como punto y final de la retro, Aimee ha apuntado las conclusiones y las posibles mejoras en tarjetas y las ha dejado pegadas a la pared para que todo el mundo las pueda ver.

Y eso es todo, la verdad es que me ha parecido una forma muy amena de llevar una retrospectiva.

Nos vemos :)

PD: El servidor va igual que ayer porque hoy he borrado todo lo que hice y lo he vuelto a hacer desde otro enfoque :S Esperemos que mañana avance algo más.

lunes, 29 de noviembre de 2010

Eden por dentro

Hoy he empezado mi internship en Eden y tengo que deciros que esto es la caña. He conocido a Chris, Todd, Spencer, Juliet y Aimee y son todos muy simpáticos y muy amables. Entre Chris y Aimee me han explicado lo que es Eden y me han pasado su "código de valores" (A ver si mañana os blogueo algo). Sinceramente, es una empresa espectacular. No se muy bien como explicarlo, pero escucharles contar como sienten la empresa y verlos en acción con sus clientes deja bien claro que su máximo interes es hacer que las personas se superen. Es muy inspirador.

Aimee y Steve iban a ser los encargados de darme caña estos primeros días, pero Steve (al que conocí en la Software Craftsmanship y al que todavía debo una cerveza) está enfermo y le ha tocado a Aimee lidiar conmigo :) Lo primero que hemos hecho Aimee y yo ha sido modificar la web de Eden. Supongo que la mayoría ya os habréis dado cuenta del cambio :P El proceso entero ha sido muy sencillo. El código está en github y el deploy se hace con un comando. A prueba de plagelaos :)
Más tarde, Aimee me ha encargado (ha petición de enrique vía email) una tarea algo más compleja. Me ha pedido que realice una implementación de un servidor web que cumpla la rfc2616 :) Además, tendré que hacer una exposición sobre el tema el próximo viernes... Por supuesto, hay que desarrollarlo usando TDD (Con Cucumber y RSpec). Para añadir algo de dificultad al ejercicio, me he propuesto hacerlo en Ruby y utilizando el Vim (bueno, el MacVim, que es algo más amigable) ¿Qué puede salir mal? Pues nada, porque hemos venido a aprender y a mejorar, y eso no se consigue dentro de tu zona de confort. Hay que tirarse a la piscina.
Por si os interesa el código lo estoy dejando en github, aunque estos próximos días os iré contando mis dudas y las soluciones. De momento, hoy he aprendido a lanzar todos los specs de mi proyecto a la vez :P Os cuento como lo he hecho. Me he creado un fichero spec_helper.rb en el que he metido todos los ficheros con specs como require. Después lo único que hago es ruby spec_helper.rb y automagicamente se ejecutan todos los tests. Supongo que habrá alguna forma más sencilla de hacerlo ¿Me la contáis? Tampoco me importaría mirar un poco como funciona autotest...

No quería terminar sin agradeceros a todos los ánimos que me estáis dando :D ¡Muchas gracias!

Por cierto, creo que en Madrid ha nevado hoy ¿no? Aquí ha salido el sol por la mañana :) La vida puede ser maravillosa, que decía aquel.

Saludos del "Lucky Bastard" :P

PD: Me dejo muchas cosas en el tintero (Todd explicándome que si tengo algún problema no dude en hablar con él, Spencer recogiéndome en el B&B para llevarme a Eden, el bollo que me ha comprado Juliet, las cañas que nos hemos tomado al salir con los chicos de la empresa cliente a la que están ayudando de la que no recuerdo el nombre ahora, etc). Todo genial.

domingo, 28 de noviembre de 2010

Un plagelao en Winchester

¡Sí, ya estoy en Winchester! De momento (no podía ser de otra forma) todo está siendo espectacular.

Para empezar, Enrique Comba me ha ido a recoger a la estación y me ha acompañado a lo que va a ser mi casa durante este mes, Flowerdrews. Es el B&B que me buscó Juliet Arnott y es increíble (además de calentito). Siento no tener cámara de fotos (sí, soy lamentable), pero os lo recomiendo 100% a todos los que vengáis a Winchester. Es un sitio bastante tranquilo, las habitaciones son enormes y la pareja que lo lleva es super amable :)

Después de dejar la maleta y la mochila en la habitación, Enrique me ha llevado a las oficinas de Eden Development. "Yo... He visto cosas que vosotros no creeriais" :P Las oficinas reflejan todo lo que Enrique nos ha contado tanto en el aos2010 como en la lista de agile-spain. Hay restos de inceptions, story boards, libros, teclados Dvorak, sillas con nombres de bólidos, un globo-clon y muchos Macs ("ordenadores de verdad" los llama Enrique). Un pasote :) Sin embargo, lo que más me ha llamado la antención es la cantidad de espacio "libre" que tienen. De hecho, Enrique me ha contado que ellos no tienen un sitio fijo en el que trabajar. Cada uno trabaja donde le da la gana (o donde haya elegido su pareja, claro). Estoy deseando ir mañana para ver el taller a pleno rendimiento :) Va a ser una pasada.

Tras la visita a las oficinas de Eden, nos hemos ido de ruta turística por Winchester. Hemos visto al Rey Arturo, el mercado de Navidad, el centro de la ciudad, la catedral (testimonio gráfico incluido), etc, aunque lo mejor ha sido la charla durante el recorrido, saltando del software a la fotografía, pasando por la comida y, como no, por Eden Madrid :)

Siento que la entrada sea tan cortita, pero estoy baldado y mañana va a ser un día duro. De hecho, una de las cosas que me ha dicho Enrique es que esta primera semana las voy a pasar canutas, así que me voy a dormir :) ¡Mañana más!

miércoles, 24 de noviembre de 2010

Más sobre S.O.L.I.D.

En el último post os intenté convencer de que habíamos conseguido no violar el principio de inversión de dependencias con nuestra clase Banco. Si no lo recordáis, nos quedó algo como esto:



José Luis Barrera me sugirió en los comentarios que utilizáramos una clase Credenciales que agrupara tanto el nombre del usuario como el Pin. Con esa nueva abstracción, el código de Banco queda aún más claro:



Guay :D

Ahora bien, ¿qué ocurre cuando la validación de las Credenciales falla? Tal y como tenemos ahora mismo nuestra implementación, OperacionesBancarias lanzaría una excepción por cada tipo de error que se produzca al validar el usuario. Por ejemplo, si lo que falla es que las Credenciales son incorrectas se produce una excepción CredencialesIncorrectas. Si lo que sucede es que la validación de las Credenciales ha sido fallida más de tres veces, la excepción que se lanza es una AccesoInvalidadoPorMultiplesReintentosFallidos. Si lo que se produce es un error en el acceso al banco real, se lanzará un BancoInaccesible.
Veamos como implementaríamos un cliente de Banco (un Cajero) que se preocupe del resultado de la validación:



Pues no parece que sea muy legible... No se vosotros, pero yo estoy bastante acostumbrado a este tipo de código y tengo que decir ¡basta ya!
Las excepciones que captura Cajero no son parte de la abstracción de Banco, son detalles de bajo nivel que se encuentran en OperacionesBancariasBancoManolito, con lo que estamos volviendo a violar el principio de inversión de dependencias. Además, estamos controlando el flujo del programa mediante excepciones. ¡Que desastre!

Las excepciones deberían ser para casos excepcionales
Como bien nos contó (recordó) Enrique Comba en el curso de T.D.D., las excepciones deben ser excepcionales. No tiene sentido usarlas para controlar el flujo porque, en ese caso, dejan de ser excepcionales. Esto que parece tan trivial es una de las cosas que más nos cuesta cuando nos ponemos a programar.
Con esto en mente, volvamos a nuestro ejemplo, ¿Es excepcional que unas Credenciales sean incorrectas? ¿Es excepcional que un Banco tenga que anular una tarjeta porque el usuario se ha equivocado n veces al intentar usarla? De nuestro ejemplo, el único caso "excepcional" puede ser que el banco real no esté accesible pero ¿de verdad es tan raro que haya un corte de comunicaciones? Para mi, ninguno de estos casos es merecedor de una excepción, así que vamos a intentar arreglarlo. Lo primero que vamos a hacer es que Cajero no dependa de los detalles de OperacionesBancariasBancoManolito (y si de paso evitamos controlar el flujo con excepciones, mejor que mejor). Para ello, vamos a pasarle al Banco la responsabilidad de avisar al Cajero cuando suceda un evento de validación (correcta, incorrecta, invalida, sin conexión). Refatorizamos nuestro Banco para que quede como sigue:



y nuestro Cajero ahora queda mucho más limpio:



Aunque nuestra clase Cajero ha quedado mucho más clara, hemos pasado el problema de las excepciones a la clase Banco. Además, estamos violando el principio de segregación de interfaces (I). Vayamos paso a paso.

Segregación de interfaces

Clients should not be forced to depend upon interfaces that they do not use.

Los clientes no deben verse forzados a depender de interfaces que no usan.

Para cumplir este principio, nuestra clase Cajero debe implementar un interfaz para manejar los eventos de validación, que es lo único que la clase Banco necesita conocer de Cajero:



Y nuestra clase Banco dejaría de depender de Cajero para depender de dicho interfaz:



Ahora que nuestra clase Cajero ya cumple el principio de segregación de interfaces, arreglemos Banco.
La solución que se me ha ocurrido es que sea la abstracción Token la que nos de la información que actualmente nos dan las excepciones:



Ahora el flujo ya no es guiado por excepciones pero, lo que me parece más importante aún, es que nuestro código ahora es más sencillo de extender. Antes necesitábamos ir a un javadoc (o similar) para leer que tipo de excepciones eran necesarias para que Banco funcionara, ahora basta con implementar Token.

Por último, tengo que decir que no me gustan las estructuras if-elseif-elseif-else, pero para este caso en particular no me parece tan horrible. Si los motivos por los que Token puede no ser válido fueran más o pudieran cambiar más a menudo me pensaría una solución con suscriptores similar a la que hemos utilizado con el Cajero. Si os apetece hacerlo os lo dejo como ejercicio :P

Perdonad que me haya quedado una entrada tan larga y atolondrada. Espero que al menos se entienda lo que he intentado expresar :D ¡Nos vemos en la siguiente!

Nota: No haría estas refactorizaciones que he hecho aquí si no tuviera una buena base de pruebas contra las que probar cada pasito.

jueves, 18 de noviembre de 2010

Violando la D de S.O.L.I.D

A principios de semana tuve la suerte de asistir al curso de TDD que impartió Enrique Comba en Madrid. Me lo pasé genial pero me fui aún más convencido de que programar es muy difícil.
Aunque el temario del curso fue bastante amplio, yo sólo voy a centrarme en los principios S.O.L.I.D. Si queréis saber más sobre lo que hicimos allí, Jesús Jiménez ha escrito este post explicándolo.

El primer día del curso, Enrique nos dividió en 5 grupos y nos asignó la exposición de un principio S.O.L.I.D. a cada equipo. A nosotros (Amalia Hernandez, Jesús Jiménez, Leo Antolí y yo) nos tocó explicar la D.

Inversión de Dependencias (D)

High level modules should not depend upon low level modules. Both should depend upon abstractions
Abstractions should not depend upon details. Details should depend upon abstractions

Los módulos de alto nivel no deberían depender de módulos de bajo nivel. Ambos deberían depender de abstracciones
Las abstraccciones no deberían depender de los detalles. Los detalles deberían depender de las abstracciones

Cuéntamelo con código
El segundo día lo dedicamos a crear el software que controla un cajero automático (haciendo T.D.D., claro). El código que creó nuestro equipo (los mismos cuatro que el día anterior) lo tenéis completo aquí, pero yo me voy a centrar sólo en nuestra implementación de la clase Banco:



Lo que hace la clase Banco es realizar una petición de validación mediante el Conector a una url. Dicha validación nos devuelve un json a partir del cual se puede crear el token de seguridad con el que se realizarán las siguientes operaciones del usuario validado.

¿Habremos sido capaces de respetar el principio que nos tocó explicar el día anterior?

Los módulos de alto nivel (Banco) no deben depender de módulos de bajo nivel(Implementaciones de Conector y GeneradorToken), ambos deben depender de abstracciones. Nuestro Banco depende de la abstracción Conector y de la abstracción GeneradorToken, pero no "conoce" que implementación de cada abstracción está usando (Ambas se le inyectan en el constructor). Parece que esta parte es correcta.

Las abstracciones (Banco) no deben depender de detalles. Los detalles deben depender de abstracciones. En esta parte es donde hemos metido la pata. Si Banco no debe depender de detalles ¿Qué pinta la construcción de la url contra la que debe operar el Conector? ¿Por qué el Banco conoce que el Conector devuelve json?

Pensando en esto se me ocurre el siguiente refactor de Banco:



Nuestro módulo de alto nivel depende ahora de una abstracción más general, dejándole a los módulos de bajo nivel (Las implementaciones de OperacionesBancarias) todo lo que tiene que ver con la infraestructura (tipo de comunicación, transformación de la respuesta, etc). Pero, ¿no es el token un detalle de bajo nivel? Si la respuesta es afirmativa deberíamos eliminarlo de Banco y OperacionesBancarias devolvería directamente la Cuenta, haciendo que nuestra clase Banco fuera redundante. Sin embargo, yo (que soy el que está programando :P ) creo que cualquier autenticación bancaria me va a devolver un token (hablo desde la ignorancia, pero suena bien) con lo que deja de ser un detalle para formar parte de la abstracción. Eso sí, no estaría mal que fuera una clase Token en lugar de un String, que no todos los tokens tienen porque ser iguales. La clase Banco que no viola el principio de inversión de dependencias quedaría así:



Conclusiones
Yo ya conocía los principios S.O.L.I.D. y se que mis compañeros también (aunque de este código tenemos la culpa Leo y yo :D ). Nos habíamos preocupado de leerlos y de intentar entenderlos mucho antes de dar este curso. Entonces, ¿por qué no fuimos capaces de recordar la dichosa D. incluso habiendo tenido que explicarla el día anterior? Yo pienso que es porque no lo tenemos interiorizado. Hace falta mucha práctica y mucha experiencia trabajando con los principios S.O.L.I.D. en la cabeza para que no se te olviden mientras programas. Por eso considero importante practicar T.D.D. con ejemplos sencillos, porque lo importante no es resolver el problema, lo importante es el proceso mental con el que resuelves el problema.


Criticadme, por favor
Lo que os he contado en este artículo es como entiendo yo el principio de inversión de dependencias. ¿Coincide con lo que entendéis vosotros? Si no es así, ¿en que me he equivocado?