Marcio Cunha

Como desenhar um Domain Model resiliente usando DDD

Aprenda a aplicar Domain-Driven Design para separar regras de negócio de detalhes de infraestrutura, mantendo o código flexível.

Marcio Cunha•5 min
Também disponível em:EspañolEnglish
Resumo
  • O modelo de domínio isola as regras do negócio de detalhes mutáveis como bancos de dados
  • Entidades e Objetos de Valor evitam que o código vire um depósito de lógica procedural
  • A infraestrutura deve servir ao domínio, e nunca o inverso na arquitetura limpa
  • Agregados protegem invariantes garantindo consistência estrita em transações complexas
  • A separação rigorosa facilita testes automatizados sem acoplamento a frameworks pesados

Por que misturar regras de negócio e infraestrutura destrói sistemas

Quando começamos a construir um sistema, a tentação de colocar tudo junto em um único lugar é enorme. Criamos tabelas no banco de dados e logo escrevemos o código que lê e grava esses dados misturado com validações complexas, regras de desconto e cálculos fiscais. No início, parece rápido e eficiente. Contudo, conforme o software cresce, qualquer mudança simples na forma como cobramos um cliente ou calculamos um frete exige mexer em consultas de banco de dados, mapeamentos e até frameworks inteiros. Na prática, isso significa que o seu sistema perde flexibilidade, tornando-se caro e doloroso para manter a longo prazo.

O problema central dessa abordagem é o acoplamento excessivo, que é quando diferentes partes do código grudam de tal forma que você não consegue mexer em uma sem quebrar a outra. Se o seu banco de dados muda, suas regras de negócio quebram. Se a regra fiscal muda, você precisa reescrever trechos ligados à persistência de dados. Para resolver esse dilema de engenharia, arquitetos recorrem a abordagens consagradas, como discutimos ao explorar como desenhar um sistema resiliente com CQRS e Kafka, onde a separação de responsabilidades garante que falhas pontuais não derrubem a aplicação inteira. O objetivo principal passa a ser proteger a lógica do negócio contra ventos externos de mudanças tecnológicas.

O que é um Domain Model e como ele protege sua aplicação

O Domain Model, ou modelo de domínio, é a representação em código do mundo real que a sua empresa atua. Se você trabalha em um e-commerce, o modelo contém conceitos como Carrinho de Compras, Pedido, Pagamento e Cliente, contendo não apenas dados estáticos, mas principalmente o comportamento e as regras que regem esses elementos. Em vez de ter estruturas de dados anêmicas que servem apenas para carregar propriedades, o domínio possui inteligência própria. Quando um cliente tenta fechar um pedido sem saldo, é o próprio objeto Pedido que valida e recusa a operação, garantindo que regras vitais nunca fiquem espalhadas por controladores web ou scripts soltos.

Isso contrasta diretamente com o modelo tradicional de banco de dados centralizado, onde o modelo de dados dita o fluxo da aplicação. No Domain-Driven Design (DDD), a modelagem parte de uma linguagem ubíqua, um vocabulário compartilhado entre desenvolvedores e especialistas da área de negócios. Assim, termos como 'estorno', 'reserva de estoque' ou 'crédito pendente' significam exatamente a mesma coisa tanto na conversa com o gerente de produtos quanto nas classes do código-fonte. Esse alinhamento reduz drasticamente mal-entendidos e garante que o software reflita com precisão cirúrgica a operação da empresa, facilitando a evolução contínua da arquitetura.

Isolando o núcleo de negócio dos detalhes técnicos

Isolar o núcleo de negócio significa erguer barreiras firmes para que tecnologias de infraestrutura — como bancos relacionais, filas de mensagens, bibliotecas de serialização JSON ou frameworks web — permaneçam na periferia da aplicação. O núcleo, muitas vezes chamado de camada de domínio, deve ser puro e focado em lógica corporativa pura, sem conhecer detalhes sobre como os dados serão salvos. Para que isso funcione na prática, utilizamos padrões arquiteturais onde a infraestrutura depende do domínio, e nunca o inverso. Quando precisamos persistir um objeto, criamos contratos conhecidos como repositórios, que definem apenas o que precisa ser guardado, deixando os detalhes de implementação para as camadas externas.

Essa inversão de dependência muda radicalmente a forma como escrevemos testes e mantemos o software. Se você precisa testar uma regra complexa de cálculo de juros, não precisa mais subir um banco de dados em memória ou configurar conexões de rede pesadas. O teste roda em frações de segundo porque a lógica de negócio é isolada e desacoplada de qualquer dependência externa. Esse mesmo princípio de separação de fluxos e responsabilidades pode ser visto quando aplicamos estratégias avançadas de processamento assíncrono, tema que abordamos em detalhes ao analisar como implementar CQRS assíncrono em APIs de alto tráfego para garantir alta performance sob forte pressão de requisições.

Entidades, Value Objects e Agregados na prática

Para construir esse modelo resiliente, o DDD fornece blocos de construção fundamentais conhecidos como Entidades, Objetos de Valor e Agregados. Uma Entidade é um objeto que possui uma identidade única e contínua ao longo do tempo, independentemente de seus atributos mudarem — como um usuário que altera seu endereço de e-mail, mas continua sendo o mesmo usuário no sistema. Já os Value Objects (Objetos de Valor) são imutáveis e definidos exclusivamente por seus valores. Um endereço postal, uma quantia monetária ou um intervalo de datas são exemplos perfeitos: se o valor muda, criamos um novo objeto em vez de modificar o anterior, eliminando efeitos colaterais indesejados no código.

Os Agregados, por sua vez, agrupam entidades e objetos de valor relacionados em uma unidade coesa de transação. O agregado possui uma raiz (aggregate root), que é o único ponto de entrada para modificar o estado interno do grupo, garantindo que nenhuma regra de negócio seja violada por alterações parciais ou inconsistentes. Por exemplo, em um pedido de compra, os itens e o endereço de entrega pertencem ao agregado do Pedido. Modificações nesses dados passam obrigatoriamente pela raiz do pedido, que valida o estado geral antes de confirmar qualquer alteração. Essa estrutura protege a consistência dos dados mesmo em ambientes altamente concorrentes, evitando corrupções no banco de dados.

Considerações finais sobre a construção de domínios robustos

Projetar um Domain Model resiliente exige esforço inicial, disciplina e um alinhamento constante entre a equipe técnica e os especialistas de negócio. Embora pareça mais trabalhoso do que criar scripts diretos conectados ao banco, o retorno sobre o investimento aparece logo na primeira grande mudança de requisitos da empresa. Quando o negócio evolui, o software evolui com ele de forma limpa, sem quebrar funcionalidades legadas e sem exigir reescritas completas. Ao blindar as regras corporativas contra as oscilações tecnológicas, você constrói sistemas duráveis, fáceis de testar e preparados para crescer com estabilidade e segurança por muitos anos.