Catálogo de Técnicas de Refactorización (Martin Fowler)
La refactorización es una técnica disciplinada para reestructurar un cuerpo de código existente, alterando su estructura interna sin cambiar su comportamiento observable externo.
Martin Fowler recopiló un catálogo de movimientos atómicos de diseño que permiten transformar código degradado en código limpio paso a paso.
1. Extract Method (Extraer Método) #
Cuando tienes un fragmento de código que se puede agrupar o que requiere un comentario para explicar qué hace, extráelo a un método independiente cuyo nombre comunique claramente su propósito.
2. Replace Conditional with Polymorphism (Reemplazar Condicional por Polimorfismo) #
Tener sentencias switch o cadenas if-else if basadas en el tipo de un objeto viola el principio Open/Closed (OCP). Cada vez que se añade un nuevo tipo, hay que buscar y modificar todas esas condicionales.
1// ❌ ANTES: Switch dependiente del tipo 2double calcularVelocidad(Pajaro pajaro) { 3 switch (pajaro.tipo) { 4 case EUROPEO: return getVelocidadBase(); 5 case AFRICANO: return getVelocidadBase() - getFactorCarga(pajaro.peso); 6 case NORUEGO: return (pajaro.estaClavado) ? 0 : getVelocidadBase(); 7 default: throw new IllegalArgumentException("Tipo desconocido"); 8 } 9} 10 11// ✅ DESPUÉS: Polimorfismo orientado a objetos 12abstract class Pajaro { 13 abstract double getVelocidad(); 14} 15 16class PajaroEuropeo extends Pajaro { 17 double getVelocidad() { return getVelocidadBase(); } 18} 19 20class PajaroAfricano extends Pajaro { 21 double getVelocidad() { return getVelocidadBase() - getFactorCarga(this.peso); } 22}
3. Introduce Parameter Object (Introducir Objeto Parámetro) #
Cuando un grupo de parámetros viaja siempre junto a través de varias funciones (por ejemplo, fechaInicio, fechaFin, o latitud, longitud), agrúpalos en un objeto de dominio (Value Object).
1// ❌ ANTES: Parámetros dispersos repetidos en muchos métodos 2function obtenerCitas(fechaInicio: Date, fechaFin: Date, clienteId: string) { ... } 3function calcularFacturacion(fechaInicio: Date, fechaFin: Date) { ... } 4 5// ✅ DESPUÉS: Objeto de valor unificado que valida su propia lógica 6class RangoFechas { 7 constructor(public readonly inicio: Date, public readonly fin: Date) { 8 if (inicio > fin) throw new Error("Fecha inicio no puede ser posterior a fin"); 9 } 10 11 contiene(fecha: Date): boolean { 12 return fecha >= this.inicio && fecha <= this.fin; 13 } 14} 15 16function obtenerCitas(rango: RangoFechas, clienteId: string) { ... }
Resumen del tema
Conceptos clave #
- Extract Method: la técnica más utilizada; divide métodos extensos en funciones con nombres descriptivos y un único nivel de abstracción.
- Replace Conditional with Polymorphism: delega la lógica variante a subclases o estrategias polimórficas para cumplir con OCP.
- Introduce Parameter Object: sustituye listas largas de argumentos relacionados por un objeto coherente (Value Object).
- Seguridad en la Refactorización: nunca refactorices sin una suite de pruebas unitarias automatizadas en verde (Red-Green-Refactor).
Qué debes recordar #
Refactorizar no es reescribir desde cero; es aplicar una serie de pequeñas transformaciones seguras que preservan el comportamiento mientras mejoran radicalmente el diseño.