Bounded Contexts: delimitando domínios

1. O Problema da Comunicação e da Coesão

1.1. A Torre de Babel dos times

Em qualquer organização de médio ou grande porte, um mesmo termo pode significar coisas completamente diferentes para áreas distintas. Considere a palavra "cliente". Para o time de vendas, cliente é quem assina o contrato. Para o time de suporte, cliente é quem abre um chamado. Para o time de faturamento, cliente é quem paga a fatura. Para o time de marketing, cliente é quem está na base de leads.

Quando todos esses times compartilham um único modelo de "Cliente" no sistema, o resultado é confusão, retrabalho e bugs. Cada time acaba adicionando atributos e comportamentos que só fazem sentido no seu contexto, poluindo o modelo para os demais.

1.2. O acoplamento acidental entre módulos

O segundo problema é o acoplamento acidental. Quando um módulo de "Pedidos" precisa acessar diretamente o banco de dados do módulo de "Estoque" para verificar disponibilidade, estamos criando uma dependência frágil. Uma mudança na estrutura de dados do Estoque pode quebrar o módulo de Pedidos, mesmo que os dois domínios sejam conceitualmente independentes.

text
// Exemplo de acoplamento problemático
// Módulo de Pedidos acessando diretamente tabela de Estoque
SELECT quantidade FROM estoque.produtos WHERE id = :produtoId

1.3. A falácia do modelo único e universal

Muitas empresas tentam construir um "modelo de dados corporativo" que sirva a todos os sistemas. Essa abordagem quase sempre falha porque:

  • O modelo fica genérico demais para ser útil
  • As regras de negócio conflitantes não podem ser resolvidas em um único modelo
  • A evolução do sistema fica travada por consenso entre múltiplos times

2. Definição Fundamental de Bounded Context

2.1. Limite explícito

Um Bounded Context é um limite explícito dentro do qual um modelo de domínio específico é válido e consistente. Dentro desse limite, todos os termos têm significado único e as regras de negócio são auto-contidas.

text
// Contexto de Vendas
class Cliente {
    id: string
    nome: string
    limiteCredito: decimal
    status: string // ativo, bloqueado, pendente
}

// Contexto de Suporte
class Cliente {
    id: string
    nome: string
    nivelSuporte: string // básico, premium, enterprise
    ticketAbertos: int
}

2.2. Relação com a Ubiquitous Language

Cada Bounded Context possui sua própria Ubiquitous Language — um glossário compartilhado entre desenvolvedores e especialistas de negócio. O termo "cliente" no contexto de Vendas inclui limite de crédito; no contexto de Suporte, inclui nível de serviço. Não há contradição, pois cada contexto define seu próprio vocabulário.

2.3. Não é um módulo técnico

Bounded Context não é um pacote Java, um namespace C# ou um diretório de código. É um limite semântico e organizacional. Dois contextos podem, temporariamente, compartilhar o mesmo banco de dados (embora não seja recomendado), mas ainda assim devem ter modelos mentais e linguagens distintas.

3. Como Identificar Bounded Contexts na Prática

3.1. Análise da estrutura organizacional (Lei de Conway reversa)

A Lei de Conway afirma que sistemas refletem a estrutura de comunicação da organização. O caminho inverso também é verdadeiro: podemos identificar Bounded Contexts observando como os times se organizam. Times que se comunicam frequentemente sobre regras de negócio provavelmente pertencem ao mesmo contexto.

3.2. Mudanças de linguagem entre diferentes áreas

Preste atenção em reuniões interdisciplinares. Quando o time de Vendas diz "fechamos o pedido" e o time de Logística diz "preparamos o pedido", há uma mudança sutil de linguagem que indica contextos diferentes. Documente esses termos e veja onde eles divergem.

3.3. Frequência de mudança e independência de deploy

Contextos bem delimitados podem evoluir em velocidades diferentes. Se uma funcionalidade de "Cálculo de Frete" muda semanalmente, mas "Gestão de Usuários" muda trimestralmente, eles provavelmente pertencem a contextos separados. A independência de deploy é um forte indicador.

4. Padrões de Integração entre Contextos

4.1. Customer/Supplier

Quando um contexto precisa de dados de outro, estabelece-se uma relação de fornecedor (upstream) e consumidor (downstream).

text
// Contexto de Catálogo (upstream) fornece preços
GET /api/v1/produtos/{id}/preco

// Contexto de Carrinho (downstream) consome
// O downstream aceita o modelo do upstream sem adaptação

4.2. Conformist

O downstream simplesmente se adapta ao modelo do upstream, sem criar camadas de tradução. É útil quando o upstream é estável e confiável, mas arriscado se o upstream mudar com frequência.

4.3. Anti-Corruption Layer

Quando o downstream precisa se proteger de mudanças no upstream, cria-se uma camada de tradução.

text
// Camada Anticorrupção no contexto de Pedidos
class AdaptadorEstoque {
    consultarDisponibilidade(produtoId: string): boolean {
        // Traduz chamada para API do Estoque
        const resposta = estoqueApi.get(`/disponibilidade/${produtoId}`)
        // Traduz resposta para modelo local
        return resposta.status === "disponivel"
    }
}

5. Context Mapping: Visualizando as Fronteiras

5.1. O mapa de contextos como ferramenta de arquitetura

O Context Map é um diagrama que mostra todos os Bounded Contexts e seus relacionamentos. É uma ferramenta essencial para arquitetos entenderem as fronteiras e as integrações.

5.2. Tipos de relacionamento

  • Shared Kernel: Contextos compartilham um subconjunto do modelo (usar com cautela)
  • Open Host Service: Um contexto expõe uma API pública que outros consomem
  • Published Language: Um formato padronizado (ex: XML, JSON Schema) é usado para comunicação

5.3. Separatas

Dois contextos podem ser completamente independentes, sem qualquer comunicação direta. Isso é comum quando domínios são ortogonais, como "Recursos Humanos" e "Recomendação de Produtos".

6. Implicações Arquiteturais e Técnicas

6.1. Microserviços como implementação natural

Cada Bounded Context pode se tornar um microserviço independente, com sua própria API, banco de dados e ciclo de deploy.

text
// Arquitetura baseada em Bounded Contexts
/vendas-api      → Contexto de Vendas
/estoque-api     → Contexto de Estoque
/logistica-api   → Contexto de Logística
/faturamento-api → Contexto de Faturamento

6.2. Bases de dados independentes

Cada contexto gerencia seus próprios dados. Isso elimina o acoplamento de esquemas de banco e permite que cada time escolha a tecnologia mais adequada.

6.3. Versionamento de contratos

APIs entre contextos devem ser versionadas para permitir evolução independente.

text
GET /api/v1/pedidos       → Versão estável
GET /api/v2/pedidos       → Nova versão com mudanças
GET /api/v1/pedidos?versao=v2  → Estratégia alternativa

7. Armadilhas Comuns e Boas Práticas

7.1. God Context versus fragmentação excessiva

Um "God Context" tenta abranger todo o domínio de negócio — é um anti-padrão. Por outro lado, fragmentar demais cria contextos minúsculos que exigem comunicação excessiva. O equilíbrio está em contextos que correspondem a subdomínios coesos.

7.2. Comunicação síncrona excessiva

Se dois contextos precisam se comunicar sincronamente em toda requisição, talvez eles não estejam bem delimitados. Prefira comunicação assíncrona (eventos, filas) sempre que possível.

7.3. Refatorando Contextos mal delimitados

Quando um contexto cresce demais, extraia subcontextos gradualmente:

text
// Passo 1: Identificar subdomínio dentro do contexto grande
// Passo 2: Criar Anti-Corruption Layer para isolar o subdomínio
// Passo 3: Extrair para novo serviço com banco próprio
// Passo 4: Remover dependências do contexto original

Conclusão

Bounded Contexts são a espinha dorsal de uma arquitetura bem projetada. Eles resolvem problemas reais de comunicação entre times, evitam acoplamento acidental e permitem evolução independente dos sistemas. Ao delimitar claramente onde cada modelo de domínio é válido, criamos sistemas mais coesos, testáveis e adaptáveis às mudanças do negócio.

Lembre-se: o objetivo não é criar a fronteira perfeita de primeira, mas sim evoluir os limites conforme o entendimento do domínio amadurece. O Context Map é seu aliado nessa jornada contínua de refinamento.

Referências