Saltar al contenido
Inicio / Blog / La deuda técnica no es un problema de código
· 9 min lectura · Marc J. Cabrer

La deuda técnica no es un problema de código

Lo heredé sin mapa. Cada nueva funcionalidad tardaba más, el cliente perdía la confianza y nadie sabía exactamente por qué. Esto es lo que pasó y cómo lo resolví sin reescribirlo todo.

reflexionesdeuda-técnicagestión-técnicaproducto

Cuando recibí el proyecto, lo primero que vi fue que funcionaba.

No perfectamente, pero funcionaba. Tenía usuarios, procesaba datos, entregaba resultados. Para cualquier cliente eso era suficiente. Era la prueba de que merecía la pena seguir invirtiendo.

El problema no estaba donde se veía. Estaba en lo que no se veía.

Rápido, barato y sin plan para crecer

El sistema lo había arrancado alguien antes que yo. Lo había hecho rápido, lo había hecho barato y lo había hecho con la presión de tener que demostrar que el producto valía la pena antes de que el cliente perdiera el interés.

Todo eso es completamente comprensible.

Un MVP existe precisamente para eso: llegar al mercado lo antes posible, con el menor coste posible, y ver si hay vida al otro lado. Lo que ese desarrollador hizo tenía sentido en ese momento. El problema es que nadie planificó qué pasaría cuando el producto sí empezara a crecer.

Y crecer, creció.

El cliente que tenía razón sin entender por qué

A medida que el proyecto ganaba funcionalidades, el cliente empezaba a notar algo incómodo: cada cosa nueva tardaba más que la anterior.

No era una percepción. Era la realidad.

No es que el equipo fuera más lento. Es que el sistema hacía más difícil avanzar con cada paso. Añadir una funcionalidad nueva significaba tocar partes que no tenían nada que ver con lo que pedías. Arreglar una cosa rompía otra. Estimar cuánto tardaría algo se había convertido en un ejercicio de adivinación.

El cliente no lo entendía. Tenía razón en no entenderlo.

Desde fuera, el razonamiento es lógico: “Si añadirle un botón tardó dos días la primera vez, ¿por qué ahora tarda dos semanas?” Lo que nadie le había explicado era que el primer botón se había puesto sobre un terreno limpio, y el segundo había que ponerlo sobre un terreno donde ya habían pasado muchas cosas sin mucho orden.

La deuda técnica no es un problema de código. Es un problema de coste diferido.

Cada atajo tomado al principio es una deuda que no desaparece. Crece. Y cobra intereses.

Cómo se llegó hasta allí

Pongámonos en los zapatos del desarrollador inicial. El cliente duda. No está del todo convencido de que el producto vaya a funcionar. No quiere invertir demasiado en algo que quizás no llegue a ningún lado.

Esa duda obliga a quien construye a priorizar velocidad sobre todo lo demás.

No hay tiempo para diseñar bien la base de datos, porque primero hay que demostrar que la idea funciona. No hay tiempo para separar la lógica de negocio de los detalles técnicos, porque hay que salir a producción antes de que el cliente se enfríe. No hay tiempo para documentar, porque lo importante es que funcione hoy.

Y funcionó.

El problema es que ese “funciona hoy” se convirtió en el cimiento de todo lo que vendría después. Y sobre ese cimiento, cada nueva funcionalidad heredaba el mismo desequilibrio de base.

Lo que en un principio fue una decisión de eficiencia se convierte, con el tiempo, en el principal obstáculo para seguir siendo eficiente.

Lo que vi cuando miré dentro

Cuando entré al proyecto, el código hacía muchas cosas en los sitios equivocados.

No lo digo como crítica. Lo digo como mapa.

La lógica de negocio estaba mezclada con cómo los datos se guardaban en la base de datos. Las distintas partes del sistema se hablaban entre sí sin ningún protocolo claro. Había duplicidad de lógica: la misma regla de negocio aplicada de formas ligeramente distintas en distintos sitios. Y la base de datos reflejaba la misma improvisación acumulada: tablas con responsabilidades mezcladas, relaciones que habían crecido sin planificación.

Añadir algo nuevo significaba entender primero cómo encajaba en todo ese entramado. Eso tardaba. Y cualquier cambio podía tener efectos en lugares inesperados.

La velocidad del proyecto no dependía del talento del equipo. Dependía de la claridad —o la falta de ella— del sistema.

La conversación difícil con el cliente

Antes de proponer ninguna solución, tuve que hacer algo que no es fácil: hacerle entender al cliente lo que estaba pasando, sin que pareciera una excusa.

Porque es fácil que suene a excusa.

“El código está mal hecho” puede interpretarse como “el equipo no sabe lo que hace”. No es eso. Y nunca debe serlo.

Lo que le expliqué fue esto:

El proyecto arrancó de una forma que tenía sentido dado el contexto: sin certeza de que fuera a crecer, con presupuesto ajustado y necesidad de resultados rápidos. Esa apuesta salió bien. El producto tiene usuarios, tiene valor, merece seguir creciendo. Pero el cimiento sobre el que se construyó no estaba pensado para soportar lo que se ha construido encima.

Lo que estamos pagando ahora no es ineficiencia del equipo. Es el interés de una deuda que se contrajo al principio y que nadie había documentado como tal.

Y lo siguiente que le pregunté fue importante: ¿queremos seguir pagando intereses o queremos amortizar la deuda?

La solución: sin demoler, sin parar

La opción fácil habría sido reescribir todo desde cero. Empezar de nuevo, limpio, con todo bien pensado.

Es también la opción más cara, más lenta y más arriesgada.

Reconozco que fue mi primer impulso. Cuando el sistema que tienes delante parece un laberinto sin mapa, empezar de cero tiene un atractivo innegable. Pero ese atractivo es una trampa: el nuevo sistema hereda los problemas del anterior porque las personas que lo construyen llevan consigo el mismo conocimiento incompleto del dominio. El caos no estaba solo en el código. Estaba en todo lo que nadie había terminado de entender.

Un sistema que ya funciona y tiene usuarios no se puede apagar para rehacer.

Lo que propusimos fue diferente: ordenar sin demoler. Progresar por fases, cada una estable antes de empezar la siguiente.

Lo primero que hicimos fue lo menos visible: ordenar lo que ya existía antes de añadir nada nuevo. Separar responsabilidades dentro del código. Que cada parte del sistema hiciera una sola cosa, sin mezclar la lógica de negocio con cómo los datos se almacenaban, sin mezclar las reglas de una funcionalidad con las de otra. Esta primera fase no añadía nada al producto. Pero sentaba la base para poder hacerlo.

Cuando eso estuvo estable, pasamos a la estructura. Introdujimos capas con contratos claros entre ellas: una que gestionaba las peticiones, otra que aplicaba las reglas de negocio, otra que accedía a los datos. Cuando las capas están diferenciadas, cambiar una no rompe las demás. Y estimar cuánto tarda un cambio deja de ser una adivinanza.

Después tocó el dato. Normalizamos la base de datos, eliminamos duplicidades, nos aseguramos de que cada información viviera en un solo sitio y de que las relaciones entre datos fueran coherentes. Esta es la fase más invisible para el cliente, pero la que más impacta en la fiabilidad del sistema a largo plazo. No genera pantallas nuevas ni funcionalidades visibles. Solo deja de generar problemas que antes costaba mucho entender de dónde venían.

Y por último, una vez el sistema tenía estructura y los datos tenían orden, agrupamos todo lo relacionado con cada área de negocio. Que lo de facturación estuviera junto. Que lo de usuarios estuviera junto. Que cada parte pudiera evolucionar sin depender de las demás para hacerlo.

Cada fase tuvo coste. Pero cada fase también tuvo un retorno visible.

Cuando las promesas empezaron a cumplirse

El cliente fue viendo algo que no esperaba: a medida que avanzábamos por las fases, las estimaciones empezaron a cumplirse. Las funcionalidades empezaron a salir en los plazos que decíamos.

Y algo curioso también pasó: empezamos a aceptar peticiones que antes habíamos rechazado.

Hubo una concretamente que me viene a la mente. El cliente había pedido tiempo atrás una guía interactiva dentro de la misma aplicación. En ese momento la rechazamos: el sistema no estaba en condiciones de añadir algo así sin riesgo de desestabilizar lo que ya funcionaba. Era demasiado conectado con demasiadas partes.

Cuando el sistema ya tenía una estructura más clara, volvió a pedirla.

Esta vez la hicimos. Y la entregamos en menos de ocho horas.

No porque seamos más rápidos. Porque el sistema ya sabía dónde iba cada cosa.

Aquí hay que mencionar algo más: esa velocidad también se debe al apoyo de la IA. No como protagonista, sino como acelerador. Con un sistema ordenado, la IA puede ayudar de verdad: entiende el contexto, propone cambios coherentes, reduce el tiempo de implementación. Sobre un código caótico, la IA es tan desorientada como cualquiera. La base importa. Siempre.

El cliente pasó de cuestionar por qué todo tardaba tanto a pedir más horas para seguir desarrollando.

Lo que queda por encima del código

Hay algo en esta historia que va más allá de las decisiones técnicas.

Cuando un proyecto arranca con poca certeza y poco presupuesto, la deuda técnica es a veces una consecuencia inevitable, no un error evitable. El error no está en contraerla. El error está en no nombrarla.

Si al principio del proyecto alguien hubiera dicho: “Vamos a construir esto rápido y barato porque necesitamos validar antes de invertir más. Eso significa que el sistema tendrá límites. Cuando crezca, necesitaremos volver sobre la base antes de poder seguir”, la conversación difícil que tuve después habría sido más fácil. O quizás no habría sido necesaria.

La deuda técnica documentada es una herramienta de gestión. La deuda técnica silenciosa es una bomba de relojería.


Antes de aceptar atajos en el próximo proyecto, hay preguntas que vale la pena hacerse. Si nadie ha documentado qué se está sacrificando y por qué, la deuda no está gestionada: solo existe. Si no hay una condición clara que indique cuándo habrá que volver a ordenar, ese momento nunca llegará en un buen momento —siempre habrá algo más urgente. Si el cliente no sabe que lo que acepta hoy tendrá un coste futuro, no está tomando una decisión informada: está firmando algo que no ha leído.

Y quizás la pregunta más incómoda: ¿puede el equipo señalar la deuda sin que eso se interprete como una excusa? Si no puede, el problema no es técnico. Es de confianza.

No se trata de evitar la deuda técnica siempre. A veces es la decisión correcta. Se trata de no firmarla sin saber lo que estás firmando.

¿Te ha resultado útil?

Contacto

Reserva la conversación adecuada, no una reunión cualquiera.

Si necesitas contraste técnico, entra por disponibilidad. Si todavía estás ordenando el problema, escríbeme primero y decidimos qué formato encaja mejor.

Prefieres escribir antes?