Nivel 3 · 25 min
Antipatrones de Diseño
Un antipatrón es una solución común a un problema recurrente que parece razonable al principio pero resulta contraproducente. Reconocer antipatrones en código existente es una habilidad clave para arquitectos y seniors. Los más críticos: God Object, Feature Envy, Acoplamiento Estrecho, Modelo de Dominio Anémico y Optimización Prematura.
God Object y Feature Envy
God Object (también llamado God Class) es una clase que sabe o hace demasiado — centraliza lógica que debería estar distribuida. Se identifica cuando la clase tiene decenas de métodos sin relación clara, referencia a casi todas las demás clases, o cuesta refactorizar algo sin tocarla. Feature Envy ocurre cuando un método usa más datos de otra clase que de la suya propia — señal de que pertenece a esa otra clase. Ambos violan SRP.
Tight Coupling y Modelo Anémico
El acoplamiento estrecho (Tight Coupling) hace que los cambios en un módulo requieran cambios en cascada en otros — síntoma de dependencias directas en lugar de interfaces. El Modelo de Dominio Anémico (Anemic Domain Model, término de Martin Fowler) ocurre cuando las clases de dominio son solo contenedores de datos (getters/setters) y toda la lógica está en servicios externos. Violás la encapsulación y el principio de que los datos y el comportamiento deben cohabitar.
Optimización Prematura y otros antipatrones
Knuth: ''La optimización prematura es la raíz de todos los males.'' Micro-optimizaciones que sacrifican legibilidad antes de medir el problema real son perjudiciales. Otros antipatrones comunes: Copy-Paste Programming (duplicación en lugar de abstracción), Magic Numbers (constantes sin nombre), Spaghetti Code (flujo sin estructura), Golden Hammer (usar la misma solución para todos los problemas).
Code example
// Modelo anemico (mal)
class Order { private List<Item> items; /* solo getters/setters */ }
class OrderPricingService {
BigDecimal calculate(Order order) { /* toda la logica aqui */ }
}
// Modelo rico (bien)
class Order {
BigDecimal calculateTotal() { /* logica donde estan los datos */ }
void addItem(Item item) { /* validaciones incluidas */ }
}