Pular para o conteúdo

Conceitos

Contextos delimitados e agregados (DDD)

Intuição

Pense numa grande empresa: a palavra "cliente" significa uma coisa para o time de vendas (um possível comprador, com histórico de contatos), outra para o financeiro (quem deve ou já pagou uma fatura) e outra para o suporte (quem abriu um chamado). Tentar fazer um único cadastro "universal" de cliente que sirva a todos acaba virando uma bagunça que ninguém entende. O caminho mais saudável é cada área ter o seu próprio modelo, com seu próprio vocabulário, e combinar com clareza como as áreas conversam entre si. Dentro de cada área, ainda existem pequenos grupos de coisas que precisam estar sempre coerentes entre si — como um pedido e seus itens, que nunca podem ficar com totais inconsistentes — e esses grupos têm uma "porta de entrada" única por onde toda alteração passa.

Como funciona

No Domain-Driven Design, um contexto delimitado (bounded context) é a fronteira explícita dentro da qual um modelo de domínio é válido e a linguagem ubíqua (ubiquitous language) tem um significado único e consistente; o mesmo termo, como "Cliente" ou "Produto", pode legitimamente ter modelos diferentes em contextos diferentes, e tentar unificá-los num modelo canônico único costuma gerar acoplamento e ambiguidade. As relações entre contextos são descritas num mapa de contexto (context map), com padrões como cliente/fornecedor (customer/supplier, em que o contexto a jusante pode negociar necessidades com o a montante), conformista (conformist, em que o a jusante adota o modelo do a montante sem poder influenciá-lo) e camada anticorrupção (anti-corruption layer, uma camada de tradução que impede que o modelo de outro contexto vaze para o seu). Dentro de um contexto, o modelo é organizado em agregados (aggregates): clusters de entidades e objetos de valor tratados como uma unidade de consistência, com uma única raiz do agregado (aggregate root) que é o único ponto de acesso externo e quem garante as invariantes do conjunto. Outros objetos referenciam um agregado apenas pelo identificador da raiz, e a regra prática é que uma transação modifique um único agregado, de modo que as invariantes que precisam valer a cada commit ficam todas dentro de uma fronteira. Entre agregados, e entre contextos, a consistência é eventual: um agregado publica eventos de domínio (domain events) descrevendo fatos que ocorreram, e outros agregados ou contextos reagem a eles em transações próprias. Quando um processo de negócio atravessa vários agregados ou serviços, é aí que entram sagas, coordenadas por orquestração ou coreografia; este conceito trata de onde traçar as fronteiras e do que precisa ser consistente dentro delas, não de como coordenar o que as atravessa.

Na prática

Na prática, as fronteiras de serviços em microsserviços tendem a funcionar melhor quando seguem contextos delimitados, porque cada serviço passa a ter seu modelo, seu armazenamento e seu vocabulário próprios, e as chamadas entre serviços acontecem nas costuras do mapa de contexto, onde uma camada anticorrupção protege um modelo limpo de integrações legadas ou externas. Agregados pequenos, desenhados em torno de invariantes reais de negócio, evitam transações grandes e contenção de locks, ao custo de aceitar consistência eventual e eventos de domínio entre eles. As referências canônicas sobre o tema são Eric Evans, "Domain-Driven Design" (2003), que introduz contextos delimitados e agregados, e Vaughn Vernon, "Implementing Domain-Driven Design" (2013), que detalha o desenho de agregados e a integração entre contextos.

Use em um desenho

Pratique na escola de System Design os casos que dependem deste conceito.