Módulo 7: Modernizar Legacy Code
Módulo 7: Modernizar Legacy Code
Módulo 7: Modernizar Legacy Code
Descripción de la cápsula
Phase 2 te enseñó técnicas de refactoring (M4), migración de frameworks (M5), y context management (M6). Este módulo aplica todo a un caso concreto y extremadamente común: código legacy que necesita modernización. No migración de framework — modernización: actualizar syntax deprecated, introducir type hints, reemplazar patterns obsoletos, eliminar dead code.
Casi todo equipo tiene código que "funciona pero está obsoleto." Fue escrito con las mejores herramientas y conocimiento disponible en su momento. Las dependencias se deprecaron, los patterns evolucionaron, el lenguaje agregó features nuevos. Modernizar no es criticar — es actualizar al presente.
Claude Code es extraordinariamente efectivo aquí: puede detectar code smells, patterns deprecated, y dead code en minutos — lo que manualmente toma horas de revisión archivo por archivo.
Al terminar las 5 cápsulas, vas a poder identificar tech debt sistemáticamente, priorizar modernización con criterio impacto/riesgo, modernizar syntax y patterns sin romper comportamiento, y ejecutar modernización incremental con tests de regresión en cada paso.
Contexto del Módulo
¿Dónde estamos?
Guía #8, Phase 3: Legacy y Proyecto, Módulo 7 de 8.
Phase 3: Legacy y Proyecto (Módulos 7-8)
├── Módulo 7: Modernizar Legacy Code ← ESTÁS AQUÍ
│ → Tech debt detection, syntax modernization, dead code
└── Módulo 8: Proyecto Integrador
→ Migración completa de proyecto legacy real
Lo que ya sabes
De Phase 1 dominas el onboarding (M1), exploración (M2) y architecture analysis (M3). De Phase 2 dominas refactoring multi-file (M4), migración (M5) y context management (M6). Este módulo aplica todo eso a un caso específico: código que evolucionó orgánicamente y acumuló tech debt.
¿Hacia dónde vamos?
El Módulo 8 integra los 7 módulos anteriores en un proyecto de migración completo. Las técnicas de modernización que aprendes aquí se ejecutan en ese proyecto sobre un codebase legacy real.
Objetivo Profesional
Al final podrás:
- ✅ Identificar tech debt sistemáticamente con Claude Code
- ✅ Priorizar modernización con la matriz impacto/riesgo
- ✅ Modernizar syntax Python (f-strings, type hints, dataclasses, pathlib)
- ✅ Modernizar patterns (context managers, enums, async/await)
- ✅ Eliminar dead code con confianza
- ✅ Ejecutar modernización incremental con tests en cada paso
- ✅ Distinguir modernización (preserva comportamiento) de rewrite (cambia comportamiento)
Un Caso Real: Modernizar Sin Romper
Para anclar el módulo, considera un caso típico:
Tarea: Modernizar un módulo
payments/processor.py(~600 líneas) escrito en Python 3.6, sin type hints, conos.pathen todas partes, formato%sen strings,try/exceptcapturandoExceptiongenérico, y 3 funciones que parecen no usarse.
Enfoque A: "Big bang modernization"
Día 1, 09:00 → Abre el archivo, decide "voy a limpiarlo todo".
Día 1, 11:00 → Hizo: type hints + f-strings + pathlib + dataclasses
+ eliminó funciones "no usadas" + cambió excepciones.
Día 1, 11:30 → Tests no existen. Corre la app: parece funcionar.
Día 1, 14:00 → Push a staging.
Día 1, 16:00 → INCIDENT: una de las funciones "no usadas" sí se llamaba
dinámicamente desde un módulo de reportes.
Revertir todo. Día perdido.
POSTMORTEM:
- Sin tests, no se sabe qué se rompió ni dónde
- Demasiados cambios juntos: el diff es ilegible
- Función "muerta" no estaba muerta — solo no era visible para grep
Enfoque B: Modernización incremental (este módulo)
Día 1, 09:00 → DETECTAR (Cápsula 02)
"Lista todos los items de tech debt en payments/processor.py.
Categoriza por tipo y severidad."
→ Claude Code lista 23 items en 5 minutos.
Día 1, 09:15 → PRIORIZAR (Cápsula 02)
Aplica matriz impacto/riesgo. Decide orden:
1. Type hints (alto valor, riesgo bajo)
2. F-strings (medio valor, riesgo bajo)
3. pathlib (medio valor, riesgo bajo)
4. Excepciones específicas (alto valor, riesgo medio)
5. Eliminar dead code (alto valor, RIESGO ALTO — al final)
Día 1, 09:30 → SAFETY NET (M4 cápsula 05)
Tests de regresión que capturan comportamiento actual.
Verifica que pasan contra el código sin tocar.
Día 1, 10:00 → COMMIT 1: type hints
Solo añadir type hints. Tests pasan. Commit.
Día 1, 11:00 → COMMIT 2: f-strings
Solo cambiar % y .format() a f-strings. Tests pasan. Commit.
Día 1, 11:30 → COMMIT 3: pathlib
Solo reemplazar os.path por pathlib. Tests pasan. Commit.
Día 1, 14:00 → COMMIT 4: excepciones específicas
Reemplazar except Exception por excepciones específicas.
Tests pasan. Commit.
Día 1, 15:30 → COMMIT 5: dead code
ANTES: usar Explore (M2) para verificar que las funciones
realmente no se llaman (incluyendo dynamic dispatch).
Encuentra: 2 son dead, 1 SE LLAMA dinámicamente.
Elimina solo las 2 confirmadas. Tests pasan. Commit.
Día 1, 16:00 → 5 commits limpios. Tests verdes en cada uno. Code review
fácil porque cada commit hace UNA cosa.
Cero incidentes en staging.
Mismo trabajo. Mismo resultado final. Riesgo radicalmente distinto.
La diferencia clave: un tipo de cambio por commit, tests verdes en cada paso. Si algo falla, sabes exactamente qué lo rompió. Si necesitas revertir, revierte uno, no todos.
Progresión del Módulo
Mapa del Módulo
| Cápsula | Tema | Qué aprenderás |
|---|---|---|
| 02 | Identificar Tech Debt con Claude Code | Detección sistemática de code smells, deprecated patterns, dead code |
| 03 | Modernizar Syntax y Patterns Deprecated | De old Python a modern Python: f-strings, type hints, dataclasses, pathlib |
| 04 | Refactoring Incremental vs Big Bang | Por qué incremental gana y cómo ejecutarlo |
| 05 | Proyecto: Modernización de Módulo Legacy | Modernizar un módulo con 5+ items de tech debt |
Flujo de aprendizaje
Empiezas aprendiendo a detectar tech debt sistemáticamente (cápsula 02) — sin esto, modernizar es subjetivo. Después aprendes a modernizar syntax y patterns específicos (cápsula 03) con ejemplos concretos antes/después. La cápsula 04 te da la metodología (incremental vs big bang) que aplica a cualquier modernización. Y el proyecto integra todo en un módulo real con 5+ items de tech debt.
Conceptos Clave que Verás
Vista previa rápida de conceptos centrales del módulo para que llegues con vocabulario:
Tech Debt
Costo futuro de mantener algo que se hizo de forma sub-óptima en el pasado. No es lo mismo que "código malo": tech debt es información sobre el costo, no un juicio. La matriz impacto/riesgo (cápsula 04) te ayuda a decidir qué pagar y qué dejar.
Code Smells
Síntomas observables de tech debt: funciones largas, naming inconsistente, duplicación, parámetros con tipos Any. La cápsula 02 te da el catálogo y cómo Claude Code los detecta sistemáticamente.
Deprecated Patterns
Patrones que el lenguaje o ecosistema ya superó. Ejemplos en Python:
%sformatting → f-strings (3.6+)os.path→pathlib(3.4+)- Diccionarios sin orden garantizado → ordered dicts por defecto (3.7+)
- Type hints opcionales → recomendados con mypy/pyright
Dead Code
Código que no se ejecuta. Cuidado: "no encontrado por grep" ≠ "muerto". Python tiene dynamic dispatch (callbacks, getattr, decorators con strings). La cápsula 02 te da el protocolo de verificación dinámica.
Modernización vs Migración vs Rewrite
Tres niveles de cambio distintos:
| Acción | Preserva comportamiento | Cambia framework | Cambia features |
|---|---|---|---|
| Modernización (este módulo) | ✅ Sí | ❌ No | ❌ No |
| Migración (M5) | ✅ Sí | ✅ Sí | ❌ No |
| Rewrite (no en esta guía) | ❌ No | Posible | ✅ Sí |
Mezclar los tres es la causa #1 de proyectos de migración fallidos.
Matriz Impacto/Riesgo
Framework de priorización: cada item de tech debt se evalúa en dos ejes:
- Impacto — cuánto valor genera resolverlo (mantenibilidad, performance, seguridad)
- Riesgo — qué probabilidad hay de romper algo al cambiar
Orden de ejecución: alto impacto + bajo riesgo primero, alto riesgo al final con verificación adicional. La cápsula 04 desarrolla el framework.
Refactoring Incremental
Un tipo de cambio por commit. Tests verdes en cada paso. Si algo falla, sabes exactamente qué lo rompió. Lo opuesto: big bang — todo junto, riesgo alto. La cápsula 04 muestra cómo ejecutar incremental con Claude Code.
El Principio Central
Incremental siempre gana. Un cambio a la vez, con tests. Es más lento en apariencia pero infinitamente más seguro. Modernizar f-strings en un commit. Type hints en otro. Dead code removal en otro. Nunca todo junto.
Tres consecuencias prácticas:
- Un tipo de cambio por commit. Si el commit dice "modernización", está mal. Debe decir "type hints en payments/processor.py".
- Tests verdes en cada paso. No avanzas al siguiente cambio si los tests del anterior no pasan.
- Verificación dinámica antes de eliminar. "No usado" según grep ≠ "muerto". Usa Explore para verificar dynamic dispatch.
Conexión con Proyecto
En el Proyecto del Módulo (cápsula 05), modernizas un módulo Python con al menos 5 items de tech debt. Cada cambio tiene test de regresión. El entregable es el módulo modernizado + un change log que documenta cada commit.
En el Módulo 8 (Proyecto Integrador), las técnicas de modernización son uno de los pasos del full migration cycle. El assessment del Módulo 8 identifica el tech debt; este módulo te da la metodología para resolverlo de forma incremental y segura.
Trampas a Evitar al Cursar Este Módulo
Cinco malentendidos previsibles. Anticípalos antes de empezar.
1. "Si Claude Code lista tech debt, lo arreglo todo de una vez"
No. La lista de tech debt es input para priorizar, no un to-do para ejecutar todo en un solo PR. La cápsula 04 te da la matriz impacto/riesgo: alto impacto + bajo riesgo va primero, alto impacto + alto riesgo (como dead code) va al final con verificación adicional.
2. "Modernizar es lo mismo que rewrite"
No. Modernizar preserva comportamiento mientras actualiza syntax/patterns. Rewrite empieza de cero y puede cambiar comportamiento. Si te encuentras "mejorando la lógica de negocio mientras modernizas", paraste de modernizar y empezaste a hacer otra cosa — separa los cambios.
3. "Dead code = código que grep no encuentra"
No. Python tiene dynamic dispatch (getattr, __getattr__, decoradores con strings, plugins). Una función puede estar siendo llamada dinámicamente sin que grep la encuentre. Antes de eliminar, usa Explore (M2) y revisa logs de producción. La cápsula 02 desarrolla este punto.
4. "Tech debt es deuda que hay que pagar inmediatamente"
No. Tech debt es información sobre el costo futuro de mantener algo. A veces el costo de pagarlo es mayor que el costo de mantenerlo. La matriz impacto/riesgo (cápsula 04) te ayuda a decidir qué pagar y qué dejar — modernizar todo no siempre es la respuesta correcta.
5. "Type hints son cosmética"
Subestimar type hints es un error caro. Type hints detectan bugs antes de runtime, mejoran la lectura del código, y habilitan refactorings más agresivos porque el linter te avisa de breakage. La cápsula 03 los trata como prioridad alta, no como detalle estético.
Diagnóstico: ¿Cuál es tu Punto de Partida?
Cinco preguntas para calibrar antes de empezar.
Pregunta 1: La última vez que "limpiaste" código viejo, ¿cuántos tipos de cambio hiciste en un solo commit?
Si dijiste "varios": la trampa #1 te aplica. La cápsula 04 te enseña por qué incremental gana.
Si dijiste "uno solo": vas bien. La cápsula 04 formaliza ese hábito como metodología reusable.
Pregunta 2: ¿Sabes diferenciar tech debt de bugs?
Si sí: la cápsula 02 formaliza la detección de tech debt y te ayuda a priorizar.
Si no: simple — bug = no funciona como debería; tech debt = funciona pero el costo de mantenerlo es alto. La cápsula 02 desarrolla la taxonomía.
Pregunta 3: ¿Has eliminado código "no usado" y descubierto después que sí se usaba?
Si sí: la trampa #3 te aplica. La cápsula 02 te da el protocolo de verificación.
Si no: te lo va a pasar tarde o temprano. La cápsula 02 te previene.
Pregunta 4: ¿Tienes type hints en tu código nuevo? ¿Y los añades a código existente cuando lo tocas?
Si "sí" a ambos: vas bien. La cápsula 03 te da el patrón sistemático.
Si "no" a alguno: la cápsula 03 muestra el ROI: type hints añaden 10% de tiempo y eliminan ~30% de los bugs típicos en runtime.
Pregunta 5: ¿Cómo decides qué tech debt vale la pena pagar?
Si tienes un proceso: la cápsula 04 te lo formaliza como matriz reutilizable.
Si dices "intuición": la cápsula 04 te da los ejes (impacto, riesgo, frecuencia de cambio) para tomar decisiones reproducibles.
Si dudaste en 3 o más: este módulo te da la metodología que falta para modernizar con confianza. Si respondiste todas con criterio, úsalo enfocado en la cápsula 02 (detección sistemática) que escala mucho con Claude Code.
Evidencia de Éxito
Antes de avanzar al Módulo 8 (Proyecto Integrador), deberías poder:
- ✅ Escanear un módulo con Claude Code y listar 5+ items de tech debt en menos de 10 minutos
- ✅ Priorizar los items con la matriz impacto/riesgo, no al azar
- ✅ Modernizar syntax (f-strings, type hints, pathlib, dataclasses) sin romper tests
- ✅ Verificar dinámicamente que el código a eliminar realmente no se usa
- ✅ Producir un commit por tipo de modernización (no "limpieza general")
- ✅ Distinguir modernización (preserva comportamiento) de rewrite (cambia comportamiento)
- ✅ Aplicar el ciclo tests-verdes-en-cada-paso por hábito
Si alguno no se cumple al final, regresa a la cápsula correspondiente. El Módulo 8 ejecuta una migración completa que incluye modernización — sin estas técnicas, el proyecto integrador se vuelve un "big bang" arriesgado.
Resumen
- Modernizar legacy es el trabajo más demandado en equipos de software
- Claude Code detecta tech debt en minutos que manualmente toma horas
- Incremental > big bang — un tipo de cambio por commit
- Tech debt no es negligencia — es evolución natural del código
- Tests de regresión en cada paso (regla del Módulo 4)
- Dead code requiere verificación dinámica, no solo grep
- La diferencia entre el "día perdido" del Enfoque A y los "5 commits limpios" del Enfoque B es exactamente la metodología de este módulo
Siguiente cápsula: 02 — Identificar Tech Debt con Claude Code — detección sistemática de code smells, deprecated patterns, y dead code. Es la base de la priorización de la cápsula 04 y del proyecto.
Recursos Adicionales
- Working Effectively with Legacy Code - Michael Feathers - La biblia del legacy code
- Python What's New - Features nuevos de cada versión de Python
- Refactoring Guru - Code Smells - Catálogo de code smells
- pyupgrade - Herramienta que moderniza syntax Python automáticamente
- vulture - Detector de dead code en Python
- mypy - Type checker que complementa la adición de type hints
- PEP 8 - Style guide oficial de Python (referencia para "modern Python")