# Arquitectura y evolución de sistemas heredados (Legacy) > Referencia especializada del skill `rdx-solid`. Consulta [arquitectura.md](arquitectura.md) y el documento del ámbito afectado: [arquitectura-backend.md](arquitectura-backend.md), [arquitectura-frontend.md](arquitectura-frontend.md) o [arquitectura-shared.md](arquitectura-shared.md). ## 1. Propósito Modernizar y mantener sistemas existentes con seguridad, preservando comportamientos y contratos requeridos. «Legacy» no significa necesariamente código de baja calidad: puede ser software estable, valioso y escasamente documentado. **Prioridad:** comprender antes de cambiar; verificar antes de declarar el cambio correcto. No imponer patrones o nomenclaturas nuevas de forma masiva. ## 2. Reconocimiento inicial 1. Identifica límites del sistema, ejecutables, servicios y consumidores. 2. Revisa dependencias, versiones, compilación y despliegue. 3. Localiza contratos públicos, formatos de intercambio y persistencia. 4. Identifica comportamientos implícitos, trabajos programados y efectos secundarios. 5. Comprueba las pruebas existentes y los mecanismos de recuperación. 6. Delimita la tarea, sus riesgos y los componentes afectados. No presupongas que un comportamiento aparentemente extraño es un error: puede ser un requisito histórico o un contrato con consumidores externos. ## 3. Caracterización del comportamiento Cuando falten especificaciones o pruebas, utiliza ejemplos de entrada y salida, datos anonimizados, consultas, trazas o pruebas de caracterización para describir el comportamiento actual. Distingue: - **Comportamiento a conservar:** contratos y resultados vigentes necesarios. - **Defecto a corregir:** fallo confirmado respecto al comportamiento esperado. - **Cambio funcional:** nuevo requisito que modifica la semántica. No conviertas automáticamente un fallo conocido en una obligación permanente mediante una prueba de caracterización. ## 4. Refactorización incremental - Realiza cambios pequeños y reversibles cuando sea posible. - Separa las correcciones funcionales de las refactorizaciones generales. - Introduce pruebas de regresión en torno a comportamientos críticos cuando sea viable. - No renombres, reformatees o muevas grandes áreas ajenas a la tarea. - Conserva convenciones y límites de módulos existentes salvo necesidad justificada. - Utiliza adaptadores temporales si permiten migrar consumidores gradualmente. - Evita reescrituras completas sin evaluación de costes, riesgos y continuidad del servicio. La ausencia de pruebas no prohíbe todo cambio: exige mecanismos de verificación proporcionales, mayor cautela y documentación de incertidumbres. ## 5. Estrategias de modernización | Estrategia | Cuándo considerarla | Riesgo a controlar | |---|---|---| | Refactorización localizada | Corregir estructura sin cambiar contratos | Regresiones involuntarias | | Adaptador / fachada | Aislar un contrato antiguo | Traducción semántica incorrecta | | Capa anticorrupción | Separar modelos de dominio antiguo y nuevo | Complejidad de mapeo | | Strangler Fig | Sustituir capacidades progresivamente | Enrutamiento y coexistencia | | Migración por etapas | Cambiar persistencia o infraestructura | Consistencia y reversión | | Sustitución completa | Sistema realmente inviable de mantener | Alcance, datos y paridad funcional | Escoge la opción con menor riesgo y coste total razonable; no asumas que reescribir equivale a mejorar. ## 6. Capas de adaptación y anticorrupción Una capa anticorrupción evita que el nuevo dominio adopte conceptos o errores del modelo antiguo. ```typescript interface CustomerDirectory { findCustomer(id: CustomerId): Promise; } class LegacyCustomerAdapter implements CustomerDirectory { constructor(private readonly legacyApi: LegacyCustomerApi) {} async findCustomer(id: CustomerId): Promise { const legacyRecord = await this.legacyApi.readCustomer(id.value); return legacyRecord ? mapLegacyCustomer(legacyRecord) : null; } } ``` Los tipos y colaboradores son ilustrativos. Verifica diferencias de identificación, nulos, fechas, moneda, errores y codificación: un mapeo estructural no garantiza equivalencia semántica. No crees una capa anticorrupción cuando un adaptador sencillo sea suficiente. ## 7. Migración de datos y persistencia - Determina esquemas, claves, restricciones, volumen y dependencias. - Diseña migraciones reproducibles con validaciones de integridad. - Evalúa ventanas de mantenimiento, backups y recuperación. - Considera expansión-contracción para cambios de esquema compatibles. - Si existe doble escritura, define fallos, reconciliación y fuente de verdad; no la adoptes sin necesidad. - Verifica volumen, rendimiento y compatibilidad con versiones desplegadas. - Evita transformaciones destructivas sin un procedimiento probado o adecuado de recuperación. ## 8. Contratos, compatibilidad y despliegue Identifica qué consumidores pueden quedar afectados: clientes externos, informes, procesos por lotes, integraciones, archivos de intercambio, aplicaciones móviles o servicios anteriores. - Mantén formatos y significado de campos cuando sea requerido. - Utiliza versionado o adaptadores si los consumidores no pueden migrar a la vez. - Controla coexistencia de versiones y despliegues escalonados. - Define condiciones de reversión cuando el riesgo lo exija. - No elimines endpoints o campos aparentemente no usados sin verificar consumidores externos. ## 9. Dependencias y tecnologías obsoletas - Determina compatibilidad y riesgos de seguridad de runtimes, librerías y drivers. - No actualices todas las dependencias durante una corrección puntual sin necesidad. - Prioriza vulnerabilidades o incompatibilidades relevantes según su impacto. - Realiza actualizaciones por etapas y verifica sus contratos. - Documenta dependencias no sustituibles y mecanismos de mitigación. ## 10. Pruebas y seguimiento - Pruebas de caracterización para comportamiento existente. - Regresión para defectos corregidos. - Integración para adaptadores y persistencia. - Contrato para consumidores externos y coexistencia. - E2E para flujos de negocio críticos. - Comparación controlada de resultados antiguo/nuevo cuando sea viable. Evita utilizar exclusivamente métricas de cobertura como garantía de migración. Observa errores, tiempos de respuesta, integridad de datos y resultados funcionales tras un cambio cuando el entorno lo permita. ## 11. Señales de alerta - Reescribir todo antes de conocer el comportamiento existente. - Confundir limpieza estética con mejora arquitectónica necesaria. - Modificar contratos sin inventariar consumidores. - Migrar datos sin validar integridad ni recuperación. - Repartir reglas inconsistentes entre implementación antigua y nueva. - Eliminar lógica aparentemente redundante con efectos históricos desconocidos. - Introducir frameworks nuevos para una corrección localizada. - Declarar paridad funcional sin pruebas o evidencias suficientes. ## 12. Lista de comprobación - [ ] ¿Conozco comportamiento, contratos y consumidores afectados? - [ ] ¿He distinguido defectos de comportamientos históricos a conservar? - [ ] ¿La estrategia de migración es proporcional al riesgo? - [ ] ¿Existe verificación antes y después del cambio? - [ ] ¿La integridad de los datos y la compatibilidad están protegidas? - [ ] ¿Se han previsto reversión o recuperación cuando corresponda? - [ ] ¿He evitado reestructuraciones ajenas a la tarea? - [ ] ¿He comunicado incertidumbres y verificaciones pendientes? **Principio final:** modernizar significa reducir el riesgo y mejorar la capacidad de evolución, no reescribir por preferencia tecnológica.