17. Errores comunes al aplicar estos principios

Aplicar DRY, KISS y YAGNI en proyectos con Java exige equilibrio. Una interpretación extrema puede generar el efecto contrario: duplicaciones innecesarias, código críptico o funcionalidades recortadas sin validar que eran requeridas. Este capítulo recopila los tropiezos más habituales y ofrece recomendaciones para evitarlos.

El objetivo es detectar a tiempo si estamos tergiversando la idea original del principio y corregir el rumbo antes de introducir deuda técnica.

17.1 Errores frecuentes con DRY

  • Abstracciones prematuras: extraer clases genéricas antes de comprender las variaciones reales.
  • DRY a nivel sintáctico: reutilizar fragmentos idénticos pero con propósitos diferentes, atando conceptos que deberían evolucionar por separado.
  • Falta de validación: eliminar duplicaciones sin agregar pruebas que garanticen el comportamiento.

17.2 Errores frecuentes con KISS

  • Confundir simple con simplista: omitir validaciones o casos de error esenciales.
  • Evitar patrones útiles: rechazar estructuras probadas (como Strategy o Template Method) aunque resuelvan la complejidad.
  • Nombrado pobre: reducir nombres o comentarios hasta perder claridad.

17.3 Errores frecuentes con YAGNI

  • Usar YAGNI como excusa: negarse a planificar extensiones evidentes y posponerlas hasta que se vuelven urgentes.
  • Eliminar métricas o logs necesarios: confundir instrumentación con funcionalidad que “no hace falta”.
  • No documentar decisiones: olvidar registrar por qué se pospuso una funcionalidad, lo que genera discusiones recurrentes.

17.4 Ejemplo en Java: mal uso de DRY

Veamos cómo una abstracción exagerada puede complicar un simple cálculo de impuestos. El equipo extrajo una clase genérica sin considerar que cada país requiere reglas distintas.

// DRY mal aplicado: abstracción genérica difícil de mantener
class TaxCalculator<T> {
    private final Function<T, BigDecimal> baseExtractor;
    private final Function<T, BigDecimal> rateExtractor;

    TaxCalculator(Function<T, BigDecimal> baseExtractor,
                  Function<T, BigDecimal> rateExtractor) {
        this.baseExtractor = baseExtractor;
        this.rateExtractor = rateExtractor;
    }

    BigDecimal calculate(T item) {
        return baseExtractor.apply(item).multiply(rateExtractor.apply(item));
    }
}

En la práctica solo existen dos tipos de impuestos y las reglas cambian con frecuencia. Una solución específica, pero clara, simplifica el mantenimiento.

// Solución pragmática: lógica clara y extensible cuando aparezcan nuevos casos
final class ImpuestoService {
    BigDecimal calcularIva(Pedido pedido) {
        return pedido.subtotal().multiply(new BigDecimal("0.21"));
    }

    BigDecimal calcularIngresosBrutos(Pedido pedido) {
        return pedido.subtotal().multiply(new BigDecimal("0.035"));
    }
}

Si surge otro tipo de impuesto, se incorporará con evidencia. Mientras tanto, el código permanece legible y fácil de probar.

17.5 Estrategias para corregir el rumbo

  • Revisar periódicamente si las abstracciones aún tienen sentido; refactorizar cuando dejen de hacerlo.
  • Complementar KISS con pruebas de aceptación para asegurar que la simplicidad no sacrifica comportamiento.
  • Registrar en un ADR (Architecture Decision Record) las funcionalidades pospuestas por YAGNI, con fecha de reevaluación.
  • Combinar métricas (duplicación, complejidad ciclomática, lead time) para detectar desviaciones temprano.

17.6 Checklist de autodiagnóstico

  • ¿Las abstracciones responden a casos reales y verificados? (DRY)
  • ¿El código se entiende con una lectura tranquila, sin adivinar intenciones? (KISS)
  • ¿Cada funcionalidad tiene evidencia actual que justifique su existencia? (YAGNI)
  • ¿Hay pruebas automatizadas que respalden los cambios introducidos?
  • ¿El equipo documentó cuándo volver a evaluar las decisiones pospuestas?

Identificar y corregir estos errores mantiene a DRY, KISS y YAGNI como aliados para construir software de calidad, en lugar de transformarlos en reglas rígidas que frenan la entrega de valor.