← dev-notes
CLEAN CODE · PARTE 2 DE 2

Clean Code
Estructura y diseño emergente

Clases, errores, límites y refactor continuo para sostener la calidad

00 Objetivo de esta parte
Meta: pasar de “código que funciona hoy” a “código que sigue funcionando y evolucionando en 6 meses”. Aquí el foco está en estructura, límites y refactor disciplinado.
01 Clases cohesionadas
🧱
01
Tamaño y foco
Una clase grande suele ocultar más de una responsabilidad. Divide por razón de cambio para reducir impacto en mantenimiento.
🔌
02
Bajo acoplamiento
Prefiere depender de abstracciones y contratos claros, no de detalles concretos de infraestructura.
🧩
03
API mínima
Exponer menos reduce mal uso y hace más fácil refactorizar internals sin romper consumidores.
MAL VS BIEN — CLASE CON RESPONSABILIDADES MEZCLADAS
// Mal: dominio + persistencia + notificación en una sola clase
public class InvoiceService {
    public void closeInvoice(Invoice invoice) {
        invoice.markAsClosed();
        jdbcTemplate.update("update invoices set status='CLOSED' where id=?", invoice.id());
        smtpClient.send(invoice.customerEmail(), "Factura cerrada");
    }
}

// Bien: caso de uso orquesta contratos, cada detalle afuera
public final class CloseInvoiceUseCase {
    private final InvoiceRepository invoices;
    private final NotificationPort notifications;

    public void execute(InvoiceId id) {
        Invoice invoice = invoices.findById(id).orElseThrow();
        invoice.close();
        invoices.save(invoice);
        notifications.invoiceClosed(invoice);
    }
}
02 Errores y manejo de excepciones
🛑
04
Fail fast y mensajes útiles
Lanza errores temprano con contexto relevante para diagnóstico. Evita “Exception” genérica sin información.
🧭
05
Límite de traducción
Traduce errores técnicos a errores de dominio en fronteras de módulo para no propagar detalles internos.
Error técnico filtrado
Exponer `SQLException` o mensajes del proveedor al dominio/cliente rompe encapsulamiento.
Error de dominio traducido
Mapear fallos de infraestructura a errores de negocio permite decisiones claras y estables.
03 Diseño emergente por refactor
06
Paso pequeño y seguro
Refactoriza en cambios acotados con feedback de tests para evitar regresiones silenciosas.
🔎
07
Eliminar duplicación
La duplicación no es solo código igual: también reglas replicadas en múltiples capas.
📉
08
Complejidad accidental
Cada nueva abstracción debe pagar renta. Si no simplifica lectura o cambio, probablemente sobra.
04 Flujo didáctico de refactor
1
PASO
Asegura comportamiento
Primero protege con tests el comportamiento actual (aunque esté feo).
2
PASO
Refactor mínimo
Extrae una responsabilidad o simplifica una función por iteración.
3
PASO
Ejecuta tests
Si algo rompe, revierte rápido; el objetivo es progreso seguro, no heroísmo.
4
PASO
Consolida reglas
Al final, documenta decisiones de diseño y patrones de uso para el equipo.
Checklist final antes de merge:
  • ¿Cada clase tiene una razón de cambio clara?
  • ¿Los errores se traducen en los límites del módulo?
  • ¿Las abstracciones nuevas reducen complejidad real?
  • ¿El diff mejora legibilidad sin cambiar comportamiento accidentalmente?