Domain Driven Desing - Como modelos se perdem
- #DDD
Para exemplificar os conceitos explicados no artigo anterior, irei apresentar uma situação que ilustra o DDD na prática.
João é dono de uma loja de artesanatos em um centro comercial e decide vender seus produtos pela internet. Para realizar suas vendas, ele optou por um modelo muito simples, mas que atendia às necessidades do seu negócio:
type struct Pedido {
id string
id_cliente string
id_nota_fiscal string
endereço_entrega string
valor_total float64
status string
}
João utilizou esse sistema por anos e realizou diversas vendas, o que chamou muito a atenção das outras lojas do centro comercial. Os lojistas passaram a questionar João sobre a possibilidade de integrarem suas lojas ao seu sistema. Empolgado, ele começa a trabalhar numa nova modelagem, e algumas ideias surgem no processo, entre elas, a possibilidade de adicionar compras recorrentes ao sistema, o que o leva ao seguinte modelo:
type struct Pedido {
id string
id_cliente string
id_nota_fiscal string
cnpj string
endereço_entrega string
valor_total float64
status string
id_vendedor string
data_proxima_cobrança time.Time
e_recorrente bool
}
Apesar do novo modelo carregar as informações necessárias para operacionalizar o negócio, a jornada de compra do cliente parece ter se perdido. O pedido inicialmente representava o ato do cliente selecionar produtos e comprá-los. Na modelagem proposta por João, no entanto, os pedidos passaram a ser segregados por vendedor, deixando de refletir a experiência do usuário e se distanciando do domínio original.
Vamos agora aplicar os conceitos do DDD para trazer o modelo de volta ao domínio do negócio.
Para isso, devemos iniciar um processo de análise da jornada de compra. Uma boa prática é exercitar nossa capacidade de desenhar um diagrama de contexto, o nível 1 do modelo C4 (recomendo fortemente que estudem sobre isso, talvez eu escreva um artigo no futuro).
O usuário seleciona itens no marketplace e, ao final de sua jornada, dispara um pedido. Cada item possui seu próprio vendedor, que será responsável por emitir a nota fiscal referente à sua venda. Com essa jornada em mente, resolvemos boa parte dos problemas de modelagem:
//Modelo simplifcado para fins didáticos
type struct Vendedor {
id string
status string
}
type struct Venda {
id_vendedor string
itens []ItemPedido
nota_fiscal NotaFiscal
}
type struct ItemPedido {
produto string
quantidade int
status_entrega string
id_venda string
}
type struct Pedido {
id string
id_cliente string
endereço_entrega string
itens []ItemPedido
}
Apesar do modelo anterior resolver boa parte dos problemas, ele ainda não contempla o novo serviço de compras programadas. Isso porque o ciclo de uma assinatura é uma jornada à parte, vamos novamente exercitar o processo de análise da jornada do cliente.
Uma assinatura está associada a um único item, e isso tem um motivo: o usuário pode querer cancelar a assinatura de um item específico sem cancelar os demais. Na data programada, cada assinatura ativa dispara a criação de um pedido próprio, agrupando todas as compras programadas daquele dia.
O fluxo completo fica assim:
type struct Assinatura {
id string
id_cliente string
id_item string
ciclo string // mensal, semanal, etc
status string // ativa, pausada, cancelada
proxima_cobranca time.Time
}
Assinatura (por item)
→ gera Pedido (agrupando assinaturas ativas do dia)
→ gera Venda (por vendedor)
→ gera NotaFiscal
Com isso, o domínio de compras programadas fica isolado do domínio de compras avulsas, um pedido de assinatura nunca se mistura com um pedido iniciado manualmente pelo usuário, preservando a clareza da jornada de cada um.
Com a introdução das assinaturas, conseguimos modelar os três principais fluxos do nosso marketplace: compras avulsas, vendas entre múltiplos vendedores e compras programadas. Cada conceito encontrou seu lugar natural no modelo, refletindo com fidelidade a jornada do usuário e as regras do negócio.
Vale destacar que esse processo não foi linear. Partimos de uma entidade corrompida que tentava representar tudo ao mesmo tempo, e através da análise da jornada do cliente fomos destilando os conceitos até chegar em um modelo que qualquer especialista de negócio reconheceria.
No entanto, uma pergunta ainda fica em aberto: como as peças desse modelo se comunicam? Quando uma assinatura vence, o que notifica o sistema para gerar um pedido? Quando um pedido é criado, como a venda de cada vendedor é disparada?
Essas perguntas nos levam ao conceito de Domain Events, o mecanismo que dá vida ao modelo e orquestra a comunicação entre seus fluxos de forma desacoplada. É o que exploraremos no terceiro e último artigo desta série, usando o marketplace do João como fio condutor.

