Pular para o conteúdo
11 min de leitura

Bounded contexts e a divisão de domínios em DDD

Por Lucas Andrade ·

Bounded context é a fronteira onde um modelo e sua linguagem fazem sentido. Entenda como dividir domínios em DDD e por que evitar o modelo canônico gigante.

Neste artigo

Existe um momento na vida de quase todo sistema em que ele começa a resistir a mudanças. Adicionar um campo aparentemente trivial exige tocar em sete lugares. Uma alteração no cadastro de clientes quebra, misteriosamente, o cálculo de fretes. O time descobre que a palavra "produto" significa coisas sutilmente diferentes para quem cuida do catálogo, para quem cuida do estoque e para quem cuida da nota fiscal — e que essas diferenças estão todas espremidas numa única classe gigante que tenta agradar a todos e não serve bem a ninguém.

O Domain-Driven Design, formulado por Eric Evans, nasceu para atacar exatamente esse tipo de sofrimento. Sua contribuição mais duradoura não é um conjunto de padrões táticos de código, mas uma ideia estratégica: a de que sistemas complexos não devem ter um único modelo unificado do domínio, e sim vários modelos, cada um válido dentro de uma fronteira explícita. Essa fronteira tem nome: bounded context, ou contexto delimitado.

Este artigo trata de por que essa ideia é tão libertadora, o que exatamente delimita um bounded context, como a linguagem ubíqua e o mapa de contextos entram na história, e como identificar as fronteiras certas. O tema é conceitual, mas as consequências são muito concretas: fronteiras bem traçadas são a diferença entre um sistema que envelhece com dignidade e um que apodrece a cada nova funcionalidade.

Domínio e subdomínios: o território antes do mapa#

Antes de falar de fronteiras, é preciso falar do que está sendo delimitado. Domínio é a esfera de conhecimento e atividade em torno da qual o software é construído — o negócio, o problema real. Para uma empresa de comércio eletrônico, o domínio inclui vender produtos, gerir estoque, processar pagamentos, entregar encomendas, atender clientes.

Nenhum domínio real é homogêneo. Ele se divide naturalmente em subdomínios, e esses subdomínios não têm todos a mesma importância. O DDD distingue três tipos. O subdomínio central é aquele que diferencia o negócio, onde está a vantagem competitiva — é onde vale investir o melhor esforço de modelagem. Os subdomínios de apoio são necessários mas não diferenciadores; existem para o central funcionar. E os subdomínios genéricos são problemas resolvidos, para os quais faz mais sentido comprar uma solução pronta do que construir — autenticação, envio de e-mail, emissão fiscal padrão.

Essa distinção é estratégica porque orienta onde gastar energia. Modelar com esmero um subdomínio genérico é desperdício; tratar o subdomínio central com desleixo é sabotar a própria razão de existir do produto. Subdomínio é uma divisão do espaço do problema — como o negócio de fato se organiza, independentemente de software.

Bounded context: a fronteira do espaço da solução#

Se subdomínio é uma divisão do problema, bounded context é uma divisão da solução. É a fronteira explícita dentro da qual um modelo específico, com sua linguagem específica, é coerente, consistente e válido. Dentro dessa fronteira, cada termo tem um significado único e não ambíguo; cada conceito tem uma forma; as regras se aplicam sem exceção.

O ponto crucial, e o que mais custa a assimilar, é que o mesmo termo do negócio significa coisas diferentes em contextos diferentes — e isso não é um problema a ser eliminado, é a realidade a ser respeitada. Pegue a palavra "cliente". No contexto de vendas, cliente é alguém com histórico de compras, preferências, potencial de recompra. No contexto de faturamento, cliente é uma entidade com CNPJ, endereço fiscal e condições de pagamento. No contexto de suporte, cliente é o titular de tíquetes e um histórico de interações. Forçar um único modelo de "Cliente" a atender aos três é exatamente o que gera aquela classe inchada, cheia de campos que só fazem sentido para um dos usos e ficam nulos ou confusos nos outros.

O bounded context autoriza cada contexto a ter seu próprio modelo de Cliente, otimizado para o que aquele contexto faz. Eles se referem à mesma pessoa do mundo real, mas são representações distintas, e a tradução entre elas acontece de forma explícita na fronteira. Essa autorização para divergir é o coração do DDD estratégico.

Linguagem ubíqua: o modelo falado#

Amarrada de forma inseparável ao bounded context está a linguagem ubíqua. É a linguagem compartilhada entre desenvolvedores e especialistas do negócio, usada de maneira rigorosa e consistente em conversas, documentos e — literalmente — no código. Se o negócio chama de "apólice", o código tem uma classe Apolice, não Contract ou Registro. A linguagem do domínio e a linguagem do software são a mesma.

Por que isso importa tanto? Porque a maior fonte de defeitos em sistemas complexos não é erro de sintaxe, é mal-entendido. O desenvolvedor entende "reserva" de um jeito, o especialista quer dizer outro, e a divergência só aparece em produção. A linguagem ubíqua ataca essa origem obrigando o time a alinhar significados com precisão e a codificar esse alinhamento no próprio software, de modo que o código vira uma expressão fiel do entendimento do negócio.

E aqui está a conexão elegante: a linguagem ubíqua só é ubíqua dentro de um bounded context. É justamente porque "cliente" significa coisas diferentes em vendas e em faturamento que você não pode ter uma linguagem única para o sistema inteiro. Cada contexto tem sua própria linguagem ubíqua, internamente consistente. A fronteira do contexto é, ao mesmo tempo, a fronteira até onde uma linguagem se sustenta sem ambiguidade. Um define o outro.

O modelo canônico gigante: a tentação a evitar#

Diante da constatação de que "cliente" aparece em vários lugares, o instinto de muitos times é nobre e desastroso: criar o modelo definitivo de Cliente, o modelo canônico, único, que serve para toda a empresa. Um esquema de banco unificado, uma classe compartilhada, uma verdade central. Parece o auge da organização. É, na prática, uma armadilha.

O modelo canônico gigante falha porque tenta ser tudo para todos. Ele acumula os campos de todos os usos, as regras de todos os contextos, as exceções de cada caso especial. Vira um objeto que ninguém entende por inteiro, que muda o tempo todo porque qualquer contexto pode precisar de algo novo, e cuja mudança arrisca quebrar todos os outros de uma vez. É o oposto do isolamento: acopla tudo a tudo através de uma dependência compartilhada no centro.

Pior, esse modelo tende a virar uma commodity de domínio compartilhada — aquela biblioteca commons cheia de entidades que todos importam e todos alteram, e que se torna o ponto onde qualquer mudança vira negociação entre todos os times. O DDD estratégico rejeita essa abordagem frontalmente. A saída não é unificar, é delimitar e traduzir. Deixe cada contexto ter seu modelo próprio; conecte-os por contratos explícitos nas fronteiras. Um pouco de "duplicação" aparente entre contextos é o preço saudável do desacoplamento — e quase sempre não é duplicação de verdade, porque os modelos, embora se pareçam, evoluem por razões diferentes.

Mapas de contexto: desenhando as relações#

Bounded contexts não vivem isolados; eles se relacionam, trocam dados, dependem uns dos outros. O mapa de contextos é a ferramenta que torna essas relações explícitas, mostrando quais contextos existem e como se conectam. Não é um diagrama técnico de infraestrutura; é um mapa das relações de poder, dependência e integração entre os modelos e, muitas vezes, entre os times que os mantêm.

O DDD nomeia vários tipos de relação nesse mapa, e conhecê-los ajuda a decidir conscientemente. Alguns dos mais importantes:

  • Cliente-fornecedor (customer-supplier): um contexto a jusante depende de um a montante, e há uma relação de negociação em que as necessidades do cliente têm peso nas decisões do fornecedor.
  • Conformista (conformist): o contexto a jusante simplesmente adota o modelo do fornecedor como está, sem tradução, aceitando a linguagem dele — útil quando não há poder de negociação e o custo de traduzir não compensa.
  • Camada anticorrupção (anti-corruption layer): o contrário do conformista. O contexto a jusante constrói uma camada de tradução que protege seu modelo próprio de ser contaminado pelo modelo do vizinho, traduzindo os conceitos externos para os seus na fronteira. É uma das ferramentas mais valiosas para integrar com sistemas legados ou externos sem deixar que a bagunça deles infecte seu modelo limpo.
  • Núcleo compartilhado (shared kernel): dois contextos concordam em compartilhar uma parte pequena e estável do modelo, com o compromisso explícito de que qualquer mudança nessa parte é negociada entre ambos. Poderoso, mas perigoso — deve ser mínimo, porque é acoplamento deliberado.
  • Caminhos separados (separate ways): os contextos decidem não se integrar de jeito nenhum, porque o custo da integração supera o benefício. Reconhecer quando não integrar é tão maduro quanto saber integrar.

O mapa de contextos transforma decisões que aconteceriam por acidente — "esse serviço acabou dependendo daquele" — em escolhas conscientes sobre acoplamento, tradução e responsabilidade.

A relação com times e serviços#

Aqui a teoria encontra a organização. A Lei de Conway observa que a arquitetura de um sistema tende a espelhar a estrutura de comunicação da organização que o constrói. O DDD dá a essa observação um uso deliberado: se cada bounded context tende a ser mantido por um time, e as fronteiras dos contextos são bem escolhidas, então a estrutura do software e a estrutura da organização se reforçam em vez de brigar.

É por isso que bounded contexts costumam ser a unidade natural de decomposição em microsserviços. Um serviço que corresponde a um bounded context tem um modelo coeso, uma linguagem consistente, uma fronteira clara de responsabilidade e um contrato explícito com os vizinhos. Ele muda por razões próprias, isoladas das razões dos outros. Extrair serviços ao longo de fronteiras de contexto é extrair ao longo de costuras naturais; extraí-los por critérios técnicos aleatórios — "vamos separar todos os CRUDs" — é rasgar no meio de conceitos que deveriam ficar juntos.

Isso não significa que todo bounded context precise virar um serviço separado. Num monolito modular, cada contexto pode ser um módulo com fronteira interna clara. O valor conceitual do bounded context independe da escolha de distribuição; ele é primeiro uma ferramenta de organização de modelos e linguagem, e só depois, se fizer sentido, uma linha de corte para serviços.

Como identificar as fronteiras#

A pergunta prática que fica é: como saber onde uma fronteira deve ficar? Não há fórmula mecânica, mas há sinais confiáveis que a experiência ensina a reconhecer.

  • Mudança de linguagem. Quando a mesma palavra passa a significar coisas diferentes, ou quando um termo novo aparece que antes não existia, você provavelmente cruzou uma fronteira de contexto. A linguagem é o detector mais sensível.
  • Divergência de modelo. Quando os atributos e comportamentos que importam para um conceito mudam de acordo com quem o usa — o Cliente de vendas versus o de faturamento —, isso é a fronteira pedindo para existir.
  • Alinhamento com capacidades de negócio. Fronteiras que seguem capacidades reais do negócio — vender, faturar, estocar, entregar — tendem a ser estáveis, porque o negócio muda mais devagar do que a tecnologia.
  • Coesão e acoplamento. Coisas que mudam juntas pela mesma razão pertencem ao mesmo contexto; coisas que mudam por razões independentes pedem contextos separados. Fronteira boa maximiza coesão dentro e minimiza acoplamento fora.
  • Fronteiras organizacionais e de dados. Onde um time termina e outro começa, onde uma fonte de verdade de dados troca de dono, quase sempre há uma fronteira de contexto tentando emergir.

Vale lembrar que fronteiras não precisam nascer perfeitas. É legítimo começar com uma divisão aproximada e refiná-la conforme o entendimento do domínio amadurece — desde que refatorar continue barato, o que reforça o valor de descobrir essas fronteiras dentro de um monolito modular antes de congelá-las em contratos de rede.

Conclusão#

Bounded context é, no fundo, um ato de humildade epistemológica: a aceitação de que nenhum modelo único captura um domínio complexo, e de que tentar forçá-lo produz sistemas frágeis e classes inchadas que servem mal a todos. Em vez de um mapa canônico do território inteiro, o DDD propõe muitos mapas menores, cada um preciso dentro de sua fronteira, cada um com sua linguagem ubíqua consistente, conectados por relações explícitas num mapa de contextos.

O benefício é profundamente prático. Fronteiras claras localizam a mudança — mexer num contexto não reverbera pelos outros. Elas permitem que times trabalhem com autonomia, que serviços sejam extraídos ao longo de costuras naturais, e que a linguagem do código permaneça fiel à linguagem do negócio. O trabalho difícil não é técnico, é de entendimento: conversar com os especialistas, ouvir a linguagem mudar, perceber onde os significados divergem e ter a disciplina de honrar essa divergência em vez de apagá-la. Quem aprende a enxergar essas fronteiras ganha a ferramenta mais poderosa do design de software para domar a complexidade — não eliminando-a, mas dividindo-a em pedaços que uma mente humana consegue, de fato, entender por inteiro.

Leituras relacionadas

Nenhum comentário ainda

Seja o primeiro a comentar.

Deixe seu comentário

Entre com sua conta Canverly para comentar. Você pode usar a mesma conta em qualquer site da rede.

Entrar com Canverly