Evelb

TDD es una técnica Jedi de diseño de software emergente; hacer test primero es TFD

TDD es una técnica Jedi de diseño de software emergente; hacer test primero es TFD
Darío Beiró

Hoy comenzamos una serie de entradas sobre TDD (test-driven development), valores y prácticas que la rodean. Algunas entradas serán más técnicas y otras serán más filosóficas, pero en general intentaremos transmitiros nuestra experiencia: nuestros aciertos y errores como equipo que inicialmente no practicaba este tipo de técnicas de XP (extreme programming)

Hace ya un tiempo que decidimos apostar por TDD como metodología de desarrollo de nuestro software, tanto en los nuevos proyectos como en los ya existentes. Ha sido y es un camino muy enriquecedor, que creo nos ha aportado y aporta muchísimo valor al equipo y a nuestros desarrollos, lo que se traduce también en valor para nuestros clientes. Por supuesto, las dificultades no han sido pocas, pero eso lo trataremos en entradas futuras con más detalle 🙂

 

TDD no es hacer el test primero

A título personal, me encuentro muchas veces con que TDD es visto como hacer primero los test y luego el código de producción. Hoy me gustaría centrar este texto en torno a esta afirmación que cuando menos es incompleta, o directamente errónea.

El problema es la idea que subyace, el concepto de que lo importante son los test, cuando realmente los test son solo un medio (y muy potente) para un fin mayor. Si hacemos TDD con el foco solamente en los test primero, acabaremos con un amplio conjunto de test en verde y un software de baja calidad que “funciona” pero que seguramente tenga poco recorrido, o tenga cierto recorrido a costa de ir llenando la mochila de la deuda técnica, conocida por su efecto demoledor en la espalda del buen programador, por no hablar de costes. Será en ese punto cuando abandonaremos TDD frustrados y con la idea de que es una técnica poco útil.

Este enfoque realmente recuerda más a TFD (test-first development) , concepto del que habla Kent Beck en su libro extreme programming explained por el cual un desarrollador no debería escribir una sola línea de código sin antes haber hecho un test que la pruebe, garantizando que esa unidad de trabajo es correcta técnicamente. Por supuesto, es una técnica útil y válida, pero no es TDD.

 

Los test son un medio para garantizar la calidad

La clave de todo esto es ser conscientes de que la calidad no reside en el número de test que tenga un producto, la calidad reside principalmente en un buen diseño, con todo lo que ello implica; y requiere. Ese es precisamente el fin mayor de TDD, usar los test como un medio para guiar el diseño de un modo ágil, manteniendo la simplicidad y garantizando que en el proceso de desarrollo no rompemos nada de lo hecho hasta el momento. Por supuesto es bueno pensar en hacer primero los test, nos permite hacer un desarrollo más simple, cambiar nuestro “mindset” y enfocarnos a desarrollar código para que pase el test, pero no podemos quedarnos ahí.

Repasemos el proceso de desarrollo con TDD para ver exactamente dónde deberíamos poner mayor énfasis.

 

Rojo, Verde, Refactor

Comenzamos escribiendo un test y buscando el rojo, es decir, buscamos que falle. Sobre qué test escribir primero: hay muchos enfoques, a mi personalmente me resulta más sencillo seguir el enfoque de afuera a dentro y empezar por las partes más externas (Outside-in) pero algunos de mis compañeros de equipo prefieren lo contrario (Inside-out); esto no debe ser un problema. Empezamos por el test de la unidad que nos resulte más sencillo de ver (función, clase, componente…) y buscamos el rojo porque queremos garantizar que lo que vamos a probar no está ya implementado y que nuestro test es en sí mismo correcto. Ojo, buscar el rojo significa hacer que el test falle, debe por tanto compilar y ejecutarse.

Una vez conseguido el rojo, programamos el código mínimo de producción para que el test pase de rojo a verde. Es muy importante hacer solo el código mínimo para garantizar la simplicidad del proceso y no dejarnos tentar por las ganas de escribir el código completo, aún por claro que parezca, pues contaminaremos nuestros test y eso es realmente peligroso. Más allá del hecho de estar construyendo (y manteniendo) un diseño que no sabemos si vamos a necesitar, podríamos caer en hacer test que, de forma involuntaria, sabemos que van a pasar, ya que de forma inconsciente estamos contaminados por el desarrollo previo. Una vez hecho el código mínimo y con el test en verde, pasamos al último paso, el gran olvidado: refactor.

 

La clave radica en refactorizar

Probablemente este sea uno de los pasos más importantes y lo que convierte a TDD en TDD y no meramente TFD (test-first development). Consiste en replantear nuestra solución y ver si es posible hacer modificaciones que, sin cambiar la funcionalidad, hagan el código más claro, mantenible, y robusto; limpio en definitiva. Es importante tener presente que el refactor no debe ceñirse solamente al código de producción, también es muy interesante que analicemos nuestro código de test, ya que por experiencia es fácil que queden bastante enmarañados si no los tratamos con mimo. A veces, simplemente con extraer un par de constantes y extraer un par de funciones ganamos muchísimo en términos de calidad, otras tendremos que hacer refactorizaciones más ambiciosas. 

Nuestro consejo aquí es hacer commit antes, justo antes de empezar la refactorización. El motivo no es miedo a perder comportamiento, puesto que tenemos los test para garantizar que la funcionalidad se mantiene y el código se comporta como esperamos. El motivo es garantizar que si un punto determinado queremos volver atrás, podemos hacerlo con seguridad y agilidad tirando de revert.

 

Definimos las piezas del puzzle y cómo encajarlas

A la hora de refactorizar para mejorar nuestro diseño, es importante también que reflexionemos, ya desde el primer test, en nuestra arquitectura y en cómo vamos ir dándole forma con los test. Piensa que cada vez que escribimos un test, estamos tomando decisiones de diseño muy importantes: nombres de clases y funciones, valores de retorno, argumentos, paquetes, clases… Realmente estamos definiendo todas las piezas del puzzle y cómo encajarlas.

Si te quedas sin ideas a la hora de hacer refactor, ayuda tener presente alguna lista de code smells, que nos faciliten el identificar puntos. Para esto recomiendo también la lectura Refactoring de Martin Fowler. Es posible que haya momentos en los que no veamos obvio que refactorizar, pero es importante hacer este ejercicio de introspección con nuestro código y ser autocríticos. Nosotros cuando llegamos a un punto concreto donde no vemos claro por donde avanzar o que refactorizar nos juntamos brevemente enfrente de la pantalla e intentamos discutirlo. Esto siempre es buena idea, ya que el código es colectivo y como tal debemos apoyarnos en las personas que lo sustentan.

 

Larga vida a TDD

Esta es la magia de TDD, con el planteamiento del test y la búsqueda del rojo tomamos las decisiones de diseño oportunas, garantizamos que eso funciona desarrollando lo mínimo para conseguir el verde y volvemos sobre esa ideas iniciales en la fase de refactor, las volvemos a evaluar y las mejoramos, manteniendo el verde, de forma iterativa y meditándolas a medida que nuestro software madura de la mano de nuestros test.

Recuerda, cuando hacemos TDD lo que hacemos es guiar nuestro diseño mediante test, no simplemente hacer primero los test.

Si quieres entrar en detalle o tienes interés por TDD, prácticas y valores de XP te recomiendo leer los libros de Kent Beck, Test-Driven Development by Example y Diseño Ágil con TDD de Carlos Blé. Ambas personas y profesionales de referencia. No dejes tampoco de leer el libro de Martin Fowler sobre Refactoring.

Finalmente, ¡te animo a que compartas tu experiencia con nosotros!

 

2 opiniones sobre “TDD es una técnica Jedi de diseño de software emergente; hacer test primero es TFD

  1. Me ha encantado lo bien que está explicada la diferencia entre TFD y TDD, lo claro y conciso que es el artículo explicando está gran técnica de desarrollo. Muchísimas gracias por la mención a mi libro 🙂

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *