O que é Domain-Driven Design?

Domain-Driven Design (DDD), ou design orientado ao domínio, é uma abordagem para desenvolver software em domínios complexos por meio de colaboração contínua entre especialistas do negócio e pessoas desenvolvedoras. Eric Evans sistematizou a abordagem no livro Domain-Driven Design: Tackling Complexity in the Heart of Software, publicado em 2003. DDD não é sinônimo de usar objetos com nomes de negócio; é uma forma de aprender, comunicar e modelar as regras que diferenciam o produto.

O domínio é a área de conhecimento e atividade que o software apoia: logística, seguros, pagamentos, saúde ou qualquer contexto. A complexidade costuma estar menos em salvar dados e mais em entender o significado de estados, exceções, responsabilidades e decisões. DDD direciona esforço para o coração do problema, onde um modelo melhor pode produzir valor.

Linguagem ubíqua: o modelo compartilhado

Uma linguagem ubíqua é um vocabulário compartilhado por especialistas e equipe técnica, usado em conversas, documentação, testes e código. Se o negócio distingue “reserva solicitada”, “confirmada” e “expirada”, esses termos devem ter significados explícitos. Uma palavra ambígua como “processar” pode esconder operações muito diferentes.

A linguagem não nasce pronta num glossário. Ela é refinada por conversas e exemplos: “O que acontece se o pagamento for aprovado depois da expiração?” Uma resposta pode revelar uma regra que o modelo precisa representar. Nomes de métodos e eventos tornam-se uma forma de verificar se o código expressa o entendimento atual, não uma tradução literal e imutável do vocabulário de negócio.

Bounded Contexts: limites para modelos coerentes

Um bounded context, ou contexto delimitado, é uma fronteira dentro da qual um modelo e seus termos têm significado consistente. “Produto” no catálogo pode representar uma oferta comercial; no estoque pode representar um item físico com localização; em faturamento pode ser uma linha tributável. Tentar impor uma única classe universal pode produzir um modelo cheio de campos opcionais e regras contraditórias.

Contextos podem ser implementados como módulos de um monólito ou como serviços separados. DDD não manda criar microsserviços. A fronteira é primeiro semântica e organizacional; a decisão de distribuição inclui custo operacional, necessidade de autonomia e consistência. Contextos precisam conversar por contratos explícitos, e um contexto pode traduzir o modelo de outro por uma camada anticorrupção.

Entidades, objetos de valor e agregados

Entidades e objetos de valor

Uma entidade é reconhecida pela identidade ao longo do tempo, mesmo que alguns atributos mudem: um pedido continua sendo o mesmo pedido depois de mudar de estado. Um objeto de valor é definido pelo conjunto de seus atributos e normalmente é imutável: Dinheiro com valor e moeda, ou um intervalo de datas. Objetos de valor ajudam a impedir combinações inválidas, como somar dólares a reais sem uma regra explícita.

Agregados e invariantes

Um agregado é um grupo de objetos tratados como uma unidade de consistência; uma raiz controla as alterações externas e protege invariantes. Se a regra exige que o total de itens de um pedido não seja negativo, operações de inclusão e remoção devem manter essa condição. O agregado não é simplesmente um grafo de objetos persistidos juntos: agregados grandes aumentam contenção e dificultam concorrência.

Uma boa regra prática é manter agregados pequenos e definir transações em torno das invariantes que precisam ser imediatas. Outras atualizações podem ocorrer de forma eventual por eventos e processos de aplicação, quando o domínio aceita essa semântica. Essa escolha precisa refletir requisitos reais, não uma preferência abstrata por consistência eventual.

Serviços e eventos de domínio

Um serviço de domínio expressa uma operação significativa que não pertence naturalmente a uma única entidade ou objeto de valor. Ele deve continuar sendo lógica de domínio, não uma sacola genérica de métodos. Um evento de domínio representa um fato que aconteceu, como PagamentoAutorizado ou PedidoExpedido. O nome no passado ajuda a distinguir fato de solicitação.

Eventos podem permitir que reações evoluam sem encher o agregado de dependências externas. Ainda assim, publicar eventos envolve falhas e consistência. Se um estado precisa ser salvo junto com uma mensagem para outro sistema, uma estratégia como outbox pode evitar perder a publicação após a gravação. Eventos internos do domínio não precisam ser automaticamente eventos públicos de integração; esses contratos têm públicos e ciclos de vida diferentes.

Como DDD se combina com Clean Architecture

DDD ajuda a responder “quais são os conceitos e regras do domínio?”; Clean Architecture ajuda a responder “como impedir que o modelo dependa de tecnologia externa?”. Um modelo rico pode ficar no núcleo, casos de uso coordenam intenções, e adaptadores conectam HTTP, banco e mensageria. As abordagens se complementam, mas nenhuma exige usar todos os padrões da outra.

Uma camada de domínio não é automaticamente DDD: se contém apenas classes anêmicas geradas a partir de tabelas, falta modelagem de comportamento e linguagem. E DDD não exige Clean Architecture: seus conceitos podem ser aplicados em diferentes arquiteturas. O importante é proteger a linguagem do domínio e manter dependências adequadas à escala do sistema. Veja o guia de Clean Architecture com exemplos em C#.

Como começar sem exagerar

  1. Escolha uma área de negócio com regras relevantes, não uma tabela isolada.
  2. Converse com especialistas e registre exemplos concretos, incluindo exceções.
  3. Identifique palavras ambíguas e refine uma linguagem compartilhada.
  4. Desenhe limites de contexto antes de decidir se precisa de serviços separados.
  5. Modele invariantes importantes em operações explícitas e teste seus cenários.
  6. Revise o modelo à medida que a equipe aprende; o domínio real pode contradizer a primeira hipótese.

Não aplique agregados, eventos ou serviços de domínio por checklist. Um CRUD simples pode permanecer simples. DDD vale o investimento quando linguagem, regras e colaboração reduzem a complexidade do negócio e ajudam a equipe a entregar comportamento correto.