Communitygithub.com

Diseño Guiado por el Dominio (DDD) — Patrones y Prácticas

Habilidades de ingeniería listas para usar y mejores prácticas para tu asistente de IA.

¿Qué es Diseño Guiado por el Dominio (DDD) — Patrones y Prácticas?

Esta habilidad proporciona un conjunto completo de patrones y prácticas de Domain-Driven Design (DDD) adaptados para asistentes de IA como Claude Code, Cursor y Codex. Está diseñada para ayudar a los desarrolladores a modelar lógica de negocio compleja, establecer límites transaccionales claros y evitar abstracciones con fugas. El skill cubre tanto diseño estratégico (Contextos Delimitados, Mapas de Contexto) como táctico (Entidades, Objetos Valor, Agregados, Eventos de Dominio, Servicios y Repositorios), e incluye ejemplos prácticos en TypeScript. También explica cuándo aplicar DDD (lógica de negocio compleja, aplicaciones empresariales) y cuándo evitarlo (CRUD simple, hackathons). La habilidad refuerza la regla de dependencia de Arquitectura Limpia, la separación entre Eventos de Dominio y Eventos de Integración, y el uso de Capas Anticorrupción para integrar sistemas externos. Incluye además una sección de solución de problemas y una lista de verificación de validación para evitar antipatrones comunes como los agregados dios o la fuga de infraestructura en la capa de dominio.

Compatible con✓Claude Code~Codex CLI~Cursor
npx skills add kok-o/koko-contextos-agents

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

¿Qué hace Diseño Guiado por el Dominio (DDD) — Patrones y Prácticas?

Cuándo Usar DDD

Úsalo cuando:

  • Lógica de negocio compleja que va más allá de CRUD
  • Múltiples expertos del dominio con diferentes vocabularios
  • El modelo de dominio es la ventaja competitiva
  • Aplicaciones de nivel empresarial

No lo uses cuando:

  • Aplicaciones CRUD simples
  • Hackathon/MVP (excesivo)
  • No hay experto del dominio disponible

Diseño Estratégico

Contextos Delimitados

El concepto más importante de DDD. Un Contexto Delimitado es un límite dentro del cual un modelo particular se define y es aplicable.

Ejemplo — Comercio Electrónico:

[Contexto de Pedido]      [Contexto de Pago]      [Contexto de Envío]
  - Pedido                  - Pago                  - Envío
  - ItemPedido              - Transacción            - NúmeroSeguimiento
  - Cliente (ref)           - Reembolso              - Dirección
  - Dirección (valor)       - Factura                - Transportista

Cliente significa cosas diferentes en cada contexto:

  • Contexto de Pedido: nombre, correo electrónico, preferencia de envío
  • Contexto de Pago: información de facturación, métodos de pago
  • Contexto de Soporte: historial de tickets, puntuación de satisfacción

Mapa de Contexto

[Pedido] ←→ [Pago]          # Asociación
[Pedido] → [Envío]          # Cliente-Proveedor
[Pedido] → [CRM heredado]   # Capa Anticorrupción

Diseño Táctico

Entidades

Objetos con identidad. Dos entidades con los mismos atributos pero IDs diferentes son diferentes.

class Usuario {
  readonly id: UsuarioId;
  nombre: string;
  correo: CorreoElectronico;  // Objeto Valor
}

Objetos Valor

Objetos definidos por sus atributos, no por su identidad. Inmutables.

class CorreoElectronico {
  constructor(readonly valor: string) {
    if (!esValidoCorreo(valor)) throw new ErrorCorreoInvalido(valor);
  }
  equals(otro: CorreoElectronico): boolean {
    return this.valor === otro.valor;
  }
}

Agregados

Un grupo de entidades y objetos valor con una única raíz de agregado (Raíz del Agregado). Todo el acceso pasa por la raíz.

class Pedido {  // Raíz del Agregado
  private items: ItemPedido[] = [];
  
  agregarItem(producto: ReferenciaProducto, cantidad: number): void {
    // Lógica de negocio AQUÍ, no en un servicio
    if (cantidad <= 0) throw new ErrorCantidadInvalida();
    this.items.push(new ItemPedido(producto, cantidad));
  }
  
  get total(): Dinero {
    return this.items.reduce((suma, item) => suma.sumar(item.subtotal), Dinero.cero());
  }
}

Reglas de Agregados:

  1. Referenciar otros agregados solo por ID
  2. Un agregado por transacción
  3. Consistencia eventual entre agregados

Eventos de Dominio

Algo que ocurrió en el dominio que los expertos del dominio consideran importante.

class PedidoRealizado implements EventoDeDominio {
  constructor(
    readonly idPedido: PedidoId,
    readonly idCliente: ClienteId,
    readonly total: Dinero,
    readonly ocurridoEn: Date
  ) {}
}

Servicios de Dominio

Lógica de negocio que no pertenece naturalmente a una entidad u objeto valor.

class ServicioDePrecios {
  calcularPrecio(pedido: Pedido, cliente: Cliente, promociones: Promocion[]): Dinero {
    // Lógica de precios compleja que involucra múltiples agregados
  }
}

Repositorios

Abstracción sobre el acceso a datos. Un repositorio por raíz de agregado.

interface RepositorioDePedidos {
  buscarPorId(id: PedidoId): Promise<Pedido | null>;
  guardar(pedido: Pedido): Promise<void>;
  eliminar(id: PedidoId): Promise<void>;
}

Estructura de Directorios (DDD)

src/
├── modulos/
│   └── pedidos/                    # Contexto Delimitado
│       ├── dominio/
│       │   ├── entidades/
│       │   │   └── pedido.ts       # Raíz del Agregado
│       │   ├── objetos-valor/
│       │   │   └── dinero.ts
│       │   ├── eventos/
│       │   │   └── pedido-realizado.ts
│       │   ├── servicios/
│       │   │   └── precios.ts
│       │   └── repositorios/
│       │       └── repositorio-pedido.ts  # Interfaz
│       ├── aplicacion/
│       │   ├── comandos/
│       │   │   └── realizar-pedido.ts
│       │   ├── consultas/
│       │   │   └── obtener-pedido.ts
│       │   └── manejadores/
│       │       └── realizar-pedido.manejador.ts
│       └── infraestructura/
│           ├── persistencia/
│           │   └── repositorio-pedido.impl.ts  # Implementación
│           └── api/
│               └── pedidos.controlador.ts

La Regla de Dependencia de la Arquitectura Limpia

En DDD, las dependencias DEBEN apuntar estrictamente hacia adentro:

[ Frameworks & Drivers (Web, DB, UI) ]
      └──▶ [ Adaptadores de Interfaz (Controladores, Gateways) ]
            └──▶ [ Aplicación (Casos de Uso, Manejadores CQRS) ]
                  └──▶ [ Dominio (Entidades, Objetos Valor) ]
  • La capa de Dominio tiene CERO dependencias de ORMs (Prisma, TypeORM), frameworks HTTP (Express, NestJS) o SDKs externos.
  • Los repositorios se definen como interfaces en la capa de dominio/aplicación y se implementan en la capa de infraestructura.

Eventos de Dominio vs Eventos de Integración

  1. Eventos de Dominio: Representan cambios de estado dentro de un único Contexto Delimitado.
    • Se lanzan directamente dentro de la Raíz del Agregado (pedido.agregarItem(...) lanza ItemAgregadoAlPedido).
    • Se despachan en proceso antes de la confirmación de la transacción.
  2. Eventos de Integración: Se publican a través de los límites del Contexto Delimitado para comunicarse con otros servicios.
    • Se despachan mediante el patrón Buzón de Salida Transaccional (Transactional Outbox) hacia brokers de mensajes.
    • Deben usar esquemas compatibles hacia atrás con versionado.

Capa Anticorrupción (ACL)

Al consumir datos de un contexto delimitado externo o de una API de proveedor de terceros (por ejemplo, Stripe, Salesforce):

  • NO importes modelos de dominio externos directamente en tu dominio.
  • Crea un Traductor / Adaptador ACL en la capa de infraestructura para convertir DTOs externos en tus propios Objetos Valor y Entidades.

Anti-patrones

  • [FALLA] Modelo de dominio anémico — entidades con solo getters/setters, toda la lógica en servicios
  • [FALLA] Agregado grande — los agregados deben ser pequeños, centrados en invariantes
  • [FALLA] Transacciones entre agregados — usa consistencia eventual
  • [FALLA] DDD en todas partes — usa DDD solo donde la complejidad lo justifique
  • [FALLA] Entidades ORM filtrándose en el Dominio — las entidades de dominio no deben depender de @Entity() ni de decoradores ORM

Ejemplos de Código

Consulta EXAMPLES.md para ejemplos de código detallados.

Lista de Verificación de Validación

Qué verificar durante la fase de revisión antes de completar la tarea.

Errores Comunes

Anti-patrones y cosas que evitar explícitamente. Consulta TROUBLESHOOTING.md.

Notas de Integración

Cómo interactúa esta habilidad con otras habilidades.

Skills relacionados