← dev-notes
REFACTORING · PARTE 1 DE 3

El Ciclo y los
Code Smells

La regla de oro, el ciclo del refactoring y los disparadores que te dicen cuándo actuar

REFACTORING · P1
🔑 Regla de oro 🤢 Code Smells 🔄 Ciclo Red-Green-Refactor 🛡 La red de seguridad
01 La regla de oro
🔑
MARTIN FOWLER — REFACTORING (2ND ED.)
"No se añade funcionalidad mientras se refactoriza.
No se refactoriza mientras se añade funcionalidad."
Esta separación es lo que convierte el refactoring en una práctica disciplinada. Mezclar ambas actividades lleva a bugs difíciles de rastrear: ¿fue el cambio de lógica o el cambio estructural lo que lo rompió? Con la regla de oro, siempre lo sabes.
02 El ciclo — Red, Green, Refactor
El único orden correcto para refactorizar con seguridad
🔴
RED
Test en rojo
Escribe el test que describe el comportamiento. Debe fallar — si no falla, el test es inútil.
🟢
GREEN
Test en verde
Escribe el código mínimo para que el test pase. No importa si es feo — lo arreglas en el siguiente paso.
🟡
REFACTOR
Mejorar la estructura
Mejora el diseño sin cambiar el comportamiento. Los tests siguen en verde. Aquí entra el catálogo de técnicas.
🔵
COMMIT
Pequeños pasos
Haz commit frecuente. Si rompes algo, el rollback es a minutos atrás, no a horas. Pequeños pasos son la clave.
🛡 La red de seguridad: No existe refactoring sin tests. Si los tests no están en verde antes de empezar, lo que haces es cambiar código a ciegas — no refactorizar. La suite de tests es el contrato que te garantiza que el comportamiento no cambió.
03 Code Smells — los 4 disparadores principales
● CRÍTICO
🔤 Mysterious Name
El nombre de una variable, función o clase no revela su intención. Obliga al lector a ejecutar el código mentalmente para entenderlo — la peor forma de gastar energía cognitiva.
❌ ANTES
calc(d, r)
int x = q * p
process(data)
✅ DESPUÉS
calculateDiscount(days, rate)
int totalPrice = qty * price
validateAndSendEmail(user)
Señal: Si necesitas un comentario para explicar qué hace una función, su nombre está mal. El código debería explicarse solo.
● EL ENEMIGO Nº1
📋 Duplicated Code
El mismo bloque de lógica aparece en dos o más lugares. Viola el principio DRY (Don't Repeat Yourself). Cuando hay que cambiar esa lógica, hay que hacerlo en todos los sitios — y siempre te olvidas uno.
❌ PROBLEMA
// en OrderService:
tax = price * 0.19

// en InvoiceService:
tax = price * 0.19
✅ FIX
// TaxCalculator:
calculateTax(price) {
return price * TAX_RATE
}
Señal: Ctrl+F y encuentras el mismo bloque en más de un lugar. Técnica: Extract Method → extraer a un lugar canónico.
● ALTO
📏 Long Function / Large Class
Una función hace demasiadas cosas. Una clase tiene demasiadas responsabilidades. Síntoma de falta de cohesión — cada elemento debería tener una sola razón para cambiar (SRP).
❌ SEÑALES
// función de 80 líneas
// clase con 20 métodos
// comentarios-sección
// "... y luego también..."
✅ GUÍA
// Función: ≤10-15 líneas
// Una función, un verbo
// Clase: ≤200 líneas
// Un sustantivo, una resp.
Señal: Necesitas scroll para leer una función. Hay comentarios del tipo // Paso 1: validar — esos comentarios son nombres de métodos disfrazados.
● MEDIO
🔢 Primitive Obsession
Usar tipos primitivos (String, int) para representar conceptos del dominio que tienen lógica, formato y validaciones propias. El remedio es el patrón Value Object de DDD.
❌ ANTES
String rut = "12.345.678-9"
String email = user.email
int age = 150 // válido?
✅ DESPUÉS
Rut rut = new Rut("12345678-9")
Email email = new Email(raw)
Age age = Age.of(150) // lanza!
Conexión DDD: Primitive Obsession se cura con Value Objects. La validación vive en el constructor — nunca llega un Email inválido al dominio.
04 Catálogo extendido — más smells que debes reconocer
Code Smell
Severidad
Descripción
Técnica de remedio
Long Parameter List
Crítico
Función con 5+ parámetros. Difícil de recordar, fácil de mezclar el orden. Señal de que falta cohesión o un objeto de parámetros.
Introduce Parameter Object
Feature Envy
Alto
Un método de la clase A usa más datos de la clase B que los propios. El método está en el lugar equivocado — pertenece a B.
Move Method
Data Clumps
Alto
El mismo grupo de parámetros aparece siempre junto (street, city, zip). Son un objeto disfrazado de variables sueltas.
Extract Class / Value Object
Switch Statements
Medio
Un switch o cadena de if-else que chequea el tipo de un objeto. Viola OCP — cada nuevo tipo requiere modificar el switch.
Replace with Polymorphism
Dead Code
Medio
Código comentado, variables nunca leídas, métodos nunca llamados, ramas if (false). Genera ruido y confusión.
Eliminar sin miedo
Comments as Explanation
Informativo
Comentario que explica qué hace el código (no el porqué). Señal de que el código en sí debería ser más expresivo.
Extract Method con buen nombre
Divergent Change
Diseño
Una clase cambia por razones distintas (por el DB y por la API). Tiene más de una responsabilidad — violación directa de SRP.
Extract Class
Shotgun Surgery
Diseño
Un solo cambio lógico requiere tocar docenas de clases distintas. La responsabilidad está demasiado fragmentada — lo opuesto de Divergent Change.
Move Method / Inline Class
📚
La fuente: Martin Fowler — Refactoring (2ª ed., 2018)
El catálogo completo de Fowler tiene más de 60 técnicas y decenas de smells documentados. Para el nivel senior, domina los smells más frecuentes y sus remedios directos. Lo que te hace senior no es memorizar el catálogo — es reconocer el olor y saber el camino hacia el diseño más limpio.