Communitygithub.com

Design Orientado a Domínio (DDD) — Padrões e Práticas

Habilidades de engenharia prontas para uso e melhores práticas para seu assistente de IA.

O que é Design Orientado a Domínio (DDD) — Padrões e Práticas?

Esta skill fornece um guia abrangente e prático sobre Domain-Driven Design (DDD), cobrindo desde a tomada de decisão sobre quando usar DDD até padrões estratégicos e táticos. É ideal para desenvolvedores e arquitetos de software que constroem sistemas empresariais complexos com lógica de negócio sofisticada. A skill detalha conceitos fundamentais como Contextos Delimitados (Bounded Contexts), Entidades, Objetos de Valor, Agregados, Eventos de Domínio e Serviços de Domínio, sempre acompanhados de exemplos de código em TypeScript e diagramas claros. Ela enfatiza a importância da arquitetura limpa (Clean Architecture), a separação rigorosa entre a lógica de domínio e a infraestrutura, e fornece uma estrutura de diretórios pronta para uso. Além disso, a skill alerta sobre antipadrões comuns, como o modelo de domínio anêmico e agregados muito grandes, e inclui uma seção de solução de problemas para ajudar a evitar erros frequentes na prática. Projetada para funcionar em qualquer assistente de IA que suporte definições de skill, ela organiza o conhecimento em um formato estruturado que pode ser ativado sob demanda ao projetar modelos de domínio críticos, limites de consistência transacional ou APIs empresariais.

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

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Design Orientado a Domínio — Padrões & Práticas

Quando Usar DDD

Use quando:

  • Lógica de negócio complexa que vai além de CRUD
  • Múltiplos especialistas de domínio com vocabulários diferentes
  • O modelo de domínio é a vantagem competitiva
  • Aplicações de nível empresarial

Não use quando:

  • Aplicações CRUD simples
  • Hackathon/MVP (exagero)
  • Nenhum especialista de domínio disponível

Design Estratégico

Contextos Delimitados

O conceito mais importante do DDD. Um Contexto Delimitado é um limite dentro do qual um modelo específico é definido e aplicável.

Exemplo — E-Commerce:

[Contexto Pedido]          [Contexto Pagamento]       [Contexto Envio]
  - Pedido                  - Pagamento               - Remessa
  - ItemPedido              - Transação                - CódigoRastreio
  - Cliente (ref)           - Reembolso                - Endereço
  - Endereço (valor)        - Fatura                   - Transportadora

Cliente significa coisas diferentes em cada contexto:

  • Contexto Pedido: nome, e-mail, preferência de envio
  • Contexto Pagamento: informações de faturamento, métodos de pagamento
  • Contexto Suporte: histórico de tickets, pontuação de satisfação

Mapa de Contexto

[Pedido] ←→ [Pagamento]     # Parceria
[Pedido] → [Envio]          # Cliente-Fornecedor
[Pedido] → [CRM Legado]     # Camada Anticorrupção

Design Tático

Entidades

Objetos com identidade. Duas entidades com os mesmos atributos, mas IDs diferentes, são diferentes.

class Usuario {
  readonly id: UsuarioId;
  nome: string;
  email: Email;  // Objeto de Valor
}

Objetos de Valor

Objetos definidos por seus atributos, não pela identidade. Imutáveis.

class Email {
  constructor(readonly value: string) {
    if (!isValidEmail(value)) throw new InvalidEmailError(value);
  }
  equals(other: Email): boolean {
    return this.value === other.value;
  }
}

Agregados

Um cluster de entidades e objetos de valor com uma única raiz (Raiz do Agregado). Todo acesso passa pela raiz.

class Pedido {  // Raiz do Agregado
  private items: ItemPedido[] = [];

  addItem(produto: ReferenciaProduto, quantidade: number): void {
    // Lógica de negócio AQUI, não em um serviço
    if (quantidade <= 0) throw new InvalidQuantityError();
    this.items.push(new ItemPedido(produto, quantidade));
  }

  get total(): Dinheiro {
    return this.items.reduce((soma, item) => soma.add(item.subtotal), Dinheiro.zero());
  }
}

Regras do Agregado:

  1. Referencie outros agregados apenas por ID
  2. Um agregado por transação
  3. Consistência eventual entre agregados

Eventos de Domínio

Algo que aconteceu no domínio e que os especialistas de domínio se importam.

class PedidoRealizado implements EventoDominio {
  constructor(
    readonly pedidoId: PedidoId,
    readonly clienteId: ClienteId,
    readonly total: Dinheiro,
    readonly ocorridoEm: Date
  ) {}
}

Serviços de Domínio

Lógica de negócio que não pertence naturalmente a uma entidade ou objeto de valor.

class ServicoPrecificacao {
  calcularPreco(pedido: Pedido, cliente: Cliente, promocoes: Promocao[]): Dinheiro {
    // Lógica de precificação complexa envolvendo múltiplos agregados
  }
}

Repositórios

Abstração sobre acesso a dados. Um repositório por raiz de agregado.

interface RepositorioPedido {
  buscarPorId(id: PedidoId): Promise<Pedido | null>;
  salvar(pedido: Pedido): Promise<void>;
  deletar(id: PedidoId): Promise<void>;
}

Estrutura de Diretórios (DDD)

src/
├── modulos/
│   └── pedidos/                    # Contexto Delimitado
│       ├── dominio/
│       │   ├── entidades/
│       │   │   └── pedido.ts       # Raiz do Agregado
│       │   ├── objetos-de-valor/
│       │   │   └── dinheiro.ts
│       │   ├── eventos/
│       │   │   └── pedido-realizado.ts
│       │   ├── servicos/
│       │   │   └── precificacao.ts
│       │   └── repositorios/
│       │       └── pedido.repository.ts  # Interface
│       ├── aplicacao/
│       │   ├── comandos/
│       │   │   └── realizar-pedido.ts
│       │   ├── consultas/
│       │   │   └── obter-pedido.ts
│       │   └── manipuladores/
│       │       └── realizar-pedido.handler.ts
│       └── infraestrutura/
│           ├── persistencia/
│           │   └── pedido.repository.impl.ts  # Implementação
│           └── api/
│               └── pedidos.controller.ts

A Regra de Dependência da Arquitetura Limpa

Em DDD, as dependências DEVEM apontar estritamente para dentro:

[ Frameworks & Drivers (Web, BD, UI) ]
      └──▶ [ Adaptadores de Interface (Controllers, Gateways) ]
            └──▶ [ Aplicação (Casos de Uso, Handlers CQRS) ]
                  └──▶ [ Domínio (Entidades, Objetos de Valor) ]
  • A camada de Domínio tem ZERO dependências de ORMs (Prisma, TypeORM), frameworks HTTP (Express, NestJS) ou SDKs externos.
  • Repositórios são definidos como interfaces na camada de domínio/aplicação e implementados na camada de infraestrutura.

Eventos de Domínio vs Eventos de Integração

  1. Eventos de Domínio: Representam mudanças de estado dentro de um único Contexto Delimitado.
    • Acionados diretamente dentro da Raiz do Agregado (pedido.adicionarItem(...) aciona ItemAdicionado).
    • Despachados em processo antes do commit da transação.
  2. Eventos de Integração: Publicados através dos limites dos Contextos Delimitados para comunicar com outros serviços.
    • Despachados via padrão Transactional Outbox para brokers de mensagens.
    • Devem usar esquemas compatíveis com versões anteriores.

Camada Anticorrupção (ACL)

Ao consumir dados de um contexto delimitado externo ou API de fornecedor terceirizado (ex.: Stripe, Salesforce):

  • NUNCA importe modelos de domínio externos diretamente para o seu domínio.
  • Crie um Tradutor/Adaptador ACL na camada de infraestrutura para converter DTOs externos em seus próprios Objetos de Valor e Entidades.

Antipadrões

  • [FALHA] Modelo de domínio anêmico — entidades com apenas getters/setters, toda a lógica em serviços
  • [FALHA] Agregado grande — agregados devem ser pequenos, focados em invariantes
  • [FALHA] Transações entre agregados — use consistência eventual
  • [FALHA] DDD em todo lugar — use DDD apenas onde a complexidade justifica
  • [FALHA] Entidades ORM vazando para o Domínio — entidades de domínio não devem depender de @Entity() ou decoradores ORM

Exemplos de Código

Consulte EXAMPLES.md para exemplos de código detalhados.

Lista de Verificação de Validação

O que verificar durante a fase de revisão antes de concluir a tarefa.

Erros Comuns

Antipadrões e coisas a evitar explicitamente. Consulte TROUBLESHOOTING.md.

Notas de Integração

Como esta skill interage com outras skills.

Habilidades Relacionadas