Legado — no es simplemente código antiguo. Es un sistema funcional que genera dinero para el negocio pero frena el desarrollo. En el desarrollo móvil, el legado puede estar escrito en Objective-C, usar bibliotecas obsoletas o patrones arquitectónicos anticuados. Según un informe de CAST Software (2024), la edad promedio de una línea de código en proyectos enterprise supera los 14 años. La estrategia de trabajo con el legado determina si se convierte en un freno o sigue siendo un activo manejable.
Puntos clave
Legado — código o sistema que sigue funcionando en producción pero ya no cumple con los estándares modernos de calidad. El legado puede estar escrito en un lenguaje obsoleto (por ejemplo, Objective-C en lugar de Swift), usar bibliotecas sin soporte o patrones arquitectónicos considerados antiguos.
La característica clave del legado es la ausencia de pruebas. Según la definición de Michael Feathers (2004), el código legado es código sin pruebas. Si no se puede cambiar el comportamiento de forma segura, el sistema está en estado legacy independientemente de su edad. El código nuevo sin pruebas unitarias es legado desde el primer día.
El legado no es necesariamente malo. Un sistema bien diseñado en Java 8 puede ser más fiable y comprensible que un código caótico en Kotlin con corrutinas. La edad del código no es un indicador de calidad — lo importante es lo fácil que el sistema se deja modificar y ampliar.
Cada sistema exitoso se convierte en legado con el tiempo. Es un proceso natural: las tecnologías evolucionan más rápido de lo que el código puede reescribirse. Una aplicación escrita hace 5 años en Swift 2 es legado hoy, aunque en su momento fuera moderna.
El valor de negocio del legado a menudo se subestima. El sistema funciona de forma fiable, procesa transacciones, almacena datos — reescribirlo conlleva riesgos. Según Standish Group (2024), el 35% de los proyectos de reescritura completa terminan en fracaso. Económicamente no está justificado deshacerse del legado, sino aprender a trabajar con él.
Las mejores estrategias son la migración gradual, encapsular el código antiguo tras nuevas interfaces y las pruebas automatizadas. El legado solo se convierte en un problema cuando deja de ser modificable a un coste predecible.
Falta de pruebas automatizadas — el principal indicador. Si después de cambiar una sola línea un desarrollador no puede ejecutar pruebas y confirmar que nada se rompió — estás ante un legado. Una señal adicional: el proceso de despliegue lleva horas y requiere pasos manuales.
La documentación no coincide con el código — otro marcador. Los diagramas arquitectónicos están desactualizados, los comentarios describen un comportamiento que ya ha cambiado. Time-to-ramp-up para un nuevo desarrollador supera el mes — señal de alta complejidad y baja mantenibilidad.
Señales adicionales: arquitectura monolítica sin límites claros, pruebas manuales como método principal de verificación, pipeline de CI largo (más de 30 minutos), uso de bibliotecas sin versiones actualizadas e imposibilidad de actualizar dependencias sin romper módulos relacionados.
El fenómeno del “código frágil” — un cambio en un lugar rompe tres más. Esto es consecuencia del acoplamiento fuerte, cuando los módulos saben demasiado el uno del otro. Cuanto mayor es el acoplamiento, más rápido el sistema pasa a la categoría de legado.
Reducción de velocidad — el riesgo principal. Añadir una funcionalidad simple requiere horas de estudio del código y días de pruebas. Según Stripe (2024), los desarrolladores dedican el 33% de su tiempo a superar deuda técnica, directamente relacionada con la presencia de módulos legacy en el proyecto.
Fuga de experiencia — los autores del código original abandonan la empresa y la documentación es incompleta. Los nuevos desarrolladores temen tocar módulos desconocidos, lo que lleva al efecto de “código congelado”: el módulo no evoluciona pero sigue funcionando. El bus factor de estos sistemas es críticamente bajo.
Seguridad — las bibliotecas obsoletas contienen vulnerabilidades conocidas. Usar OpenSSL 1.0.2 o versiones antiguas de Jackson en proyectos Java es un camino directo a incidentes de seguridad que pueden costar reputación y clientes al negocio.
Desmotivación del equipo — trabajar con legado sin una estrategia de mejora reduce la satisfacción de los desarrolladores. El equipo deja de sentirse orgulloso del producto, la rotación de personal aumenta, lo que ralentiza aún más el desarrollo del sistema.
Pruebas de caracterización — el primer paso antes de cualquier cambio en código legado. Ejecuta el código con datos de entrada conocidos y registra la salida esperada. Estas pruebas capturan el comportamiento actual como especificación. Golden master testing es una variante donde la salida se compara con un archivo de referencia.
Análisis de seams — encontrar puntos donde se puede romper el acoplamiento sin cambiar el comportamiento. Michael Feathers identifica varios tipos de seams: preprocessor seam, object seam, link seam. Object seam es el más común: reemplazar un objeto real por un stub de prueba a través de una interfaz.
Sprout method y Sprout class — técnicas para añadir código nuevo junto al antiguo, no dentro de él. En lugar de modificar un método existente, crea un nuevo método con la lógica deseada y llámalo desde el antiguo. Así se minimiza el riesgo de romper el código funcional.
class LegacyPaymentProcessor {
def process(payment) {
// 200 líneas de código legado que no deben tocarse
logPayment(payment) // método sprout
}
def logPayment(payment) {
// nuevo código añadido junto al legado
}
}
Patrón Strangler Fig — el enfoque recomendado para la migración de legado. Se crea un nuevo módulo en paralelo, el tráfico se redirige gradualmente de lo antiguo a lo nuevo. El módulo antiguo “muere” naturalmente cuando deja de recibir peticiones. El patrón minimiza los riesgos y permite revertir si surgen problemas.
Branch by Abstraction — técnica donde se crea una abstracción sobre la implementación antigua y la nueva. El código cliente se cambia a la abstracción y la implementación antigua se reemplaza gradualmente. Ejemplo: reemplazar la capa de red de AFNetworking a Alamofire mediante un protocolo unificado NetworkService.
Migración por fases — dividir la transición en pequeños pasos: encapsular el módulo antiguo → escribir pruebas → crear un nuevo módulo → ejecutar en paralelo → eliminar el módulo antiguo. Cada paso termina con un estado estable del sistema, lo que permite desplegar en cualquier momento.
Preguntas frecuentes
La reescritura completa es la opción más arriesgada. Solo el 25% de los proyectos de Big Rewrite tienen éxito a tiempo. Es mejor aplicar el patrón Strangler Fig: reemplazar módulos gradualmente sin detener el producto. Cada iteración aporta valor de negocio y los riesgos se distribuyen en el tiempo.
Empieza con pruebas de caracterización: ejecuta el módulo con datos conocidos, registra el resultado. Golden master testing es una forma sencilla de capturar el comportamiento. Añade pruebas cada vez que toques una línea de código. En 6 meses tendrás un armazón que protege contra regresiones.
Si el sistema es estable, no requiere cambios frecuentes y no afecta a la velocidad de desarrollo de otros módulos — déjalo. “Si funciona, no lo toques” es un enfoque razonable para módulos legacy aislados con baja frecuencia de cambios. Toca el código solo cuando necesites introducir cambios de negocio.
Usa versionado semántico y actualiza por pasos: patch → minor → major. Escribe pruebas de compatibilidad para cada biblioteca. Dependabot o Renovate automatizan la creación de PRs de actualización. Si una biblioteca está obsoleta, planifica su reemplazo mediante una abstracción.
La deuda técnica es una metáfora para estimar el coste de las mejoras aplazadas. El legado es un sistema o código concreto que ya ha quedado obsoleto. La deuda técnica puede acumularse en un mes, el legado requiere tiempo. No toda deuda técnica se convierte en legado, pero todo legado contiene deuda técnica.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también