SuperAPI AI Directory

ddd

Design & creation

View repository

Updated 10-15 20:31

About this skill

Domain-Driven Design

O modelo é o software. Linguagem ubíqua no código. DDD não é pastas Domain/ com getters — é invariantes protegidas por agregados e contextos com limites claros.

Escolha de estilo: software-architecture. Setas de dependência: clean-architecture. Um deploy, vários contextos: modular-monolith. Extração: microservices-architecture.

Quando (não) usar

Use quando regras, conflitos de linguagem e ciclos de vida de dado forem o risco.

Não use (tático pesado) em CRUD, BFF fino, jobs de glue. Ali, transações simples e DTOs bastam. Strategic (nomes de contexto) ainda ajuda.

Estratégico

Linguagem ubíqua

  • Os termos do domínio aparecem em tipos, métodos e eventos — não ManagerUtil, DataDTO2.
  • Se o negócio diz “reserva” e o código diz “OrderItemFlag`, o modelo está errado.
  • Glossário curto por contexto; o mesmo termo não significa a mesma coisa em outro contexto (Pagamento ≠ Fatura).

Bounded context

  • Um contexto = um modelo + uma equipe mental. API pública; interior privado.
  • Mapa: parente (upstream/downstream), ACL, shared kernel (mínimo), customer/supplier.
  • Integração entre contextos: eventos ou ACL — não join de tabelas nem import de entidades internas.
Vendas  --OrderPlaced-->  Fulfillment
Vendas  --ACL-->          Legado ERP
  • Um contexto ≠ um microsserviço obrigatório. Pode ser módulo no monolito.

Tático

Bloco Papel
Entity Identidade + ciclo de vida
Value object Igualdade por valor, imutável
Aggregate Fronteira de consistência; um root
Domain event Algo que aconteceu no domínio
Repository Reconstitui agregados (não “DAO de tabela”)
Domain service Regra que não cabe numa entidade
Application service / use case Orquestra 1 transação / 1 comando

Agregado

  • Invariantes dentro do root. Nada de fora altera filhos sem passar pelo root.
  • Referências entre agregados por ID, não por objeto navegável enorme.
  • Pequeno: transação = um agregado. “God aggregate” é monolito dentro do contexto.
  • Persistência: carrega o agregado, aplica comando, salva. Sem entity semi-gráfica espalhada na UI.
Order (root)
  ├── OrderLine (entity interna)
  └── Money (VO)
outro agregado: Customer  →  só customerId dentro de Order

Eventos de domínio

  • Nome no passado (OrderPlaced). Payload mínimo + IDs.
  • Publicado após o commit (outbox se cruzar processo) — event-driven-architecture.
  • Não use evento para “chamar o outro serviço sincronicamente”.

Repositório

  • Get(id), Save(aggregate). Queries de tela/listagem não precisam passar pelo agregado — modelo de leitura (cqrs se divergir).
  • Implementação na infra; interface no domínio (Clean) se o projeto já inverte dependências.

Application vs Domain

  • Use case: autentica contexto, carrega agregado, chama domínio, persiste, dispara evento.
  • Domínio: sem HTTP, sem SQL, sem framework de web. Relógio/IDs injetados se a regra precisar.

Anti-padrões

  • Anemic domain: entidades só dados + “service” procedural de 2k linhas
  • Agregado = banco inteiro
  • DDD pasta copiada (Entities, DTOs, Interfaces) sem invariante
  • Shared kernel com 40 tipos “comuns”
  • Repositório GetAll + filtro na aplicação para regra que era do agregado
  • Bounded context por tabela

Integração com outras skills

  • Decisão: software-architecture
  • Dependências: clean-architecture
  • Módulos: modular-monolith
  • Reads vs writes: cqrs
  • Integração assíncrona: event-driven-architecture
  • Serviços: microservices-architecture
  • Authz no agregado/contexto dono: authentication-authorization

Critérios de conclusão

  • Contextos e linguagem visíveis no código
  • Agregados com invariante e transação clara
  • Referência cross-aggregate por ID
  • Eventos no passado, após persistência
  • Sem DDD tático onde o domínio é CRUD