Módulo 7: Modernizar Legacy Code
Modernizar Syntax y Patterns Deprecated
Modernizar Syntax y Patterns Deprecated
Descripción de la cápsula
El scan del módulo anterior te dio el inventario. Esta cápsula te enseña a ejecutar cada tipo de modernización con Claude Code: de old Python a modern Python. Cada modernización es un commit separado con tests de regresión.
Modernización de Syntax
F-strings (Python 3.6+)
# Antes:
message = "Hello, %s! You have %d items." % (name, count)
message = "Hello, {}! You have {} items.".format(name, count)
# Después:
message = f"Hello, {name}! You have {count} items."
# Prompt a Claude Code:
> "Convierte todas las %-formatting y .format() strings
en src/services/ a f-strings. No cambies strings que
no tienen variables interpoladas."
Type Hints (Python 3.5+)
# Antes:
def get_users(active_only, limit):
# ¿Qué tipos? ¿Qué retorna? No se sabe sin leer el código
pass
# Después:
def get_users(active_only: bool, limit: int = 100) -> list[dict]:
pass
# Prompt:
> "Agrega type hints a todas las funciones públicas en
src/services/user_service.py. Infiere los tipos del
uso actual en el código. Usa syntax moderna (list[str]
en vez de List[str])."
Dataclasses (Python 3.7+)
# Antes:
class Config:
def __init__(self, host, port, debug=False):
self.host = host
self.port = port
self.debug = debug
def __repr__(self):
return f"Config(host={self.host}, port={self.port})"
def __eq__(self, other):
return (self.host == other.host and
self.port == other.port and
self.debug == other.debug)
# Después (3 líneas reemplazan 12):
from dataclasses import dataclass
@dataclass
class Config:
host: str
port: int
debug: bool = False
Pathlib (Python 3.4+)
# Antes:
import os
file_path = os.path.join(base_dir, "config", "settings.json")
if os.path.exists(file_path):
with open(file_path) as f:
data = json.load(f)
parent_dir = os.path.dirname(os.path.abspath(__file__))
# Después:
from pathlib import Path
file_path = Path(base_dir) / "config" / "settings.json"
if file_path.exists():
data = json.loads(file_path.read_text())
parent_dir = Path(__file__).parent.resolve()
Walrus Operator (Python 3.8+)
# Antes:
results = get_results()
if results:
process(results)
match = pattern.search(text)
if match:
handle(match.group())
# Después:
if results := get_results():
process(results)
if match := pattern.search(text):
handle(match.group())
Modernización de Patterns
Context Managers
# Antes:
try:
file = open("data.txt")
data = file.read()
file.close()
except IOError:
data = ""
# Después:
try:
with open("data.txt") as file:
data = file.read()
except FileNotFoundError:
data = ""
Enums en vez de Magic Strings
# Antes:
status = "active"
if user["status"] == "active":
pass
elif user["status"] == "inactive":
pass
# Typo "acitve" pasa silenciosamente
# Después:
from enum import Enum
class UserStatus(Enum):
ACTIVE = "active"
INACTIVE = "inactive"
SUSPENDED = "suspended"
if user.status == UserStatus.ACTIVE:
pass
# Typo UserStatus.ACITVE → error inmediato
Specific Exceptions
# Antes:
try:
result = process_data(input)
except: # atrapa TODO, incluyendo KeyboardInterrupt
return None # silencia errores
# Después:
try:
result = process_data(input)
except ValueError as e:
logger.warning(f"Invalid input: {e}")
return None
except ConnectionError as e:
logger.error(f"Connection failed: {e}")
raise
Ejecutando con Claude Code
El prompt maestro de modernización
> "Moderniza src/services/order_service.py aplicando
estos cambios (uno a la vez, confirma cada uno):
1. %-formatting → f-strings
2. os.path → pathlib
3. bare except → specific exceptions
4. manual __init__ classes → dataclasses (donde aplique)
5. Agregar type hints a funciones públicas
Para cada cambio:
- Muestra antes y después
- Confirma que los tests pasan
- Haz un commit con mensaje descriptivo"
Conexión con Proyecto
En el Proyecto del Módulo (cápsula 05), ejecutas al menos 5 modernizaciones diferentes en un módulo legacy, cada una con test de regresión y commit separado.
Troubleshooting
Problema 1: F-string rompe string con backslashes
Solución: f-strings no permiten backslashes dentro de {}. Usa variable:
# Error:
f"Path: {path.replace('\\', '/')}"
# Fix:
cleaned = path.replace('\\', '/')
f"Path: {cleaned}"
Problema 2: Type hints rompen compatibilidad con Python 3.8
Solución: Usa from __future__ import annotations para syntax moderna en versiones viejas.
Problema 3: Dataclass no funciona con herencia compleja
Solución: No todo necesita ser dataclass. Si la clase tiene lógica compleja en init, mantenla como clase normal.
Ejercicios
Ejercicio 1: Modernizar syntax (Fácil)
Moderniza este código:
import os
name = "Hello %s" % user
path = os.path.join("/tmp", "data.txt")
if os.path.exists(path):
f = open(path)
data = f.read()
f.close()
Ver solución
from pathlib import Path
name = f"Hello {user}"
path = Path("/tmp") / "data.txt"
if path.exists():
data = path.read_text()
De 6 líneas a 4, más seguro (context manager implícito) y más legible.
Ejercicio 2: Escribir prompt de modernización (Medio)
Escribe el prompt para que Claude Code modernice un archivo de 200 líneas de forma incremental (no todo de golpe).
Ver solución
> "Moderniza src/legacy_module.py de forma INCREMENTAL.
Aplica un tipo de cambio a la vez en este orden:
1. Primero: convierte %-formatting a f-strings.
Muestra los cambios. Ejecuta tests.
2. Segundo: reemplaza os.path con pathlib.
Muestra los cambios. Ejecuta tests.
3. Tercero: agrega type hints a funciones públicas.
Muestra los cambios. Ejecuta tests.
4. Cuarto: reemplaza bare except con specific exceptions.
Muestra los cambios. Ejecuta tests.
NO hagas todos los cambios a la vez.
ESPERA confirmación entre cada paso."
Resumen
- Syntax modernization: f-strings, type hints, dataclasses, pathlib, walrus operator
- Pattern modernization: context managers, enums, specific exceptions
- Claude Code convierte semánticamente, no solo busca-y-reemplaza
- Un tipo de cambio por commit — nunca mezclar
- Tests de regresión en cada paso
Próxima cápsula: Refactoring Incremental vs Big Bang.
Recursos Adicionales
- Python 3.12 What's New - Features más recientes
- pyupgrade - Automatiza modernización de syntax
- dataclasses - Python Docs - Referencia oficial
- pathlib - Python Docs - Referencia oficial
- PEP 484 - Type Hints - La PEP de type hints
- mypy - Type checker para verificar tus type hints