35. Deuda técnica, refactorización y sostenibilidad

35.1 Introducción

En un proyecto de software, muchas decisiones se toman bajo presión: fechas cercanas, información incompleta, cambios urgentes, restricciones de presupuesto o necesidad de entregar valor rápidamente. Algunas de esas decisiones permiten avanzar, pero también pueden dejar costos técnicos para el futuro.

La deuda técnica, la refactorización y la sostenibilidad ayudan a comprender cómo mantener un producto saludable a lo largo del tiempo, evitando que cada cambio sea más lento, riesgoso y caro que el anterior.

35.2 ¿Qué es la deuda técnica?

La deuda técnica es el costo acumulado de decisiones técnicas que facilitan el avance en el corto plazo, pero dificultan el mantenimiento, la evolución o la calidad del software en el futuro.

La metáfora se parece a una deuda financiera: tomar un atajo puede permitir entregar antes, pero si no se gestiona, genera intereses en forma de errores, lentitud, fragilidad, retrabajo y dificultad para cambiar.

Idea central: la deuda técnica no siempre es mala. Puede ser una decisión consciente, pero debe reconocerse, registrarse y pagarse en el momento adecuado.

35.3 ¿Por qué aparece la deuda técnica?

La deuda técnica puede surgir por decisiones deliberadas o por problemas no detectados. A veces el equipo sabe que está tomando un atajo; otras veces la deuda aparece por falta de experiencia, comunicación o cuidado técnico.

  • Presión por entregar rápido.
  • Requerimientos poco claros o cambiantes.
  • Falta de pruebas automatizadas.
  • Diseños improvisados sin revisión.
  • Código duplicado o difícil de entender.
  • Dependencias obsoletas o mal gestionadas.
  • Documentación insuficiente o desactualizada.
  • Desconocimiento del dominio o de la tecnología utilizada.

35.4 Tipos de deuda técnica

Tipo Descripción Ejemplo
De código Problemas en la estructura, claridad o duplicación del código. Funciones muy largas con muchas responsabilidades.
De diseño Decisiones que dificultan separar responsabilidades o extender el sistema. Una regla de negocio repetida en varias pantallas.
De pruebas Falta de cobertura para validar cambios con confianza. No existen pruebas para un cálculo crítico.
De documentación Conocimiento importante no registrado o desactualizado. No se explica cómo desplegar una versión.
De infraestructura Ambientes, dependencias o configuraciones difíciles de mantener. Un despliegue manual con muchos pasos no documentados.

35.5 Deuda intencional y deuda accidental

La deuda intencional aparece cuando el equipo decide conscientemente aceptar un costo técnico para lograr un objetivo inmediato. Por ejemplo, entregar una versión mínima para validar una idea con usuarios.

La deuda accidental aparece sin una decisión clara: por falta de conocimiento, ausencia de revisión, crecimiento desordenado del sistema o acumulación de pequeños cambios mal integrados.

35.6 Impacto de la deuda técnica

La deuda técnica se vuelve problemática cuando empieza a afectar la velocidad, la calidad y la confianza del equipo. No siempre se observa de inmediato, pero con el tiempo puede convertir cambios simples en tareas costosas.

  • Aumenta el tiempo necesario para agregar funcionalidades.
  • Incrementa la probabilidad de defectos y regresiones.
  • Dificulta comprender el comportamiento del sistema.
  • Hace más costosa la incorporación de nuevos integrantes.
  • Reduce la confianza para modificar partes críticas.
  • Genera dependencia de personas que conocen detalles no documentados.

35.7 Señales de deuda técnica

Algunas señales permiten detectar que la deuda técnica está aumentando y necesita atención.

  • Cambios pequeños requieren modificar muchos archivos sin una razón clara.
  • El equipo evita tocar ciertas partes del sistema por temor a romperlas.
  • Los defectos aparecen repetidamente en los mismos módulos.
  • Las pruebas son lentas, frágiles o insuficientes.
  • La documentación no coincide con el comportamiento real.
  • Las dependencias están desactualizadas y son difíciles de actualizar.
  • Los despliegues requieren pasos manuales delicados.

35.8 ¿Qué es la refactorización?

La refactorización es la mejora de la estructura interna del software sin cambiar su comportamiento observable. Su objetivo es hacer que el código sea más claro, simple, mantenible y preparado para futuros cambios.

Refactorizar no es agregar funcionalidad nueva. Es reorganizar lo existente para que el sistema conserve lo que hace, pero lo haga con una estructura interna más saludable.

35.9 Ejemplos de refactorización

  • Extraer una función para eliminar código repetido.
  • Renombrar variables o métodos para expresar mejor su intención.
  • Dividir una clase que tiene demasiadas responsabilidades.
  • Mover una regla de negocio a un módulo más adecuado.
  • Simplificar una condición difícil de leer.
  • Separar lógica de presentación y lógica de negocio.
  • Eliminar código muerto que ya no se utiliza.

35.10 Refactorización y pruebas

Las pruebas son importantes porque la refactorización debe conservar el comportamiento externo del sistema. Si no existen pruebas suficientes, el equipo tiene menos confianza para reorganizar el código sin introducir defectos.

Antes de refactorizar una parte crítica, puede ser necesario agregar pruebas que describan el comportamiento actual. Luego, la refactorización se realiza en pasos pequeños y verificables.

35.11 Refactorización frente a reescritura

Refactorizar y reescribir no son lo mismo. Refactorizar mejora gradualmente una base existente. Reescribir implica construir nuevamente una parte significativa del sistema.

Enfoque Ventajas Riesgos
Refactorización Permite mejorar en pasos pequeños y con menor interrupción. Puede ser lenta si la deuda acumulada es muy alta.
Reescritura Permite replantear decisiones profundas desde cero. Puede subestimar reglas existentes y demorar más de lo esperado.

35.12 Gestión de deuda técnica

La deuda técnica debe gestionarse como parte del trabajo del producto. No alcanza con decir que el código está mal. Es necesario identificar problemas concretos, evaluar impacto, priorizar acciones y reservar capacidad para mejorar.

  • Registrar deudas relevantes con descripción y consecuencia.
  • Relacionar deuda técnica con riesgos o costos reales.
  • Priorizar según impacto en cambios futuros, defectos o seguridad.
  • Combinar mejoras técnicas con trabajo funcional cuando sea posible.
  • Evitar que nuevas funcionalidades aumenten deuda innecesariamente.
  • Revisar periódicamente el estado técnico del producto.

35.13 Priorizar refactorizaciones

No toda deuda técnica debe corregirse de inmediato. Algunas deudas tienen poco impacto y pueden esperar; otras bloquean cambios importantes o generan defectos frecuentes.

Conviene priorizar refactorizaciones que reduzcan riesgos, habiliten cambios próximos, mejoren módulos muy usados o disminuyan problemas repetidos.

35.14 Sostenibilidad del software

La sostenibilidad del software es la capacidad de un producto y de un equipo para mantener valor, calidad y ritmo de evolución durante el tiempo. Un sistema sostenible puede cambiar sin que cada modificación se vuelva excesivamente costosa.

La sostenibilidad depende de la calidad del diseño, las pruebas, la documentación, la arquitectura, la automatización, las prácticas de trabajo y la salud del equipo.

35.15 Factores que favorecen la sostenibilidad

  • Código claro y organizado.
  • Pruebas automatizadas confiables.
  • Arquitectura comprensible y bien delimitada.
  • Documentación útil y actualizada.
  • Procesos de construcción y despliegue repetibles.
  • Dependencias actualizadas y controladas.
  • Revisiones de código y aprendizaje compartido.
  • Espacio para mantenimiento preventivo.

35.16 Calidad interna y calidad externa

La calidad externa es lo que los usuarios perciben directamente: funcionalidades, rendimiento, estabilidad, usabilidad y resultados. La calidad interna está relacionada con la estructura del software: código, diseño, pruebas, arquitectura y facilidad de mantenimiento.

Aunque los usuarios no vean la calidad interna, con el tiempo la perciben indirectamente. Un sistema con mala calidad interna suele evolucionar más lento y presentar más defectos.

35.17 Ejemplo práctico

Supongamos un sistema de turnos médicos donde la regla para calcular disponibilidad está repetida en tres módulos distintos. Al principio parece más rápido copiar la lógica, pero luego cada cambio debe hacerse en varios lugares y aparecen inconsistencias.

El equipo decide refactorizar: centraliza la regla en un componente único, agrega pruebas para los casos principales y actualiza la documentación. El comportamiento externo no cambia, pero el sistema queda más fácil de mantener.

35.18 Errores comunes

  • Negar la existencia de deuda técnica hasta que el producto se vuelve difícil de modificar.
  • Usar la deuda técnica como excusa para reescribir todo sin analizar alternativas.
  • Refactorizar sin pruebas ni criterios claros de éxito.
  • Mezclar grandes refactorizaciones con cambios funcionales delicados.
  • Corregir solo síntomas visibles sin resolver causas estructurales.
  • No explicar el impacto de la deuda en términos comprensibles para el negocio.
  • Postergar indefinidamente el mantenimiento preventivo.

35.19 Buenas prácticas

  • Registrar deuda técnica importante y sus consecuencias.
  • Refactorizar en pasos pequeños, verificables y reversibles.
  • Agregar pruebas antes de modificar zonas críticas.
  • Priorizar mejoras que reduzcan riesgos o habiliten trabajo próximo.
  • Separar, cuando sea posible, cambios funcionales de cambios estructurales.
  • Revisar dependencias, configuraciones y documentación de manera periódica.
  • Reservar capacidad del equipo para sostener la salud técnica del producto.

35.20 Qué debes recordar

  • La deuda técnica representa costos futuros generados por decisiones técnicas actuales o pasadas.
  • No toda deuda es incorrecta, pero toda deuda relevante debe gestionarse.
  • La refactorización mejora la estructura interna sin cambiar el comportamiento observable.
  • Las pruebas aumentan la confianza para refactorizar con seguridad.
  • La sostenibilidad permite que el software siga evolucionando sin perder calidad ni velocidad.

35.21 Conclusión

La deuda técnica, la refactorización y la sostenibilidad muestran que la Ingeniería de Software no consiste solo en entregar funcionalidades. También implica cuidar la capacidad futura de cambiar, corregir y mejorar el producto.

En el próximo tema integraremos los conceptos principales del curso mediante un caso práctico que recorre el camino desde una necesidad inicial hasta una solución de software.

Volver al índice