5 errores fatales al refactorizar código legacy con IA
Hace unos meses me contrataron para modernizar un módulo de facturación escrito en 2019.
Eran cerca de 3.000 líneas de TypeScript sin tipar, callbacks anidados y lógica de negocio repartida entre controladores y servicios. Pensé: "Le paso esto a un modelo de lenguaje moderno y en 10 minutos lo tengo convertido a funciones puras y tipadas".
Refactorizar código legacy con IA parecía trivial. Le pedí al modelo que reescribiera el archivo y el resultado parecía una obra de arte: código limpio, nombres elegantes y cero warnings en el editor.
Desplegamos en staging. A las dos horas saltó la primera alerta: los clientes con direcciones fiscales internacionales no podían facturar. El modelo había considerado que una comprobación con == null de un campo antiguo era "código redundante" y la había borrado, rompiendo seis años de retrocompatibilidad silenciosa.
Si vas a meter agentes de IA en proyectos legacy, aquí tienes los 5 errores fatales que no puedes permitirte.
Error 1: Alucinación de versiones y APIs incompatibles
Los modelos de IA fueron entrenados con millones de repositorios que mezclan código de 2020 con código de 2026.
Cuando le pides a una IA que modifique un proyecto antiguo de Node.js o Angular:
- Asume que puedes usar métodos modernos de JavaScript (
Array.prototype.toSorted(),Object.groupBy()) en entornos que corren en runtimes sin soporte. - Intenta importar métodos de librerías modernas (como
rxjs/operatorsreubicados o versiones incompatibles de Axios).
// ❌ Código sugerido por IA para un proyecto en Node 18
const groupedOrders = Object.groupBy(orders, (item) => item.status);
// En runtime: TypeError: Object.groupBy is not a function
Cómo evitarlo: Especifica siempre el target exacto en tus prompts y configuraciones: "Target Node 18 LTS, ECMAScript 2022. Prohibido usar APIs de ECMAScript 2024+".
El mecanismo de fondo lo desgrané en por qué la IA se inventa cosas: el modelo no miente, completa el patrón más probable. Y en un repo de 2019, el patrón más probable es el de 2026.
Error 2: Pérdida silenciosa de contratos y el peligro del any encubierto
El código legacy suele tener tipos implícitos o estructuras heterogéneas. Cuando la IA intenta "limpiar" esos tipos, con frecuencia toma atajos peligrosos:
// Antes: código legacy feo, pero con un caso borde que lleva años en producción
function parseUser(data: Record<string, unknown>) {
return data.legacy_id ?? data.id;
}
// ❌ Refactor 'limpio' de la IA que destruye ese caso borde
interface User { id: string; }
function parseUser(data: User): User {
return { id: data.id }; // Se perdió el soporte de legacy_id
}
La IA optimiza para la legibilidad del código presente, no para la historia oculta de los bugs pasados.
Error 3: Refactorizar sin Tests de Caracterización previos
El error más destructivo es pedirle a la IA que reescriba código antes de tener una red de seguridad.
Si el código no tiene tests, no puedes refactorizar con IA. Punto.
El protocolo correcto exige crear primero Characterization Tests (Tests de Caja Negra):
// test/billing.characterization.spec.ts
import { calculateInvoice } from 39;../src/legacy/billing39;;
describe(39;Billing Legacy Characterization Tests39;, () => {
it(39;preserva el comportamiento exacto para clientes extranjeros39;, () => {
const input = { amount: 100, country: 39;DE39;, taxExempt: true };
const result = calculateInvoice(input);
expect(result).toMatchSnapshot(); // Congela el comportamiento real antes de tocar nada
});
});
Si la suite tarda minutos en correr, nadie la ejecutará antes de cada refactor. Aquí tienes cómo dejar los tests unitarios en milisegundos con Vitest: con IA de por medio, la velocidad del test runner deja de ser comodidad y pasa a ser el límite de tu ciclo de trabajo.
En el curso de Testing en Angular con Jest y Testing Library dedicamos un módulo completo a blindar código histórico mediante tests de regresión antes de aplicar cualquier modernización.
Error 4: Saturación y degradación de la ventana de contexto
En repositorios con cientos de archivos interconectados, pasarle al agente archivos gigantes (1.000+ líneas) provoca pérdida de atención (lost in the middle).
El agente empieza a ignorar imports cruciales o inventa interfaces auxiliares en lugar de reutilizar las del proyecto.
Regla de oro: No pidas "refactoriza el módulo de pagos". Pide "extrae el cálculo de impuestos de este archivo a una función pura aislada y valida que el test adjunto siga en verde".
Error 5: Aceptar Diffs extensos sin revisión granular
Aceptar un diff de 400 líneas generado por IA sin revisarlo línea a línea es una negligencia profesional.
┌─────────────────────────────────────────────────────────────┐
│ PROTOCOLO DE REFACTOR CON IA │
│ │
│ 1. Test de Caracterización (Fija el comportamiento) │
│ 2. Spec Técnica (Define lo que se puede y no se puede tocar)│
│ 3. Refactorización atómica (Menos de 80 líneas por paso) │
│ 4. Verificación de Test Runner en verde │
└─────────────────────────────────────────────────────────────┘
Este es exactamente el enfoque que explicamos en el libro de Spec-Driven Development (SDD): tratar las modificaciones de código como contratos medibles con límites inquebrantables.
Qué hacer hoy con esto
Si tienes que tocar un módulo legacy esta semana:
- No abras la IA todavía.
- Escribe tres tests que cubran los casos de uso principales y los casos de borde más raros que conozcas.
- Ejecuta los tests y asegúrate de que pasan.
- Solo entonces, entrega el código y los tests a tu agente de IA con la instrucción explícita de no romper la suite.
Para acceder a checklists de refactorización segura y scripts de validación automática para proyectos empresariales, únete a Dominicode Labs.
Preguntas frecuentes
¿Por qué la IA rompe código legacy que antes funcionaba?
Porque los modelos de lenguaje intentan simplificar lo que parece "código redundante" sin entender los parches históricos o edge cases que ese código resolvía en producción.
¿Qué es un Characterization Test y por qué es indispensable?
Es una prueba automatizada que captura el comportamiento actual del sistema (con sus virtudes y sus defectos) para garantizar que una refactorización no altere inadvertidamente el resultado final.
¿Cómo evitar que la IA use versiones incompatibles de librerías?
Configurando un archivo de contexto claro (como CLAUDE.md o reglas de proyecto) donde se especifique la versión exacta de Node.js, TypeScript y el target ECMAScript soportado.
¿Cuánto código conviene pasarle a la IA en cada refactorización?
Menos de lo que crees. Por debajo de 80 líneas por paso el diff se revisa entero en un vistazo y cualquier regresión se localiza de inmediato. Con diffs de 300 o 400 líneas nadie revisa de verdad: se aprueba por cansancio.
¿Se puede refactorizar código legacy con IA sin tests de ningún tipo?
No de forma responsable. Si no hay tests, el primer trabajo del agente no es refactorizar sino generar tests de caracterización que congelen el comportamiento actual. Solo cuando esa red está en verde tiene sentido tocar la implementación.
Por Bezael Pérez — Developer senior con más de 15 años de experiencia y fundador de Dominicode.
