Cómo Juanito se convenció y acabó usando TDD

by , under Technical practices

FacebooktwitterlinkedinmailFacebooktwitterlinkedinmail
Juanito era un desarrollador de software bastante bueno. Toda su vida había desarrollado siguiendo la vieja escuela. Había empezado a programar de joven, había sacado su carrera con buenas notas, llevaba acumulados varios años de experiencia y, en general, el código que hacía era de una calidad bastante decente. Nunca había tenido demasiados problemas con las fechas de entrega y tampoco lo que entregaba fallaba demasiado. El pensaba que era un buen programador y que el TDD era una cosa exótica que, podía estar muy bien, pero tampoco era estrictamente necesaria. Al fin y al cabo, Windows se hizo sin TDD, el mainframe se programo sin TDD, y la lanzadera espacial, y las bases de datos, y el TCP/IP, y…

Un día en su trabajo, con su código que funcionaba bien, estaba desacoplado, tenía bien repartidas las responsabilidades, incluso se basaba fuertemente en interfaces, decidió probar a hacer un test. Lo programó para probar el modulo de más bajo nivel que tenía y lo ejecutó. Le gustó. Decidió que en ratos iría escribiendo más tests que le permitiesen probar todos sus modulos (al fin y al cabo para eso vale el TDD, ¿no?, para probar…) Y los escribió y los ejecutó, y estaba contento.

Pero un buen día, llegó el cambio: había que cambiar algunas especificaciones de la capa para la que había hecho tests para adaptarla a otra plataforma de ejecución. Juanito empezó a cambiar el comportamiento de una clase y los tests de todas sus clases empezaron a fallar. Los ajustó como pudo y siguió cambiando. Y los tests siguieron fallando y Juanito ajustando. Y al final, Juanito se hartó, acabó hasta el gorro, y borró los tests: le quitaban más tiempo de lo que le aportaban. El ya sabia que su código funcionaba al implementar los primeros tests y ahora que lo iba a cambiar un poco resulta que tenía que tirar todos los tests y volverlos a hacer de nuevo. Por cada funcionalidad cambiada le tocaba alterar la clase que la implementaba y la totalidad de los tests. “Pues vaya una ayuda”, pensó.

Asi que Juanito se quedó pensando en que realmente la gente dice que hace TDD por seguir la moda, pero que es imposible hacer tests con mucha cobertura y que, de todas formas, quienes los hacen, pierden eficiencia. Era más rápido seguir desarrollando bien a la vieja usanza, aprendiendo más y poniendo cuidado. Al fin y al cabo a él le había funcionado siempre.

Juanito no estaba solo, tenía compañeros en el trabajo que también programaban a la vieja usanza. Algunos bien, otros mal, y otros de pena. A los que peor lo hacían les iba realmente mal y todo les fallaba mucho y entregaban muy tarde. Juanito pensaba que se tenían que formar más y ganar más experiencia y poner más cuidado. Además, cuando pensaba en su experiencia con TDD, se decía a si mismo que estos compañeros, si no eran capaces de programar bien el código de producción, ¿cómo iban a ser capaces de programar bien los tests? Si se ponían a hacer tests entonces tendrían dos veces más código que mantener y ya tenían bastante con lo de producción como para ponerse a mantener también los tests. Así que Juanito descartó el TDD.

Pero Juanito era un tío inquieto y tenía algunos amigos que le seguían dando la brasa con el TDD para arriba, el TDD para abajo. Así que, meses más tarde, decidió darle otra oportunidad. Se leyó un libro, volvió a probar, y aquello no había por donde cogerlo. El escribía código para probar sus programas pero seguía en las mismas: lo escribía después de saber que funcionaba y cuando lo cambiaba tenía que rehacer los tests. Nuevamente no le convenció pero esta vez no tiró la toalla y siguió indagando. Un amigo suyo daba cursos y hablaba de TDD. Se apuntó y fue.

Para cuando llego al curso, Juanito ya controlaba todo el tema de inyección de dependencias, mocks, y además, desde hacía mucho, ya usaba varios patrones para desacoplar sus clases. Le gustaba especialmente lo de inyectar las dependencias, porque le permitía hacerlas explícitas y le ayudaba a entender su código. Lo usaba incluso para hacer sus tests, pero la mayor parte de las veces le causaba mas inconveniente que ventaja puesto que para armar el test seguía teniendo el problema de formar todo el grafo de objetos a mano.

Empezó el curso y en él se hizo un taller de TDD. Todo avanzaba según lo esperado por Juanito: su amigo propuso desarrollar una clase con TDD y luego otra que se basaba en la primera, también con TDD. Fue curioso pero Juanito siguió pensando que él lo hubiese podido hacer también sin TDD y hubiese tardado lo mismo. Hasta que su amigo, el profesor, dijo: “cambiar ahora la primera clase para que haga Y en vez de X”. Juanito y los demás lo hicieron: cambiaron el test de la primera clase y donde decía X pusieron Y, cambiaron el código de la clase y el test pasó. Guay. Entonces el profesor dijo: ejecutad ahora el test de la segunda clase. “¡Ups! ha petado”, dijo Juanito. Y pensó: “lo mismo que me pasa en el trabajo, esto confirma definitivamente que TDD es una autentica castaña”.

Y cuando ya parecía todo perdido su amigo, el profesor, dijo: “¿Y por qué ha fallado ese test? ¿No se supone que era un test unitario? No habéis tocado nada en la segunda clase y se ha roto el test. Eso es porque vuestro test, en realidad no era unitario, sino de integración (o componentes, como prefirais llamarlo) y está testando más de una clase a la vez”.

En ese momento un haz de fotones actuando como partículas cayó sobre Juanito. Luego otro haz de fotones actuando como ondas. Y luego su visión se nubló, alcanzo el nirvana por unos segundos, y volvió a la Tierra: “¡Seré idiota! ¡Ese era el problema!”.

Y así fue como Juanito se convenció y acabo usando TDD y dando la brasa a todo el que podía para que se convirtiese. Sin embargo a Juanito siempre le quedó el poso amargo de que, a pesar de haber indagado en el TDD, haber leído libros, haber hablado con gente que lo usaba, nadie le hubiese dicho nunca las dos cosas que, para él, eran fundamentales en TDD:

  1. Que TDD no es solo una herramienta de testing sino una ayuda muy potente para hacer el diseño. Que si tus clases no son testables no es porque TDD sea difícil de implementar, es porque tus clases están mal. Y aunque a todo el mundo le parezcan bien y estén diseñadas muchísimo mejor que la media, el hecho de que una clase sea testable es un escalón más en la perfección del diseño. Es la única forma de pasar del notable al sobresaliente. Y no se puede pasar sin hacer TDD por mucho que se mejore como programador, porque TDD impone “limites fisicos” al diseño, mientras que la maestría en el diseño sin TDD es solo mental y, por lo tanto, falible.
  2. Que en TDD no se prueba el sistema, se prueban las clases aisladas, unitariamente. Y que esto es muy importante para no acabar haciendo tests de integración sin darse cuenta y que los tests se conviertan en mas código que mantener, además del de producción.

Fin.

Moraleja

Por favor, cuando contéis lo que es TDD haced hincapié en estos dos puntos. No digáis que TDD es (sólo) para probar. Decid que es una herramienta para ponernos limites y así no poder hacer diseños desastrosos con clases que ni siquiera se pueden sacar de su ecosistema y, por lo tanto, nunca se podrán reutilizar. Mejor eso que decir que son tests. Cuando la gente piensa en tests piensa en un señor sentado delante de la interfaz de usuario probando lo mismo cientos de veces. Y eso no mola. Pero saber diseñar bien y ser arquitecto “de la muerte” sí.

Y cuando ya se pongan a ello, decidles que es muy importante no hacer tests de varias clases a la vez, sino de una en una. Si empiezan a juntar muchas capas al final acabaran como el señor sentado delante de la interfaz de usuario probando lo mismo cientos de veces.

Gracias majos.

  1. Ricardo Muñoz

    Gracias viejo.
    No lo he probado por lo mismo que Juanito renunció, en 1ra y 2da instancia.
    veremos como mola al cambiar el pensamiento al igual que Don Juan

    Reply

Leave a Reply