¿Por qué el TDD te ayuda a vivir más tranquilo?

¿Por qué el TDD te ayuda a vivir más tranquilo?

It's not only about software, it's also about code

A menudo escucho a compañeros de trabajo, ingenieros, como yo, decir que hacer tests unitarios es innecesario e implica más trabajo. Argumentan que ya tienen suficiente con implementar la funcionalidad que se les pide como para encima tener que perder el tiempo implementando tests unitarios; y lo justifican diciendo que mantener el código de producción ya es suficientemente costoso como para tener que mantener el código de test; o que cuando el código es “demasiado simple” no es necesario testearlo. Además, sostienen que con los tests de integración y de end-to-end ya es suficiente para asegurar que el software cumple con las especificaciones, afirmando que es de calidad sólo porque funciona como se espera.

La verdad, es que estoy en total desacuerdo con los que piensan que los tests unitarios no son necesarios. Lo estoy, porque hablan del código de producción y del código de test como si no formaran parte del mismo proyecto, como si tuvieran vidas paralelas. Para mi, ambos contribuyen por igual al éxito del desarrollo y se deben regir por los mismos principios de diseño. También estoy en desacuerdo, porque considero que asegurar con tests unitarios que el código funciona según la especificación antes de introducirlo en una release, permite identificar errores antes de que se inicie el ciclo de validación, lo cual contribuye a disminuir el tiempo de desarrollo.

Asumiendo entonces que se van a escribir tests unitarios, la cuestión es si hay que hacerlo antes o después de escribir el código de producción. Para mí es más productivo hacer primero los tests y después el código de producción, y al decirlo es cuando a algunos ingenieros, como diría mi buen amigo Carmelo, «les explota la cabeza».

En un post anterior, comenté que con demasiada frecuencia, los ingenieros nos vemos obligados a desarrollar el software demasiado rápido. Esto provoca que no dediquemos suficiente tiempo ni para entender el problema ni para pensar en cómo resolverlo de la mejor manera posible, sobre todo si lo que tenemos que hacer es modificar código ya existente. Pensar en la solución del problema es difícil, y requiere necesariamente de un tiempo y un esfuerzo que no se deben evitar.

El TDD (Test Driven Development), la metodología que permite escribir el código de test antes que el código de producción, adquiere su mayor relevancia en este contexto, ya que fuerza a pensar en la solución del problema (y esto hay que hacerlo de todas maneras). ¿Y por qué? Pues por los siguientes tres motivos:

  • porque cuando se define un test unitario, se está pensando en cómo especificar el comportamiento del software
  • porque cuando se implementa un test que pasa, se está pensando en cómo implementar la especificación
  • y porque cuando se refactoriza el código, tanto el de producción como el de test, se está pensando en cómo mejorar su calidad y facilitar su mantenimiento

En base a esto, seguir el ciclo definido en el TDD tiene las siguientes ventajas:

  • Asegura que el software cumple con la especificación.
  • Guía para encontrar la mejor solución.
  • Permite obtener el diseño de manera natural.
  • Ayuda a obtener código de calidad.
    • Ayuda a definir correctamente las responsabilidades, las dependencias y la usabilidad de los componentes.
    • Ayuda a definir los casos de uso de los componentes, para evitar sobreingeniería y tener cubierta la funcionalidad que interesa.

Escribir los tests después, sí que es un overhead, porque el proceso de pensar en el problema ya se ha hecho al hacer la implementación. Además, cuando los tests se escriben después, se suelen usar sólo para validar la funcionalidad, y aunque está bien, no es suficiente, ya que también hay que aprovecharlos para mejorar el código. En este sentido, la metodología TDD asegura que se logren ambos objetivos.

Los managers sueñan con que sus ingenieros implementen código de calidad que funcione y que escale. El paradigma moderno es cumplir con la declaración «Clean Code That Works«. Ya hablaré de «Clean Code» en otros posts. Lo que quiero resaltar en este, es que a mí, como a muchos, nos enseñaron que primero hay que hacer «Clean Code» y después hay que hacer que funcione. Por eso, la mayoría de productores de software, se esmeran en imaginar cómo debería ser el software y dibujan un montón de bonitos diagramas UML que definen su comportamiento. Se esmeran en hacer el Diseño del Software antes incluso de escribir una sola línea de código. Entonces, cuando ya han dibujado todas las cajitas y líneas, las reescriben en forma de código. Y cuando terminan, se dan cuenta, de que quizás no habían pensado lo suficiente, y rehacen los diagramas para que reflejen el código escrito. Y siguen avanzando en este bucle hasta que terminan la implementación.

A mi este proceso me parece sumamente ineficiente e improductivo. Por eso me cambié al TDD. El paradigma del TDD es justamente hacerlo al revés. Primero, a través de los tests, fuerza a pensar y a hacer código que funcione; y después permite refactorizarlo para convertirlo en «Clean Code«, con la ventaja que los tests, al estar ya escritos, garantizan que el refactor no cambia el comportamiento. Al final del proceso, encima, se obtiene un diseño que se puede dibujar, una sola vez, mediante diagramas UML.

Pasarse al TDD implica cambiar la manera de enfocar el diseño y desarrollo de software. Al principio cuesta, porque cambiar dinámicas siempre es difícil, pero cuando has interiorizado la metodología, te das cuenta de las ventajas que tiene. Para mí, la más importante, es la tranquilidad que da saber que hay una batería de tests en verde que garantizan que el código de producción cumple con la especificación definida hasta el momento.

¿Te animas a iniciar el camino?

Tanto si eres estudiante o profesional, y necesitas ampliar tus conocimientos de programación y diseño de software orientado a objetos.

Deja una respuesta

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