Alejandría

Busca en Alejandría

Técnicas

Domain-Driven Design (DDD)

Alinea el diseño del software con el dominio del negocio mediante lenguaje compartido y límites explícitos.

01

En pocas palabras

Conjunto de patrones estratégicos (subdominios, bounded contexts, context mapping) y tácticos (agregados, entidades, eventos de dominio) para modelar dominios complejos.

Qué problema resuelve

Modelos únicos y gigantes donde «cliente» o «crédito» significan cosas distintas para cada área, con acoplamiento entre equipos y servicios.

Cuándo utilizarlo

Dominios con reglas de negocio ricas y varios equipos. Ejemplo: separar originación, cobranza y contabilidad de una plataforma de crédito.

02

De la idea a la práctica

Funcionamiento, ejemplos y decisiones para pasar al siguiente nivel.

Diseño estratégico

Subdominios. Clasifica las áreas del negocio para decidir dónde invertir:

Tipo Descripción Estrategia típica
Core Lo que diferencia a la empresa (p. ej. scoring) Construir con el mejor equipo
Soporte Necesario y específico, pero no diferencial Construir sencillo o externalizar
Genérico Resuelto en el mercado (identidad, pagos, correo) Comprar o usar SaaS

Lenguaje ubicuo. Cada término tiene un significado preciso dentro de un contexto y aparece igual en conversaciones, código, tablas y eventos. Si negocio dice «desembolso» y el código transfer, hay una traducción oculta que producirá errores.

Bounded context. Límite explícito dentro del cual un modelo es consistente. «Cliente» en Originación (solicitante con ingresos y documentos) no es el mismo «Cliente» que en Cobranza (deudor con saldo y canal de contacto). Forzar un único modelo crea una entidad enorme que nadie puede cambiar.

Context mapping

Describe cómo se relacionan los contextos y, de paso, los equipos:

Patrón Cuándo usarlo
Customer / Supplier El proveedor (upstream) prioriza necesidades del consumidor (downstream)
Conformist El downstream adopta el modelo del upstream tal cual (p. ej. un SaaS)
Anti-Corruption Layer El downstream traduce el modelo ajeno para proteger el propio
Open Host / Published Language Upstream ofrece una API o esquema estable y documentado para muchos
Shared Kernel Dos equipos comparten una parte pequeña del modelo; exige coordinación alta
Separate Ways Integrarse no compensa; se duplica deliberadamente

Al integrar con un buró de crédito o un core bancario heredado, una ACL evita que sus códigos y estructuras se filtren por todo tu dominio.

Diseño táctico

  • Entidad: identidad que persiste en el tiempo (Solicitud#123).
  • Value object: definido por sus atributos, inmutable (Dinero(1500, COP)).
  • Agregado: grupo de objetos con una raíz que garantiza invariantes; es la unidad de consistencia transaccional. Referencia a otros agregados por id, no por objeto.
  • Evento de dominio: hecho pasado relevante para el negocio (SolicitudAprobada).
  • Repositorio y servicio de dominio: acceso a agregados y lógica que no pertenece a una entidad.
public final class Solicitud {               // raíz del agregado
    private final SolicitudId id;
    private Estado estado;
    private final Dinero montoSolicitado;
    private final List<Object> eventos = new ArrayList<>();

    public void aprobar(Dinero montoAprobado, Politica politica) {
        if (estado != Estado.EN_EVALUACION)
            throw new IllegalStateException("Solo se aprueba en evaluación");
        if (montoAprobado.mayorQue(politica.montoMaximo()))
            throw new ReglaDeNegocioVioladaException("Excede el máximo");
        estado = Estado.APROBADA;
        eventos.add(new SolicitudAprobada(id, montoAprobado, Instant.now()));
    }
}

La invariante vive en el agregado, no en un controlador ni en un if repartido en tres servicios.

Cómo descubrir los límites

Combina talleres colaborativos: domain storytelling para entender procesos, Event Storming para ordenar eventos de dominio en el tiempo y detectar agregados y contextos, y el Bounded Context Canvas (DDD Crew) para documentar cada contexto: propósito, lenguaje, entradas, salidas y decisiones de negocio.

Antipatrones frecuentes

  • Modelo anémico: entidades con getters y setters y toda la lógica en servicios.
  • Agregados enormes: cargar el cliente con todos sus créditos y pagos para cambiar un teléfono. Mantenlos pequeños y usa consistencia eventual entre ellos.
  • DDD táctico sin estratégico: usar repositorios y value objects en un monolito sin límites no resuelve el acoplamiento.
  • Un contexto por tabla: fragmentar en exceso produce microservicios distribuidos acoplados.

Event Storming en tres niveles

Nivel Objetivo Participantes
Big picture Visión de todo el dominio y sus puntos de dolor Negocio, operaciones, tecnología (10–25 personas)
Proceso Detallar un flujo con reglas y actores Expertos del proceso y equipo
Diseño Agregados, comandos e invariantes para construir Equipo de desarrollo y experto

Notación habitual con notas adhesivas: eventos en pasado (naranja: «Solicitud enviada»), comandos (azul: «Aprobar solicitud»), actores (amarillo), políticas («cuando X, entonces Y»), sistemas externos, modelos de lectura y puntos calientes (dudas y conflictos, en rosa).

Ejemplo de context map para una plataforma de crédito

              ┌──────────────┐  Published Language  ┌──────────────┐
              │ Originación  │ ───── eventos ─────► │   Riesgos    │
              │ (core)       │ ◄── Customer/Supplier│ (core)       │
              └──────┬───────┘                      └──────────────┘
                     │ eventos
          ┌──────────▼───────┐       ACL        ┌────────────────────┐
          │    Cartera       │ ◄─────────────── │ Core bancario      │
          │   (soporte)      │                  │ heredado (externo) │
          └──────┬───────────┘                  └────────────────────┘
                 │ Open Host Service
     ┌───────────▼──────┐        Conformist       ┌───────────────┐
     │    Cobranza      │ ──────────────────────► │ Proveedor SMS │
     └──────────────────┘                         └───────────────┘

El mapa muestra, además de dependencias técnicas, relaciones de poder entre equipos: quién se adapta a quién.

Reglas para diseñar agregados

  1. Modela invariantes reales dentro del límite de consistencia: solo lo que debe ser consistente en la misma transacción.
  2. Diseña agregados pequeños: una raíz y pocos objetos.
  3. Referencia otros agregados por identidad, no por objeto.
  4. Usa consistencia eventual fuera del límite, mediante eventos de dominio.

Ejemplo: «el total pagado no puede superar el saldo» es una invariante del agregado Credito; «al aprobar una solicitud se crea un crédito» se resuelve con un evento entre dos agregados, no en una transacción gigante.

Estructura de código por contexto

originacion/
├── dominio/          # Solicitud, Dinero, Politica, eventos; sin dependencias de frameworks
├── aplicacion/       # casos de uso: EnviarSolicitud, AprobarSolicitud; puertos (interfaces)
├── infraestructura/  # adaptadores: JPA, Kafka, cliente del buró (ACL)
└── web/              # controladores REST, DTOs

Esta organización (arquitectura hexagonal o de puertos y adaptadores) protege el modelo de dominio de los cambios técnicos y se puede vigilar con fitness functions.

Criterios de implementación

Aplica DDD completo en el subdominio core; en los genéricos basta un CRUD o un producto. Alinea los contextos con equipos (Team Topologies) y usa eventos con el transactional outbox para integrarlos sin transacciones distribuidas.

Continúa en las fuentes

Documentación oficial para verificar detalles y explorar más.