Evolucionando mi TDD parte I

2015-07-19
TDD

Esta última semana he tenido la suerte de poder asistir al training de TDD de Carlos Blé. En el curso he aprendido un montón de cosas, muchas de ellas ya las sabía pero hasta que no haces una aplicación directa no terminas de verle el potencial. Quiero agradecer a Carlos no sólo por permitirnos asistir y por la calidad del curso ya que fue muy práctico y productivo. También quiero agradecer a todos los asistentes por su motivación y los grandes debates que surgieron.

Gracias al curso mi estilo de TDD ha comenzado a evolucionar y espero que no pare nunca de hacerlo, durante el curso mis compañeros Miguel Ángel Viera y Daniel Ojeda y yo hemos tomado un montón de notas. Después del training seguimos debatiendo y asimilando conceptos. Intentaré ir reflejando todo lo aprendido en varios posts, este tan sólo es el primero de ellos.

EXTREME PROGRAMMING

El curso empezó con una introducción a XP (eXtreme Programming). Empezamos hablando de la importancia del Good Naming y lo importante que es evitar sorpresas. Ya que es si llamo a un método se llama “add” no espero que sume y luego divida. Se habló de los valores de XP (comunicación, simplicidad, feedback, respeto y coraje) y cómo mediante un conjunto de prácticas (Pair programming, Test Driven Development y Continuos Integration) alcanzamos esos valores. La verdad que en general para mí el curso ha sido más que un training de TDD.

BABY STEPS

Todos los asistentes nos dimos cuenta de lo importante que es no sólo el saber por dónde empezar sino el saber avanzar poco a poco, dando pequeños y sencillos pasos que te impidan complicar la solución ya que tu preocupación principal es pasar el test actual. Probablemente el TDD está basado en este punto. Si quieres aplicar TDD y sacarle todo su potencial, el primer paso es interiorizar este principio. La mayor parte de los puntos que trataré a continuación si no todos, me ayudarán interiorizar este principio, ya que considero que todos ellos reflejan claramente a lo que nos referimos con Baby Steps.

PRIMER PASO: TODO LIST

Cuando íbamos a empezar a desarrollar una nueva funcionalidad en cualquier contexto (proyecto, kata…) mis compañeros y yo empezábamos con nuestro primer test. Muchas veces saber elegir cuál es nuestro primer test es algo complicado y aún más complicado es saber por cuál seguir una vez hayas pasado el primero. Había veces que debíamos pararnos por no tener las cosas claras para poder preguntarnos cuál debería ser el siguiente y notas cómo el avance es bastante irregular.

Esta semana he notado cómo el escribir una lista (to do) al principio de cada clase de tests nos permitía ser más continuos a la hora de desarrollar una funcionalidad porque teníamos claro por donde seguir. Cuando te planteas escribir esta lista no solo te estás planteando que tests escribir, estás estudiando y escribiendo las reglas del negocio, asegurándote que como desarrollador has entendido que debe hacer la nueva funcionalidad. La lista debería empezar con la descripción de una serie de comportamientos en diversas situaciones que es lo que representa a la funcionalidad en sí.

Además esta lista también podemos acompañarla de ejemplos que reflejen qué respuesta debe dar nuestro sistema para un determinado input, estos ejemplos podríamos ordenarlos por complejidad evaluándolo con nuestro compañero y posteriormente basar nuestros tests en ellos. Un ejemplo de nuestra to do list podría ser:

1
2
3
4
5
6
7
8
9
/** TODO:
* Una contraseña debe tener al menos un número
* Una contraseña no puede contener caracteres especiales
*
* Ejemplos:
* mi2contraseña ==> válida
* micontraseña ==> no válida (falta un número)
* mi*2contraseña ==> no válida (contiene caracteres especial)
*/

Podría parecer que esto es una pérdida de tiempo pero en mi opinión el emplear nuestro tiempo en entender el dominio del problema y en organizarnos no puede considerarse tiempo perdido ya que nos está ahorrando futuras dificultades. Gracias a esto también tendremos tests mucho más expresivos, claros y representativos del dominio, además de ser muy acertados y por lo tanto nos permite tomar el camino más simple a la hora de escribir código en producción e incrementando notoriamente la calidad y la simplicidad de nuestro software.

ESCRIBIR TESTS QUE SOLO FALLAN POR UNA RAZÓN

Esto nos permite centrarnos mejor en la regla que estamos cubriendo y además permitirnos pasar el test más sencillamente. Pero no sólo se trata de una ventaja para mí en el momento que estoy desarrollando, esto se trata de mantener los tests sencillos y claros. Cuando otro compañero por cualquier motivo necesite o quiera entender cómo funciona lo que hemos añadido podrá ir a nuestros tests para aprender o asegurarse de que entiende el comportamiento esperado de esa parte del sistema. Un ejemplo de tener tests que sólo fallan por incumplir tan sólo una regla son los ejemplos de la lista del punto anterior.

KEEP IT SIMPLE

Este va sobre simplicidad, es indudable que mantener nuestro software lo más simple posible es una ventaja para todo el equipo. Un claro ejemplo del uso de la simplicidad es que debemos escribir el código mínimo para obtener el verde de un test. Gracias a esto evitamos soluciones complejas y garantizamos que nuestro software hace lo que tiene que hacer, lo que el cliente ha pedido.

Para garantizar que estamos resolviendo el problema de manera simple podemos usar la regla de los 30 segundos la cual explica que si pasar un test te lleva más de 30 segundos probablemente estés intentando pasar el test equivocado. Deberías volver unos pasos atrás y enfocarlo desde otro ángulo. Esta regla es flexible si estamos ante un problema algorítmico complejo para el cuál podrías aumentar el tiempo hasta unos 5 minutos.

Pero en mi opinión el término simple va mucho más allá de solucionar un determinado problema de manera sencilla sino que también sobre que a un compañero le sea sencillo entender tu aportación.

Para ello debemos mantener nuestro código simple pero no sólo hablamos de nuestro código de producción sino que debemos mantener también nuestros tests lo más simples posible. Con esto conseguimos que cuando un miembro del equipo lea un test, pueda entender fácilmente la regla de negocio que este cubre. No hacer más asserts de los necesarios y no escribir un test con datos que realmente son inútiles para el contexto de ese test concreto son prácticas que podemos adoptar para mantener nuestros tests simples.

En mi opinión aplicar buenas prácticas como seguir los principios SOLID, preocuparse por la calidad, legibilidad y limpieza del código y, cómo no, aplicar las 4 reglas del diseño simple son también esenciales para que el equipo pueda seguir desarrollando y entendiendo nuestro software simplemente, esto también es simplicidad.

CONCLUSIÓN

A la hora de hacer TDD es muy importante entender perfectamente qué es lo que estamos haciendo. Esto nos permitirá tomar buenas decisiones con respecto al camino a seguir para llegar a aportar valor de una manera simple y continua. Mediante pasos pequeños conseguimos simplicidad de la cual el equipo se beneficia constantemente permitiendo que aumente la fluidez de trabajo.