Desenvolvimento Orientado a Domínio: modelagem, implementação e testes de qualidade
Desenvolvimento Orientado a Domínio (DDD) é uma abordagem de design de software que coloca as regras e a linguagem do negócio no centro das decisões técnicas. Em vez de começar pelo framework ou banco de dados, o time parte do domínio — suas entidades, eventos e fronteiras — para só então definir a implementação. Para produtos complexos como plataformas de assinaturas, meios de pagamento ou ERPs, essa escolha deixa de ser opcional e passa a ser estratégica.
Este artigo cobre o caminho completo: do desenho estratégico com Event Storming até a cobertura de testes orientada ao domínio, com exemplos práticos e métricas acionáveis.
Por que DDD importa para sistemas complexos
Negócios digitais maduros lidam com regulamentações mutáveis, integrações com parceiros, jornadas omnichannel e produtos que evoluem em ciclos curtos. Um código centrado apenas em CRUDs e endpoints não sustenta essa complexidade por muito tempo.
Publicações recentes da Locaweb e da Rocketseat confirmam que DDD se consolidou como abordagem para domínios complexos, microserviços e arquiteturas distribuídas — não como teoria, mas como prática de times que precisam manter estabilidade sem sacrificar velocidade de entrega.
DDD ajuda a:
- Reduzir acoplamento ao separar o sistema em Contextos Delimitados coerentes.
- Melhorar a comunicação entre negócio, desenvolvimento e QA por meio da Linguagem Ubíqua.
- Aumentar a capacidade de evolução sem reescrever tudo a cada mudança de regra.
Uma decisão prática antes de adotar: se o sistema tem regras simples, fluxo previsível e baixo nível de incerteza, DDD provavelmente é exagero. Se o domínio é complexo, crítico para o negócio e deve durar anos, a adoção faz sentido.
Fundamentos: Core Domain, Linguagem Ubíqua e Contextos Delimitados
A base do DDD é olhar primeiro para o negócio, não para a tecnologia. Três pilares sustentam essa visão.
Core Domain é a parte do negócio que gera vantagem competitiva real. Esse contexto merece o melhor time, maior investimento em modelagem e mais atenção em testes. Domínios de suporte podem reutilizar soluções de mercado ou abordagens mais simples.
Linguagem Ubíqua é o vocabulário compartilhado entre negócio, desenvolvimento e QA. Quando o código usa os mesmos termos que o product owner usa em reunião — AssinaturaCriada, FaturaGerada, PagamentoRecusado — o risco de mal-entendidos cai drasticamente.
Contextos Delimitados são as fronteiras explícitas entre partes do sistema. Pense em um mapa de metrô: cada linha representa um contexto (Faturamento, Assinaturas, Pagamentos), com estações e conexões bem definidas. O código de um contexto não invade o outro diretamente — as integrações passam por contratos claros.
Como levantar a arquitetura orientada a domínio
- Conduza uma sessão de Event Storming com especialistas de negócio, desenvolvimento e QA.
- Colete eventos de domínio:
AssinaturaCriada,FaturaGerada,PagamentoRecusado. - Agrupe eventos em fluxos e identifique potenciais Contextos Delimitados.
- Nomeie cada contexto com termos da própria empresa, reforçando a Linguagem Ubíqua.
Essa visão facilita decidir onde aplicar microserviços, qual parte fica em um monólito modular e onde usar integrações assíncronas.
Do modelo ao código: blocos táticos e testes de unidade
A força do DDD está na transição consistente do modelo para o código. A modelagem deve se refletir diretamente nas estruturas técnicas — e isso tem impacto direto na testabilidade.
Os principais blocos táticos são:
- Entidades: possuem identidade estável, como
AssinaturaouCliente. - Objetos de Valor: representam conceitos imutáveis, como
DinheiroouPeriodoDeCobranca. - Agregados: agrupam entidades e valores sob uma raiz consistente, como
Assinaturacom suasFaturas. - Serviços de Domínio: encapsulam regras que não pertencem naturalmente a uma única entidade.
Um exemplo simplificado em C# para um contexto de Assinaturas:
public class Assinatura
{
public AssinaturaId Id { get; }
public Plano Plano { get; private set; }
public StatusAssinatura Status { get; private set; }
public void Ativar()
{
if (Status != StatusAssinatura.Pendente)
throw new DominioException("Assinatura só pode ser ativada quando pendente.");
Status = StatusAssinatura.Ativa;
}
}
Esse tipo de implementação torna as regras de negócio explícitas no código. Em vez de testar apenas controllers, você valida diretamente os métodos de domínio — o que torna os testes mais rápidos, mais estáveis e mais próximos do que o negócio realmente precisa proteger.
Regra operacional: para cada regra de negócio relevante, deve existir ao menos um teste automatizado que a valide no nível de domínio. Frameworks, controllers e adapters são testados de forma mais superficial, com foco em integração.
Como conectar DDD, QA e cobertura de testes
DDD não é responsabilidade exclusiva de quem escreve código. QA, análise e produto precisam estar envolvidos desde as primeiras sessões de modelagem — e esse caráter colaborativo é o que diferencia times que adotam DDD de verdade dos que apenas usam o vocabulário.
Na prática, QA deixa de ser a etapa final de validação e passa a ser coautor das regras. Durante um Event Storming, o papel de QA inclui:
- Questionar casos de borda e fluxos alternativos.
- Identificar riscos de negócio que exigem cenários de teste específicos.
- Sugerir métricas de cobertura ligadas ao domínio, não só ao código.
Pirâmide de testes orientada ao domínio
| Camada | Foco |
|---|---|
| Base (unidade) | Entidades, Objetos de Valor e Serviços de Domínio |
| Meio (integração) | Entre Contextos Delimitados e sistemas externos |
| Topo (ponta a ponta) | Jornadas críticas de negócio |
Além da cobertura de código tradicional, defina metas de cobertura de regras de negócio. Por exemplo: todas as combinações de status de Assinatura e resultado de Pagamento que impactam faturamento devem ter cenários automatizados ou, ao menos, exploratórios documentados.
Fluxo prático: DDD aplicado a cobranças recorrentes
Imagine o time responsável por um produto de assinaturas digitais com cobrança recorrente — cenário comum em empresas que usam plataformas como as da Locaweb ou provedores de pagamento recorrente.
1. Descoberta de domínio
Reúna product owner, especialistas de negócio, desenvolvimento e QA. Mapeie eventos principais: AssinaturaCriada, AssinaturaCancelada, FaturaGerada, PagamentoAprovado, PagamentoRecusado.
2. Definição de Contextos Delimitados
- Assinaturas: regras de ciclo de vida da assinatura.
- Cobrança: geração de faturas, cálculo de valores, impostos.
- Pagamentos: integração com gateways, conciliação, retentativa.
3. Modelagem tática
- Em Assinaturas, defina Entidades como
AssinaturaeCliente. - Em Cobrança, defina Objetos de Valor como
Dinheiro,PeriodoDeCobrancaeRegraDeDesconto. - Em Pagamentos, isole detalhes de infraestrutura em adapters, preservando um modelo de domínio limpo.
4. Planejamento de testes QA deriva cenários de negócio diretamente dos eventos e regras mapeados. Defina suites específicas para churn, inadimplência, ajuste de plano e upgrades.
5. Implementação e iteração Comece pelo Core Domain (cobranças complexas, por exemplo) e só depois trate domínios de suporte. Revise modelos periodicamente conforme novas regras surgem.
Métricas de qualidade orientadas ao domínio
Modelos bem definidos de domínio permitem métricas mais inteligentes de qualidade. Em vez de medir apenas cobertura de código ou número de bugs por sprint, você acompanha a saúde do domínio.
Cobertura de regras de negócio Percentual de regras críticas com testes automatizados explícitos. Exemplo: 100% das regras que impactam faturamento ou compliance precisam de testes automatizados.
Cobertura por Contexto Delimitado Distribua testes por contexto (Assinaturas, Cobrança, Pagamentos). Contextos mais críticos devem ter maior densidade de testes de unidade e integração.
Defeitos escapados por domínio Conte bugs em produção e associe cada um a um Contexto Delimitado. Use esses dados para priorizar refatorações ou reforço de testes em contextos problemáticos.
Alinhamento semântico Proporção de classes, métodos e endpoints usando a Linguagem Ubíqua. Quanto mais o código se parece com o vocabulário do negócio, menor a chance de mal-entendidos entre times.
Erros comuns ao adotar DDD
Muitas equipes se empolgam com DDD e caem em armadilhas previsíveis. Reconhecê-las cedo evita desperdício de tempo e frustração.
Erros frequentes:
- Aplicar DDD em todo e qualquer sistema, inclusive CRUDs simples.
- Confundir microserviços com Contextos Delimitados e fragmentar tudo sem critério.
- Deixar a escolha de framework ditar o desenho do modelo de domínio.
- Tratar QA como etapa tardia, sem envolvê-lo na descoberta e modelagem.
Como evitar:
Comece pelo problema de negócio. Só considere DDD quando houver complexidade inerente de regras, integração ou escala.
Use experimentos controlados. Aplique DDD em um único domínio de alta relevância, como cobrança recorrente, antes de expandir para o restante do sistema.
Desacople o domínio da infraestrutura. Utilize padrões como Clean Architecture e CQRS de forma pragmática, como sugerem talks de .NET Conf — sem transformar a arquitetura em um fim em si mesma.
Traga QA, produto e negócio para a mesa. A Linguagem Ubíqua precisa nascer da colaboração entre todas as áreas, não apenas do time de desenvolvimento.
Próximos passos
DDD é uma forma disciplinada de aproximar código e negócio em torno de um mesmo modelo conceitual, com fronteiras claras, vocabulário compartilhado e integrações bem pensadas.
Ao combinar modelagem estratégica, padrões táticos e colaboração estreita com QA, você transforma regras soltas em um modelo robusto, testável e evolutivo. Métricas de cobertura deixam de ser apenas números de ferramenta e passam a refletir a proteção real das partes mais críticas do seu domínio.
Se o seu produto lida com cobranças recorrentes, meios de pagamento ou operações logísticas, o caminho prático é: escolha um contexto de alta relevância, envolva o time completo desde a descoberta e meça cobertura por regra de negócio, não só por linha de código.