La refactorización es una de las prácticas más importantes de Extreme Programming (XP), intrínsecamente ligada al desarrollo iterativo y a la mejora continua. Consiste en reestructurar el código existente, alterando su estructura interna sin cambiar su comportamiento externo. Es el "cómo" se limpia el código después de haberlo hecho funcionar.
Martin Fowler, una autoridad en la materia, define la refactorización como "un cambio en la estructura interna del software para hacerlo más fácil de entender y más barato de modificar, sin cambiar su comportamiento observable".
En el contexto de XP, es esencial por varias razones:
El principio fundamental de la refactorización es la separación entre cambiar el comportamiento y cambiar la estructura. Cuando un desarrollador está refactorizando, no debe añadir nuevas funcionalidades. Del mismo modo, cuando está añadiendo una nueva funcionalidad, debe intentar no refactorizar masivamente al mismo tiempo.
El proceso es el siguiente:
Este enfoque disciplinado garantiza que el diseño del software evolucione de manera segura y sostenible.
Veamos un ejemplo práctico en Python. La técnica que usaremos es "Extraer Método" (Extract Method), que se aplica cuando un método es demasiado largo y contiene bloques de código que pueden ser agrupados y extraídos a un nuevo método con un nombre descriptivo.
Imaginemos una función que calcula e imprime los detalles de una factura. Tiene varias responsabilidades mezcladas.
def imprimir_factura(factura):
total = 0
print(f"Cliente: {factura['cliente']}")
print("------------------------")
# Calcular total
for item in factura['items']:
total += item['precio'] * item['cantidad']
# Aplicar impuestos
impuestos = total * 0.21
total_con_impuestos = total + impuestos
# Imprimir detalles
print(f"Subtotal: ${total:.2f}")
print(f"Impuestos (21%): ${impuestos:.2f}")
print(f"Total a pagar: ${total_con_impuestos:.2f}")
El código anterior es difícil de leer y probar. Podemos extraer la lógica de cálculo a su propia función.
def calcular_total(items):
"""Calcula el subtotal a partir de una lista de items."""
total = 0
for item in items:
total += item['precio'] * item['cantidad']
return total
def imprimir_factura(factura):
"""Imprime los detalles de una factura de forma ordenada."""
print(f"Cliente: {factura['cliente']}")
print("------------------------")
subtotal = calcular_total(factura['items'])
impuestos = subtotal * 0.21
total_con_impuestos = subtotal + impuestos
print(f"Subtotal: ${subtotal:.2f}")
print(f"Impuestos (21%): ${impuestos:.2f}")
print(f"Total a pagar: ${total_con_impuestos:.2f}")
El nuevo código es más claro. La función `imprimir_factura` ahora se centra en la presentación, mientras que `calcular_total` se encarga de la lógica de negocio. Además, `calcular_total` es ahora una función pura y mucho más fácil de probar de forma aislada.
Aunque la refactorización puede hacerse manualmente, los entornos de desarrollo modernos (IDEs) y otras herramientas ofrecen un soporte potente para automatizar estas tareas de forma segura.
El uso de estas herramientas permite a los equipos de XP aplicar la refactorización de manera rápida, segura y consistente, manteniendo el código limpio y manejable a lo largo del tiempo.