Desafios avançados em DDD para testar seus conhecimentos
Exploração prática de contextos delimitados, invariantes de agregado, integração entre contextos vinculando eventos de domínio e estratégias de teste. Este guia técnico propõe cenários reais para você praticar a modelagem, a implementação e a validação de domínio sem recorrer a soluções genéricas.
1) Contextos Delimitados e a Arquitetura do Domínio
Em DDD, o domínio se organiza em Contextos Delimitados (Bounded Contexts). Cada contexto representa um modelo de domínio coeso, com seu próprio vocabulário onipresente e regras de negócio. O desafio está em mapear as fronteiras, acordar a linguagem com as equipes envolvidas e definir padrões de integração que não contaminem o modelo interno de cada contexto.
- Context Mapping: identifique parcerias, clientes-fornecedores, conformismo e ACL (Anti-Crossing Layer) para evitar leakage entre contextos.
- Estratégias de integração: eventos de domínio, mensagens assincronas, e contratos entre contextos, com atenção à consistência eventual quando necessário.
- Arquitetura de fusos horários: sincronização de eventos entre serviços distribuídos sem perder o significado semântico do modelo.
Pratique com cenários em que dois contextos compartilham o mesmo conceito (ex.: Order no contexto de Vendas vs. Estoque) e veja como a linguagem ubíqua dita a forma de comunicação entre eles.
2) Invariantes, Agregados e Regras de Consistência
Aggregates são a matéria-prima para manter invariantes de domínio. Todo comando, em um agregado, pode violar invariantes se não for validado pela raiz do agregado (root). A responsabilidade é manter consistência de estado dentro do agregado e expor apenas operações que respeitem esse conjunto de regras.
- Evergreen invariants: invariantes de domínio que devem permanecer verdadeiros após cada comando.
- Encapsulamento: ocultar estado interno e expor apenas métodos de comportamento com validação interna.
- Transições de estado: modelar estados do agregado como uma máquina de estados simples para facilitar a leitura de regras.
Exemplo de agregado com regras simples ilustradas abaixo:
export class Order {
public readonly id: string;
private status: 'Created' | 'Paid' | 'Shipped';
private items: OrderItem[] = [];
private constructor(id: string) {
this.id = id;
this.status = 'Created';
}
public static create(id: string): Order {
return new Order(id);
}
public addItem(item: OrderItem): void {
if (this.status !== 'Created') {
throw new Error('Não é possível adicionar itens quando o pedido não está no estado Created');
}
this.items.push(item);
}
public pay(): void {
if (this.items.length === 0) {
throw new Error('O pedido não pode ser pago sem itens');
}
this.status = 'Paid';
}
public ship(): void {
if (this.status !== 'Paid') {
throw new Error('O pedido precisa estar Paid para enviar');
}
this.status = 'Shipped';
}
// ...outros métodos de negócio
}
export class OrderItem {
constructor(public readonly productId: string, public readonly quantity: number) {}
}
3) Integração entre Bounded Contexts: ACL, Eventos e Sagas
Quando múltiplos contextos coexistem, a integração precisa respeitar as fronteiras para evitar leakage de políticas de um contexto para outro. Os padrões mais comuns são ACL (Anti-Corruption Layer) para tradução de modelos, eventos de domínio para comunicação assíncrona e sagas para coordenar transições de estado entre contextos de forma eventual.
- Anti-Corruption Layer: tradutor entre modelos, evitando que o modelo de um contexto seja exposto diretamente ao outro.
- Eventos de domínio: publicar e subscribir a eventos relevantes para que contextos consumidores reajam às mudanças de forma eventual.
- Sagas: coordenação entre vários contextos para manter consistência sem bloquear transações distribuídas; escolha entre orchestrated e choreographed conforme o domínio.
Prática recomendada: comece com eventos de domínio para cenários simples e evolua para uma saga quando houver necessidade de coordenação entre várias entidades de contextos distintos.
4) Testes Avançados em DDD: Qualidade no Domínio
Os testes em DDD devem validar invariantes no domínio, comportamento de agregados e contratos entre contextos. Adote uma abordagem centrada no domínio, com foco na leitura do código de domínio e na validação de regras de negócio, não apenas no comportamento da infraestrutura.
- Testes de unidade de agregados: validam invariantes, estados e transições de forma isolada.
- Testes de domínio: cobrem regras de negócio complexas que envolvem várias entidades de um agregado.
- Testes de contrato entre contextos: garantem que a integração entre contextos se mantenha estável ante mudanças no modelo de um deles.
- Testes de eventos: asseguram que a publicação de eventos transmite o significado esperado e que consumidores o interpretam corretamente.
Gostou do conteúdo? Continue aprendendo com outros posts sobre DDD e arquitetura de software no Yurideveloper.
Confira também:
DDD em prática •
Arquitetura DDD em Microserviços •
Testes de domínio avançados