Sobre los resultados inconclusos de los estudios sobre TDD

Practico TDD, enseño TDD e investigo sobre TDD. Hoy 2023 TDD es bastante conocido pero bastante menos practicado. Yo tengo mis propias sospechas pero recientemente me he encontrado con dos posibles explicaciones adicionales. En este sentido quiero referirme aquí al trabajo de Ghafari y colegas.

Comienzo explicando el contexto: si buscamos estudios sobre los beneficios de TDD vamos a encontrar evidencia no concluyente, o sea: encontraremos algunos estudios que a partir de experimentos aseveran ciertos beneficios de TDD al mismo tiempo que otros estudios hablan de limitaciones o incluso que la técnica no goza de ciertos beneficios. Ejemplo: algunos estudios indican que TDD mejora la calidad del código pero al mismo tiempo empeora la productividad. Otros estudios dicen que TDD no tiene impacto en la calidad e incluso algún otro habla de que tampoco impacta en la productividad.

A partir de esto, Ghafari y compañía, en su trabajo «Why Research on Test-Driven Development is Inconclusive?«, se propusieron estudiar la razón de estos resultados inconclusos. Para esto analizaron diversos estudios existentes sobre TDD y básicamente identificaron 5 factores:

  1. Definición de TDD: según indican, en los distintos estudios que analizaron se utilizan diferentes definiciones de TDD. Esto en lo personal me resultó muy raro, al menos en el sentido que los autores lo indican. Al margen de lo que indican los autores, lo que personalmente me resuena es que en mi propio trabajo de investigación he notado diferentes concepciones de TDD. Hay gente que entiende por TDD puntualmente lo descripto por Beck en su libro Test-Driven Development by Example, lo cual se centra en aplicar TDD a nivel «diseño de clases», muy asociado a prueba «chica» (onda unitaria), mientras que otros toman TDD como una idea más amplia, aplicable a distintos niveles de abstracción como son BDD/ATDD/SBE y más en línea con lo que el propio Beck menciona en su entrevista a Software Engineering Radio.
  2. Selección de los participantes: muchos de los estudios se hacen con estudiantes o con gente de industria que ha recibido una breve capacitación en TDD. Ambas situaciones son al menos discutibles para poder sacar métricas concluyentes. Si queremos llegar al fondo del asunto debemos realizar estudios con gente experimentada en el uso de TDD.
  3. Selección de la tarea: en general los experimentos utilizan ejercicios/tareas que distan mucho en complejidad de lo que uno se encuentra en «escenarios reales»
  4. Tipo de proyecto: la mayoría de los estudios se enfoca en «proyectos nuevos» (green field) cuando en los contextos reales es habitual tener que lidiar con proyectos existentes (brown field)
  5. Comparación: TDD es una práctica de uso en contextos ágiles, con lo cual al hacer estudios comparativos debería comparar el uso de TDD vs. (No-TDD en un contexto ágil), cosa que no siempre es así. Hay estudios en los que se compara el «uso de TDD» vs. «No-TDD en contextos waterfall», los resultados de este tipo de comparación puede deberse tanto al No uso TDD como también al uso de Waterfall. Es fundamental al comparar tener presente el contexto. También resulta relevante considerar distintos escenarios de No-TDD: Test-Last, Iterative Test-Last, No-Test-at-All pues la implicancias de la comparación pueden resultar muy distintas.

En términos generales me parecen bastante razonables estos 5 factores y obviamente los tendré presentes en mi propios trabajos. Para quienes quieran profundizar en esta cuestión les recomiendo leer el artículo completo, es bastante corto y de lectura llevadera.

Nuevo proyecto a la XP: Argenzuela

Hace unas dos semanas comencé a trabajar en un nuevo proyecto. Yo en Argentina y el resto del equipo en Venezuela y de ahí el «Argenzuela», ¡ja!. En el equipo somos 3 Devs, 1 tester, «proxy» Product Owner (que está en el día a día) y un Product Owner con participación más esporádica.

Al margen del (mal) chiste el proyecto consiste en desarrollar la integración de una aplicación con un Sistema CRM (Customer Relationship Management).

En términos de tecnología estamos trabajando con Ruby y RabbitMQ. En términos de infraestructura la aplicación Ruby la corremos dockerizada en Heroku y para el Rabbit usamos el servicio de Amazon. Como herramientas de gestión/desarrollo estamos utilizando el stack de Atlassian: Jira, Confluence y Bitbucket.

Trabajamos «a la XP», iteraciones semanales, TDD, CI/CD, diseño simple, refactoring, mucho pairing y otras yerbas varias.

El proyecto tiene un par de desafíos técnicos y de negocio interesantes pero al margen de eso me gusta la dinámica que equipo que estamos construyendo. Continuará…

Impresiones de la enseñanza de TDD y otras prácticas

El año pasado comenzamos con la práctica de encuestar informalmente a los alumnos sobre las algunas de las prácticas de desarrollo que estudiamos (y aplicamos) en la materia. Concretamente les consultamos con 3 prácticas que estudiamos en la materia, que consideramos muy beneficiosas pero que curiosamente en la industria no tienen un uso masivo (aún): Mob-programming, Trunk-based development y Desarrollo guiado por Pruebas (BDD/TDD).

Explicamos a los alumnos cómo utilizar estas prácticas y las aplicamos en el contexto de un proyecto de desarrollo.

Si bien los alumnos pueden no utilizar estas prácticas (hecha la ley, hecha la trampa) insistimos en las utilicen principalmente con dos argumentos (ya que en general a los alumnos no les basta con que el docente les diga «es por aquí» ¡ja!):

  • Son prácticas que traen importantes beneficios y cuya efectividad está ampliamente probadas
  • A pesar de lo anterior, son prácticas que en la industria no son mainstream y que incluso se las mira con cierta desconfianza en algunos contextos. En la materia les ofrecemos un ambiente seguro para que puedan experimentar con la práctica, contando incluso con la guía del equipo docente. Si prueban estas prácticas en este contexto ¿donde las van a probar? ¿en sus trabajos con la presión de su jefe, los deadlines y el apuro de la industria?

La actividad de encuesta es bastante simple, les presentamos un cuadro de dos ejes y les pedimos que indiquen ahí cómo fue su experiencia utilizando estas prácticas.

Puede resultar curioso para algunos que la la práctica con mejor evaluación es el desarrollo guiado por pruebas. Cabe destacar aquí que al hablar de desarrollo guiado por pruebas me refiero al uso de BDD/TDD, o sea, guiar el desarrollo a partir de especificaciones en forma de ejemplos (pruebas) generados colaborativamente entre usuarios y el equipo de desarrollo.

Test-Driven Development for Embedded C

Ayer terminé de leer este libro. En una palabra: Excelente.

Lo había tenido en radar por mucho tiempo pero recién ahora con el envión de mi trabajo de investigación sobre TDD decidí invertir tiempo en leerlo. El autor del libro es James Grenning, uno de los 17 autores del Agile Manifesto pero lo que puso el libro en mi radar fue la charla de Grenning «TDD Guided by ZOMBIES» en la cual propone una heurística para definir el orden de la secuencia de tests al hacer TDD.

El hecho de que el título del libro haga referencia a Embedded C es en gran medida anecdótico ya que casi todo el contenido es directamente aplicable a cualquier lenguaje o eventualmente fácilmente extrapolable. Es cierto que algunos capítulos están muy centrados en C y en el desarrollo de software embebido, pero varias de las problemáticas relacionadas a la dependencia del hardware son fácilmente extrapolables a las dependencias de infraestructura que uno se encuentra en el desarrollo de aplicaciones de más alto nivel.

Al margen de TDD, creo que el libro resulta muy valioso para gente trabajando en software embebido ya que provee un conjunto de técnicas que sin duda facilitan/aceleran el desarrollo del software embebido. De hecho lo interesante de las técnicas que propone son aplicables a todo desarrollo a bajo nivel, sea o no embebido. Personalmente he trabajado muy poco con software embebido pero sí he hecho desarrollo en C/C++ y de haber sabido las técnicas mencionadas en este libro creo que habría obtenido mejores resultados.

El libro me ha parecido muy completo, explica los fundamentos de TDD, trata con suficiente detalle las cuestiones de tooling para poder automatizar pruebas en C, escribir código modular y hasta implementar mocking en C. También trata cuestiones de patrones, code smells y trabajo con código legacy.

Para mi es 10 puntos, muy recomendado.

Diseño ágil con TDD

Ayer terminé de leer la edición 2020 de este libro escrito por Carlos Blé. Ya había leído (parcialmente) la edición anterior allá por 2011, pero el año pasado Carlos tuvo la gentileza de regalarme esta nueva versión (¡gracias!) y me comentó que tenía modificaciones importantes así que aproveché que estaba estudiando TDD para mi tesis de maestría y decidí leer el libro de punta a punta.

En una oración: el libro me gustó mucho. Sentí mucha afinidad en la forma de trabajo que relata y también en los consejos que el autor ofrece a título personal.

Encontré un punto de contraste interesante con otros libros de TDD. Creo que la mayoría de los libros que he leído sobre TDD (al igual que la mayoría de charlas, cursos y videos sobre TDD que he visto/presenciado) tienen un tono muy extremo, muy «todo o nada», muy «esto es así» (creo que yo mismo muchas veces peco con ese tono) pero este libro (y creo que Carlos en general) tiene un tono «de mesura», un matiz que me resultó muy ameno y que imagino puede resultar mucho más efectivo a la hora de intentar convencer a alguién de utilizar TDD.

Otra cuestión destacable del libro es no se queda en la explicación de la técnica sino que también trata sobre el uso de la técnica en distintos contextos «reales» de aplicación: en qué tipos de proyectos utilizarla TDD, cómo utilizar TDD en proyectos de código legado, como empezar a utilizar TDD, etc. Trata también la clásica rivalidad de los estilos Chicago vs London de sin necesariamente tomar partido (menciona su preferencia pero no la considera una bala de plata para todo contexto).

Otro punto no menor a destacar es que es uno de los pocos libros (¿acaso el único?) de TDD en castellano.

Creo que es un recurso interesante para aprender TDD, tal vez no entra en tanto detalle como otros libros de TDD pero al mismo cubre muchas más cuestiones, o sea: va más en anchura que en profundidad lo cual me parece bueno para un libro introductorio.

El libro está disponible en formato digital en LeanPub. Muy recomendado.

Highlights sobre el libro «Test-Driven Development By Example»

Esta semana terminé de releer este libro fundacional de TDD. Como ya mencioné no estoy convencido de que sea el punto de entrada más apropiado para aprender TDD, pero sí estoy convencido que todo practicante de TDD debería leerlo.

Personalmente creo que es un libro para leer de punta a punta, sin los capítulos de la tercera parte de libro tratan sobre patrones y se pueden leer en forma descolgada a modo de consulta, los capítulos de las dos primeras partes están dedicados al desarrollo de dos ejemplos en profundidad que luego son referenciamos en los patrones de la tercera parte.

El libro trata ciertas cuestiones de TDD que muchas veces se pasan por alto, algunas veces se las menciona a la pasada y otra vez ni siquiera se mencionan. Algunas de estas cuestiones que me parece vale la pena destacar:

  • El trabajo en forma iterativa y en pequeños pasos es realmente central a TDD. Beck habla de ciclos de 10 minutos (pag. 143).
  • Es completamente válido retroceder para avanzar, si llegamos a un punto donde estamos integrando nuestro código y vemos que hemos roto algo, puede resultar conveniente tirar lo hecho y comenzar de nuevo (pag. 149). Como estamos trabajando en incrementos realmente chicos, lo que vamos a estar tirando no es mucho, es solo el último incremento. Esto lo veo muy relacionado a la técnica Test and Commit or Revert.
  • La técnica «Log String» (pag. 146) es increíblemente simple y útil a la vez que definitivamente le voy a dedicar un artículo exclusivo.
  • Para el programador el código de test es tan importante como el código de dominio. Esto está mencionado de distintas formas a lo largo del libro y como consecuencia de esto no es raro que la cantidad de código de test sea similar a la cantidad de código de dominio. Asimismo el uso de patrones de diseño aplica tanto al código de dominio como al código de test.
  • Si bien el flujo de trabajo es codear un test a la vez, Beck recomienda comenzar la sesión de programación haciendo una lista de los casos que intentaremos cubrir durante la sesión (pag. 126). Esta lista también la utiliza para registrar casos/situaciones que puedan ir surgiendo durante la sesión sin perder el foco de trabajo: estoy trabajando en un caso, surge una idea, la anotamos en la lista y seguimos con los que estábamos (pag. 137)
  • A la hora de escribir los tests puede resultar conveniente comenzar por escribir el Assert (pag. 128)
  • Refactorizar es fundamental, no es posible hacer TDD sin refactorizar y una de las principales razones (o posiblemente la más importante) para refactorizar es evitar la duplicación de código (en realidad más que evitar duplicación de código lo que buscamos es evitar la duplicación de conocimiento). Esto es mencionado en varios lugares a lo largo del libro. Como que Beck está obsesionado con esto.
  • El apéndice 2 del libro desarrolla un ejemplo muy chiquito pero muy clarificador de la esencia de TDD.
  • El orden en que codeamos los tests puede impactar enormemente en el proceso de TDD (pag. 200). Un determinado orden puede hacer que el proceso fluya armónicamente mientras que la misma lista de tests codeada en un orden distinto puede llevar a un callejón sin salida.

Sin duda hay varias cuestiones más para destacar de este libro, pero estas son las que a mi me resonaron.

Comenzando a estudiar TDD

En el contexto de mi investigación sobre TDD decidí a arrancar desde cero a pesar de llevar ya varios años aplicando y enseñando TDD. La técnica Test-Driven Development (TDD) fue «creada» por Kent Beck durante los 90. Y pongo creada entre comillas porque el mismo Beck se define asimismo como «redescubridor» de TDD. Al margen de este acto de humildad, la realidad es que si bien Beck había leído sobre la idea de escribir el código de prueba antes que código funcional, TDD es una técnica que implica mucho más que esa idea.

Sinceramente desconozco cual sea primera mención formal a Test-Driven Development, pero la primera que yo conozco data de la primera edición del libro Extreme Programming Explained escrito por Beck y publicado en 1999. En dicho libro Beck no habla exactamente de Test-Driven Development como técnica sino que simplemente habla de escribir los tests antes de la funcionalidad y hace referencia a esto como estrategia Test-First.

Recién en su libro Test-Driven Development by Example publicado en 2003, Beck entra en los detalles de la técnica TDD. Hace ya años que no recomiendo este libro como puerta de entrada a TDD, porque personalmente me costó mucho hacer el salto de lo que propone el libro «al mundo real». Tengamos presente que los ejemplos del libro (que básicamente son 2 ejemplos tratados con bastante profundidad) están centrados en lo que podríamos denominar la capa de dominio y no lidian con nada de la infraestructura. Esto está muy bien para entender las ideas centrales de la técnica pero resulta insuficiente para poder aplicarla en «contextos industriales». Sin embargo, a partir de mi trabajo de maestría volví a leer el libro y esta relectura me llevó a revalorizarlo. Me resulta interesante cómo algunas cuestiones que descubrí practicando TDD están mencionadas en el libro, pero que en mi primera lectura yo pasé completamente por alto. Más aún, tengo la sensación de que algunas de esas cuestiones son reiteradamente subestimadas por practicantes y «evangelizadores» de TDD. Una de esas cuestiones es la naturaleza iterativa de TDD. Esta naturaleza iterativa, que también es parte central de Agile y DevOps, implica que tenemos que estar dispuestos a avanzar en una dirección con intención exploratoria aún cuando eso pueda implicar volver atrás. Llevado al código esto puede implicar escribir código (funcional o de prueba) sabiendo que en breve lo eliminaremos. Y cuando digo en breve no es dentro de 3 semanas o 3 meses, sino tal vez dentro de 15 minutos.

Son muy pocos los libros que he vuelto a leer de punta a punta. Muchas veces leo un libro de punta a punta cuando lo leo por primera vez y luego vuelvo a leer (generalmente a modo de consulta) algún capítulo en particular. Pero esta vez decidí volver a leer Test-Driven Development by Example de punta a punta otra vez y creo que ha sido una gran inversión pues me ha permitido reflexionar, cuestionarme y entender más profundamente algunas cuestiones.

Mientras escribo estas líneas reflexiono y me convenzo de que si bien yo estoy empezando mi investigación sobre TDD leyendo Test-Driven Development by Example, no es lo que yo recomendaría a un practicante, o sea, a alguien quien aprender TDD para aplicarlo en desarrollo de software. De hecho, la cuestión de por dónde empezar a aprender TDD es una de las cuestiones intento abordar en mi trabajo de investigación.

Tesis de maestría: Enseñanza de TDD

Este año me he propuesto completar mi tesis de maestría. Ya tengo el proyecto planteado y aprobado. La temática del mismo tiene que ver con desarrollar una propuesta para la enseñanza del desarrollo guiado por pruebas. Y si bien en el título de este post menciono TDD, Test-Driven Development, mi planteo es bastante más amplio que el clásico ciclo Red-Green-Refactor, mi idea es centrarme en el desarrollo guiado por pruebas pero desde una perspectiva más «holística» similar la que plantean Freeman y & Pryce en GOOS, viendo el desarrollo guiado por pruebas como un proceso de construcción de software que va más allá del diseño, la codificación y la prueba y que abarca también cuestiones de análisis, requerimientos, deployment y delivery.

La tesis en sí, es la forma de comunicar el trabajo de investigación que uno realiza. Dicho trabajo de investigación puede extenderse por meses o incluso años. Típicamente los trabajos de tesis de maestrías académicas son planteados para ser completados en un año calendario, pero eso no siempre se cumple. En mi caso armé un calendario de trabajo de apróximadamente un un año, pero dado que un año me parece un marco de tiempo demasiado extenso, plantee algunos hitos intermedios representados por publicaciones de las distintas cuestiones que vaya resolviendo.

Más allá de las publicaciones formales que realice, mi idea es ir compartiendo en este espacio algunos de mis avances. En este sentido va este primer post.

Dicho esto, si están interesados en la enseñanza, la prácticas y el aprendizaje de la técnica de desarrollo guiado por pruebas, les recomiendo estén atentos a este espacio.

Continuará…

Percepciones de mis alumnos sobre TDD y otras prácticas de desarrollo

En MeMo2 estudiamos diversas prácticas de desarrollo que luego pedimos a los alumnos utilizar durante el desarrollo de los trabajos grupales. En la clase de ayer, a punto ya de terminar el cuatrimestre, hicimos una muy breve actividad para relevar cómo les resultó el uso de esas prácticas.

Nos centramos en 3 prácticas concretas: Test-Driven Development (outside-in style), Mob-Programming y Trunk-Based Development. Para cada una de estas prácticas les pedimos que se ubiquen en lo que seria un «cuadro cartesiano» donde un eje horizontal representa cuánto utilizaron la práctica y el eje vertical representa el grado de confort/utilidad que sintieron con esa práctica.

En el caso de Mob-Programming las respuestas estuvieron bastante dispersas y sin extremos.

Pero para Trunk-Based Development y Test-Driven Development las respuestas resultaron mucho más categóricas: la gran mayoría indicó haber utilizado mucho lás prácticas con un grado positivo de confort/utilidad.

Personalmente estoy muy contento con estos resultados, que los alumnos perciban utilidad en lo que enseñamos resulta muy reconfortante. La gran duda (habitual en el ámbito académico) es cuanto finalmente terminan «comprando» estas prácticas los alumnos, o sea: fuera del contexto de la materia ¿seguirán utilizando estas prácticas?…..

Notes from my TDD Heuristics Workshop

Yesterday I delivered this workshop at Agile Brazil Conference. It was the second run of this workshop, the first one was last week when I run a «beta» edition that allowed me to adjust several things.

Yesterday’s run was much better, we were able to do more coding and the flow of the workshop was much more clear. Just five people participated of the workshop, which was not surprising for me given that Agile conferences these days are full of people that does not code at all.

Here are the slides I used in the workshop with link to the resources I mentioned. I am very satisfied with the result of the workshop so it is very possible I include it in my software engineering courses.