Product Crafter Emilio Carrión

La deuda técnica es como cuidar de un jardín

La maleza del software

Cuando empezamos a escribir software todo es siempre sencillo de implementar. Tenemos un campo vacío en el que comenzar a plantar nuevas funcionalidades. Con el paso del tiempo vamos añadiendo más y más código, más y más sistemas, más y más clases. A los meses nos damos cuenta de que plantar cosas nuevas empieza a costarnos un poco más, lo que antes era un campo vacío ahora está lleno de arbustos que han ido creciendo sin que nos diésemos cuenta, e incluso algunas malas hierbas han empezado a aparecer.

Después de un año o dos la situación ha llegado hasta un punto que la ha hecho insostenible. Añadir más funcionalidades o incluso cambiar cualquier cosa es un trabajo arduo y costoso. En lo que antes era un campo abierto, ahora tienes que adentrarte con machete y saco de dormir, no sabes cuando podrás salir de ahí dentro.

Eso es la deuda técnica, una deuda que crece sin que nos demos cuenta, que generamos a la vez que hacemos crecer nuestro software y que, igual que pasa con la complejidad, puede causarnos serios problemas.

Pero una cosa está clara, somos los causantes y los que hemos de aprender a gestionarla y controlarla. Como ya dijo Andrew Hunt en Pragmatic Programmer (aunque no del todo orientado a la deuda técnica):

Más que la construcción, el software se parece más a la jardinería…

Qué ocurre cuando no podamos

Nosotros somos los que generamos normalmente la deuda técnica. Suele surgir cuando tomamos atajos a la hora de implementar la siguiente funcionalidad o cambio. Hacemos las cosas no de la manera más limpia u obviando consensos de diseño para poder entregar el nuevo producto a nuestros usuarios lo más rápido posible. Al hacerlo, vamos desordenando poco a poco nuestro software. Y ese desorden, como el interés de una deuda (de ahí viene el nombre), va creciendo y acumulándose.

Sin embargo, al contrario de lo que podamos imaginar, generar deuda técnica no es algo malo. En realidad, es algo bastante saludable. Cuando estamos probando cosas nuevas, validando nuevos verticales de negocio o simplemente aprendiendo sobre nuestros usuarios, es bueno entregar lo antes posible para obtener ese feedback que nos va a hacer avanzar. Por lo tanto, generar un poco de deuda en el camino no es malo.

Lo malo viene cuando no miramos nunca hacia atrás y seguimos implementando funcionalidad tras funcionalidad sin pararnos a podar y limpiar la deuda que hemos ido generando. Hasta tal punto que empieza a comernos y se convierte en un problema.

¿De dónde salen todas esas malas hierbas?

A parte de la deuda problemática que viene de la despreocupación por nuestras propias plantaciones, es habitual que también surja deuda de la nada, como malas hierbas que aparecen un día cualquiera en tu campo después de regar.

Esta deuda emergente suele provenir de la propia naturaleza efímera de los sistemas que desarrollamos. Pueden ser dependencias desactualizadas que empiezan a causarnos problemas, pueden ser plataformas que quedan obsoletas y hay que migrarlas a las nuevas, pueden ser sistemas de terceros que desaparecen o cambian sus condiciones.

Malas hierbas que crecen y, que si no les prestamos la atención que requieren, se nos pondrán en medio cuando queramos desarrollar la siguiente nueva funcionalidad.

Cómo identificar la deuda técnica

Identificar la deuda técnica antes de que sea demasiado tarde es sencillo si se presta atención. Puedes intentar ver las pistas que indican que tienes un problema de deuda. Algunas de esas pistas son code smells, tardar más tiempo de lo que habías previsto implementando una nueva funcionalidad, darte cuenta de que tienes que refactorizar una gran parte de tu código porque es muy complejo y no puedes abordar un cambio, etc.

Cualquier olor a “esto debería ser más fácil” indica que puedes tener un problema de deuda técnica entre tus manos.

Lo mejor en ese momento es tomar nota y trazar todo lo que vas viendo, por qué crees que puede ser un problema y si es algo extendido en el proyecto. Generar un backlog de deuda que ir trabajando poco a poco te ayudará a empezar a reducirla.

Cómo priorizar la deuda técnica

Por algún lado hay que empezar a podar. Cuando hablamos de deuda, la que más duele es siempre aquella que se pone en medio cuando queremos hacer algún cambio.

Las zonas más calientes de tu código, las que más tocas, son propensas a acumular deuda. Y es probable que esa deuda acabe dándote más dolores de cabeza. Por lo tanto, hay que priorizar limpiar la casa que habitas normalmente, aquellos sitios donde pasas la mayor parte del tiempo y que donde acumular deuda puede causar los mayores problemas.

Por otro lado, eventualmente tocarás alguna parte del código vieja y reconocerás deuda que puede ser atajada. En esos casos lo mejor es que evites la tentación. Anota esa deuda en tu backlog para saber que existe e intenta continuar con el resto, seguramente tengas deuda más prioritaria que resolver antes.

Un framework que me gusta mucho para priorizar deuda técnica es El Muro de Deuda Técnica y que puede ayudarte a elegir que deuda requiere tu atención más inmediata y cual puede esperar a ser resuelta.

Como evitar la deuda

Como ya he comentado, generar deuda no es malo, es una herramienta que tenemos para adelantar la entrega de nuestro producto a nuestros clientes y stakeholders. Sin embargo, además de la deuda consciente que podemos incluir para conseguir este objetivo, también existe una deuda inconsciente que podemos incluir sin querer en nuestros desarrollos. Ya sea por falta de conocimientos, por despiste o por mala suerte, es un problema que afecta a todos equipos. Algunas de las maneras de evitarla son:

  • Refactorización continua: Integra la refactorización en los ciclos de desarrollo. Anima a los equipos a refactorizar el código a medida que trabajan en nuevas funcionalidades, asegurando un mantenimiento continuo en lugar de posponerlo para una etapa posterior, cuándo podría ser más difícil de abordar.
  • Pasos pequeños: Divide los proyectos en tareas más pequeñas y manejables. Esto permite refactors frecuentes, reduciendo las posibilidades de acumular una deuda sustancial con el tiempo.
  • Usa TDD: Ayuda a mantener el enfoque en la calidad del código, reduce las posibilidades de introducir errores y, de manera indirecta, minimiza la deuda técnica.
  • Revisiones de código: Revisa el código con tus compañeros de manera frecuente (o mejor aún, ¡haced pairing!). Anima a los miembros del equipo a criticar el código no solo por su funcionalidad, sino también por los estándares, la mantenibilidad y posibles indicadores de deuda técnica.
  • Comparte conocimientos: Facilita el intercambio de conocimientos dentro de los equipos. Esto ayuda a distribuir la experiencia y garantiza que se sigan prácticas recomendadas de manera uniforme, reduciendo la probabilidad de acumular deuda técnica excesiva.
  • Aprendizaje continuo: Fomenta la educación continua y la formación para los miembros del equipo. Proporciona recursos y talleres que se centren en las mejores prácticas y estrategias para gestionar la deuda técnica de manera efectiva.
  • Conciencia sobre la deuda técnica: Integra discusiones sobre deuda técnica en las reuniones de equipo y las sesiones de planificación del producto. Al aumentar la conciencia, los miembros del equipo se vuelven más proactivos al identificar y abordar posibles deudas.

Es un problema de todos

Y finalmente, no te limites a concienciar solo al equipo técnico sobre los problemas y causas de la deuda técnica. Haz participes a todos los roles del equipo. Es esencial que miembros como diseñadores y product managers sepan que es la deuda, como y porque se genera (al final muchas veces es en bien de los usuarios). Que estén alineados con que es un problema a tener en cuenta y que hay que gestionar de forma continua es esencial para cumplir expectativas y estar todos en la misma página.

TL;DR

La deuda técnica refleja la realidad en la que, al desarrollar software, a menudo tomamos decisiones rápidas o atajos que, con el tiempo, se convierten en obstáculos. Esta deuda puede surgir tanto de nuestras elecciones conscientes para entregar rápidamente funcionalidades como de factores externos impredecibles, como la obsolescencia de plataformas o dependencias desactualizadas.

Es crucial identificar a tiempo las señales de esta deuda, como los indicios de código problemático o dificultades inesperadas al añadir nuevas funcionalidades. La priorización y gestión de la deuda se vuelven vitales, enfocándonos en áreas críticas y frecuentemente modificadas del código, utilizando herramientas como el Muro de Deuda Técnica para dar prioridad a las áreas más urgentes.

Además, destacamos métodos para prevenir y reducir esta acumulación, como la refactorización continua, el TDD, revisiones frecuentes de código y la difusión de conocimientos dentro del equipo.

No obstante, es crucial reconocer que la responsabilidad de gestionar esta deuda no recae únicamente en el equipo técnico; todos los roles deben estar conscientes y comprometidos con su manejo. La gestión proactiva de la deuda técnica es crucial para mantener la calidad y eficiencia en nuestro desarrollo de software a largo plazo.

Espero que todo esto haya arrojado un poco más de luz sobre el tema. ¡Feliz poda!