TDD: Mentirosos el ciclo no es Red – Green -Refactor

Nos han engañado estos del TDD, son unos malditos mentirosos, el verdadero ciclo es:

Think - Red - Green - Refactor

Y no te lo dicen, aunque para algunos iluminados sea algo implícito, el primer paso es pensar (Think) el algoritmo/lógica que quieres implementar, y es ese primer paso el que siempre me saltaba. Soy una persona visceral y suelo actuar por impulsos, y a la hora de programar ... pues me pasa un poco que me dejo llevar.

Por eso voy a desglosaros cómo veo yo el ciclo de TDD:

Think

  1. Piensa y reflexiona la lógica que tienes que implementar.
  2. Identifica las diferentes responsabilidades que hay
  3. Por cada responsabilidad habrá una clase. (¡Quieto!, aparta las manos del teclado, no es el momento de escribir las clases. Dibújalas en un PDA (Papel de Apuntar))
  4. Elige un buen nombre para cada una de ellas. Nombres descriptivos, limpios, claros, afeitaditos. Evita las terminaciones de LoQueSeaObject, LoQueSeaManajer, etc... Si no dice nada sobre la funcionalidad de la clase quítalo. Si aún así estás tentado a ponerlo, es que esa clase hace más de una cosa (Principio KISS), así que vuelve al paso 1.
  5. En el PDA dibuja las relaciones entre las diferentes clases

Foreach (responsabilidad in PDA)

  • Crea una clase de Test por cada una (ejemplo: responsabilidad1Test)
  • Y ahora sí, en cada clase de test haz todos los Red - Green - Refactor necesarios para probar la funcionalidad que la clase testeada debe tener.

Mis conclusiones

Escribe tu código como si un asesino esquizofrénico que tiene tu dirección fuese a mantenerlo

Esta es una frase muy conocida en el mundo Agile, no recuerdo si era exactamente así, pero lo que viene a resumir es que al final pasamos más tiempo leyendo, debugeando y manteniendo código que escribiéndolo. Por eso es muy importante pensar muy bien el nombre que les vamos a dar a las clases, variables, métodos, propiedades, etc. En definitiva haz lo que sea necesario para que tu código sea legible.

La formación no es importante, es IMPRESCINDIBLE

Aprender la teoría está bien, pero si viene acompañada de una práctica con alguien que te guíe te va a ayudar mucho más, sí, es algo obvio, pero que no se suele hacer.

Las herramientas de refactoring son nuestras amigas

Sólo hablo del "generate method" y "generate class" de Visual Studio, no me han hecho falta más. Cuando empiezas a escribir el test, y haciendo clic derecho y buscar esa opción en el desplegable nos permite crear rápidamente las clases y métodos que nos vayan haciendo falta, pero no te olvides del asesino esquizofrénico.

El Nirvana del TDD

El Nirvana del TDD es no tener que debugear para detectar un bug, sólo crear un test que lo reproduzca y corregirlo. Si consigues llegar a este punto ya eres un TDD Master.

¿Cómo ampliarías este post?

8 pensamientos en “TDD: Mentirosos el ciclo no es Red – Green -Refactor

  1. Vicenç García-Altés (@vgaltes)

    Muy buenas,

    obviamente siempre tenemos que pensar, pero creo que no hay que hacerlo tanto. De echo, una de las gracias de TDD es que te hace pensar menos 🙂 Lo que tu estas describiendo no deja de ser un BUD (Big Upfront Design) disfrazado de TDD. No creo que al empezar a escribir un algoritmo, debamos pensar en como serán todas nuestras clases, responsabilidades, etc. De echo, haciendo TDD, sobretodo en el paso de refactoring, es donde analizamos si es necesario extraer clases de nuestro código actual, inyectar algo como dependencia, etc. Es allí donde evaluamos los principios SOLID y actuamos en consecuencia.

    Por lo que comentas en el artículo, parece que haces TDD bottom-up. A mi lo que me va mejor es hacer primero una pasada up-bottom (centrándome en comportamiento) y después si que hacer bottom-up en las clases que van saliendo.

    El camino para hacer TDD es duro. Yo llevo varios años en ello y estoy seguro que estoy lejos de hacerlo bien.

    Gracias por el post!

    1. juanlao Autor

      ¡Gracias por el comentario!
      Me has hecho repensar el post de nuevo. La idea de pensar menos con TDD es atractiva, pero creo que habria que matizarla. Con la practica necesaria, se que los tests, el código y la arquitectura del sistema va fluyendo casi sin pensar, pero mientras se llega a ese “nirvana” hay que estrujarse el cerebro un poco.

      Cuando digo que hay que pensar un poco, no me refiero a tener en la cabeza todas las relaciones y clases como en un BUD, sino que, una vez que sabemos cuál es la funcionalidad a implementar, identificar las responsabilidades de lo que vamos a hacer, aplicar TDD sobre esas responsabilidades de manera independiente. Obviamente puede ocurrir que cuando nos ponemos con las manos en la masa, aparecen nuevas responsabilidades que antes no veíamos, las moqueamos y listo. Después tendremos que repetir el proceso para esas nuevas responsabilidades. Pero más en un sentido de desarrollo iterativo e incremental, no en el sentido BUD que he entendido en tu comentario.
      Espero que no suene ha “ya se están hablando del sexo de los ángeles”.

      Firmado: un TDDero que busca es el camino del TDDNirvana

  2. Abel

    Mmm ( de buen rollito, que todos andamos aprendiendo…).

    No, claro que no.

    La fase de pensar, de encontrar el diseño de tu aplicación (clases; relaciones; nombres de clases, metodos, …) no viene al principio de Red-Green-Refactor sino que, en realidad, es Refactor: una vez que tus tests demuestran que el pequeño cambio que has introducido funciona, es el momento de buscar duplicidades, de cambiar nombres, de ajustar responsabilidades, de encontrar las siguientes pruebas que quieres hacer a tu código.

    Si de antemano ya sabes cual es tu diseño, que clases vas a implementar, responsabilidades de cada una y demás, tus tests no están dirigiendo tu diseño, sólo están probando que hacen lo que piensas que deben hacer…

    Con ese titulo, pensé que nos ibas a recordar que en realidad en TDD hay 4 fases: Red-Green-Refactoring-Test refactoring, que los tests también son código de producción (aunque no los despliegues) y hay mantenerlos: borrar los que ya no necesites, evitar duplicidades, cambiar nombres, … :-).

    s2,
    Abel

    1. juanlao Autor

      ¡Gracias Abel!
      ¡El buen rollito se presupone!
      Creo que voy a actualizar un poco el post. Y es que, cuando ya se lleva un tiempo aplicando TDD ¿Esta mal aprovechar la experiencia adquirida?
      Me refiero a que ante una funcionalidad a implementar, después de un tiempo aplicando TDD, las diferentes responsabilidades que hay, van resultando mas fáciles de ver, ¿No es una buena práctica pensar un poco antes en la funcionalidad, identificar las responsabilidades y aplicar TDD a esas responsabilidades?
      Si no es así, ¿Qué diferencia hay entre un tddero que lo lleva haciendo mucho tiempo y otro que acaba de empezar?
      Entiendo que esa experiencia es la que permite escribir mejores test, cosa que no es fácil y que solo da la practica, lo que pasa es que entiendo que con la practica se llega a eso, o al menos esa es la conclusión a la que yo he llegado después de aplicar TDD durante algún tiempo.
      Gracias de nuevo, y si ves que me estoy equivocando, ¿Como podria mejorar?

  3. javito

    Llevo muchos años aplicando tdd y, si bien es verdad que el refactoring es la herramienta mas importante para mantener un buen código, también es verdad que antes de afrontar una tarea compleja es recomendable tirar de lápiz y papel. Por desgracia, cada vez veo más programadores que no son capaces de representar bien de forma gráfica su diseño.

    Todo con mesura, soy partidario de no pasar demasiado tiempo pensando nombres y relaciones, porque al final se descubren solos, pero tampoco hay que ir a lo loco…

    A tener en cuenta también la vida real. La teoría esta muy bien, pero el día a día del programador es complicado y en muchas ocasiones no existe la posibilidad del refactoring.

    Esto, como todo en la vida, se va entrenando, aprendiendo y automatizando.

    En fin, que es verdad todo lo que comentáis, pero la teoría hay que adaptarla a cada situación concreta.

  4. juanlao Autor

    A eso me refería, que antes de empezar el ciclo Red-Green-Refactor, no es aconsejable ir a lo loco, hay que pensar un poco. Lo que me refiero con el post es que eso no te lo dicen, es decir, parece que basta con el Red-Green-Refactro, y ya está, vamos a la guerra.
    Sólo digo que estaría bien que avisasen un poco, en plan: “Ehh, ojito con el lado oscuro del TDD, que te vas a ostiar”, piensa un poco antes de escribir código, que luego lo tienes que mantener, y como no tengas tiempo para el refactor vas a tener miedo, y el miedo lleva a la ira, la ira lleva al sufrimiento y el sufrimiento… a maldecir SharePoint!
    😉
    !Gracias Javito por el comentario¡

  5. Javier J.

    Juan, me sorprende mucho esta entrada. ¿De verdad es necesario indicar que hay que “pensar”? ¿Cómos ería tu trabajo i no aplicaras TDD? ¿ya no tendrías que “pensar”?

    TDD es una herramienta para escribir y organizar el código, pero no va a hacer que todo salga solo y sin esfuerzo. Por ejemplo, sigues necesitando requisitos (casos de uso, historias de usuario, etc.), vas a necesitar pensar cómo vas organizar tu solución (módulos o capas, comunicaciones entre ellos, etc.)

    También vas a seguir teniendo que pensar en nombres de clases, métodos, etc. Lo que TDD te dice es que pongas estas ideas sobre el código, a trabajar lo antes posible y a obtener feedback de si funcionan o no.

    TDD funciona mejor en ciclos rápidos, en los que estás pocos minutos programando y pocos minutos ejecutado pruebas. TDD también te dirige a escribir el código más sencillo posible y a “falsificar” aquello que sea más complejo para implementarlo en un futuro. Esto yo lo interpreto como que, al aplicar TDD solo puedes pensar ene l código que estás escribiendo, por lo que cualquier otra tarea que requiera una reflexión más profunda debe darse antes o después de varios ciclos de TDD, no durante.

    Dos ejemplos de lo anterior serían, parar y hacer grandes refactorizaciones en los que implementas y mejoras patrones de diseño y arquitectura en tu código y elaborar una lista de feautres, o lista de To-Do (como puedes ver en el libro de TDD de Kent Beck) de lo que quieres implementar.

    Espero que esto te haya servido, un saludo.

  6. Martin Algañaraz

    a mi me funciona siempre hacer ATDD (test de aceptacion) antes de escribir cualquier test funcional o unitario. Primero escribo en un papel que es lo que quiero realizar, luego me enfoco en cada parte del sistema a realizar y voy escribiendo paso a paso en un papel como se realiza (cada uno de esos pasos sera un test de aceptacion), y una vez echo esto simplemente realizo los test unitarios por cada test de aceptacion, a medida que realizo los test unitarios voy agregando los test de aceptacion que me van apareciendo en la mente y escribo los test unitarios para llevarlos a cabo, siempre hay que pensar los test, pero no se trata de escribir pruebas a diestra y siniestra sino de saber que tipo de prueba escribimos y con que objetivo en mente. El sistema al final termina realizandoce casi por si mismo a medida que se van superando los test de aceptacion y unitarios. Ya para concluir realizo algunos test funcionales para ver como trabajan en conjunto las clases y los metodos antes creados con los test unitarios. Hasta ahora esa manera no me ha fallado y me parece la mas logica ya que siempre estas centrado en el sistema que estas haciendo.

Los comentarios están cerrados.