DDD – Bounded Context

Bounded Context é um conceito muito importante do DDD e pode ser a solução para a boa modelagem do seu domínio.

Bounded Context é um conceito tão importante quanto o entendimento da separação de responsabilidades das camadas do DDD. Você tem utilizado este conceito em sua aplicação? Cuidado! Você pode estar construindo uma grande bola de lama.

Bounded Context é um conceito razoavelmente fácil de se explicar, porém pode ser extremamente complexo de se implementar. Tudo depende da visão global do domínio da aplicação.

O que significa visão global do domínio?
Ter uma visão global significa enxergar toda a extensão de seu domínio e eu não estou me referindo as camadas, estou me referindo ao negócio.

Como ter uma visão global do negócio se a aplicação ainda não foi desenvolvida ou está em processo de desenvolvimento?
É necessário lutar contra a IVSF “Irresistível Vontade de Sair Fazendo” e focar antes em mapear seus contextos e definir os Bounded Contexts “contextos delimitados”. Para determinar seus Bounded Contexts você precisa ter um bom conhecimento do negócio da empresa ou ter ao seu lado um Domain Expert.

Domain Expert

É a pessoa que entende do negócio da empresa e vai apoiar os times de desenvolvimento na modelagem do domínio, definição das regras de negócio e etc. O domain expert também é responsável por definir a Ubiquitous Language “Linguagem Ubíqua”.

Context Map

Para a aplicação ter um bom design, uma fácil manutenção / extensibilidade e o domínio ser bem modelado é necessário focar em modelagem estratégica e para isso é importante preocupar-se com a integridade do modelo conforme o diagrama do Context Map apresenta.

Bounded Context - DDD - Context Map

Todos os conceitos do Context Map são importantes, é necessário compreender muito bem de cada um deles para termos condição de realizar uma boa modelagem.

Big Ball of Mud

A grande bola de lama. Você pode ter uma em suas mãos neste momento.
Este conceito aborda vários aspectos negativos de sua aplicação, desde código macarrônico que fere os princípios do SOLID e Clean Code até uma entidade com muitas responsabilidades em um único contexto. Analise a imagem a seguir:

Bounded Context - DDD - Big Ball of Mud - Grande Bola de Lama

A entidade Produto possui diversos comportamentos, cada um destes comportamentos está ligado a uma intenção da aplicação, todas as intenções são relativas ao produto em si, porém imagine a complexidade desta classe, quantas equipes de desenvolvimento estão compartilhando a mesma classe em comum.
A entidade Produto atende aspectos de Aquisição, Venda, Entrega, Estoque e etc.
Esse tipo de modelagem pode ser considerada um exemplo de Big Ball of Mud, pois qualquer manutenção nessa entidade pode ocasionar impactos sérios em diversos pontos da aplicação, é praticamente impossível de gerenciar as mudanças.

Como resolver ou evitar este tipo de cenário?
O DDD não é sobre dividir a aplicação em camadas responsáveis, o DDD é sobre modelar corretamente o domínio do seu negócio. Se sua aplicação possui uma única camada de domínio e esta camada concentra todas as entidades do seu negócio você pode estar cometendo um grande erro de modelagem de domínio. Para aplicações que possuem domínios muito complexos o ideal é aplicar o conceito de Bounded Context.

Bounded Context

Os contextos delimitados ou bounded contexts buscam delimitar o seu domínio complexo em contextos baseados nas intenções do negócio. Isto significa que você deve delimitar as intenções de suas entidades com base no contexto que ela pertence. Analise a imagem a seguir:

Bounded Context - DDD

O domínio foi subdividido em seis pedaços, ou melhor, em seis bounded contexts, um para cada intenção de negócio (Vendas, Entregas, Estoque etc.). Agora cada bounded context possui uma entidade Produto. Cada versão da entidade Produto é diferente nos seis bounded contexts existentes. A entidade Produto possui comportamentos que atendem necessidades específicas de seu bounded context, a única coisa em comum entre todas as entidades Produto é sua identidade, o ProdutoId no caso. A identidade em comum vai ajudar na persistência e na comunicação entre os bounded contexts.

Mudando um pouco de cenário imagine uma entidade chamada Funcionário, esta entidade representa o colaborador da empresa dentro da aplicação. No bounded context “Recursos Humanos” a entidade Funcionário possui uma modelagem que atende comportamentos como férias, salário, rescisão etc. No bounded context “TI” esta entidade possui uma modelagem que atende comportamentos como login, troca de senha, permissões etc.

Quando se pergunta sobre um funcionário no departamento de TI este está ligado a um usuário e suas responsabilidades dentro do sistema, quando se pergunta sobre um funcionário dentro do RH este está ligado a um colaborador da empresa. É a mesma pessoa, porém dentro da aplicação possui intenções diferentes e é baseada nas intenções que o seu domínio deve ser delimitado em contextos. Não tem necessidade nenhuma a entidade Funcionário do o bounded context de TI ter acesso a salário, reajustes e etc.

Os Bounded Contexts fornecem aos membros das equipes de desenvolvimento um claro entendimento do que deve ser consistido e desenvolvido independentemente.

Representar a mesma entidade em diversos bounded contexts não seria duplicar o código?
De forma alguma. Duplicar código é ter a mesma responsabilidade em trechos de código diferentes. Neste caso existe uma segregação de comportamentos e intenções de uma entidade conforme o contexto em que ela está. Não importa se a entidade é persistida na mesma tabela ou em tabelas diferentes, neste caso ambos os cenários são aceitos.

Características importantes de um bounded context

  • Cada bounded context pode possuir sua própria abordagem de arquitetura. Camadas de aplicação, persistência, infra-estrutura e etc.
  • A arquitetura de um bounded context não precisa estar necessariamente no padrão DDD (Domain Model) pode ser um modelo mais simples de 3 camadas, pode implementar CQRS, Event Sourcing e etc.
  • Cada bounded context pode possuir um meio próprio de persistência, sendo ele relacional, NoSQL, em memória / cache e etc.
  • Os bounded contexts podem se comunicar entre si de diversas maneiras, inclusive utilizando eventos de domínio “Domain Events” conectados em um “Event Bus”.
  • Cada bounded context possui sua própria Ubiquitous Language.
  • Cada bounded context pode ser desenvolvido por um time de desenvolvedores diferente. Não existe necessidade de um único time conhecer a implementação de todos os contextos, pelo contrário, por motivos de segurança o fonte de um bounded context pode ser restrito a um time específico.

Patterns de relacionamento entre bounded contexts

Existem diversos patterns que descrevem o tipo de relacionamento entre os bounded contexts:

  • Shared Kernel
    Um contexto compartilhado entre outros contextos, o shared kernel é um tipo de contexto onde N bounded contexts dependem dele, uma espécie de Core, este tipo de contexto não pode ser alterado sem consultar todos os times de desenvolvimento que dependem dele.
  • Customer/Supplier
    Contextos customer dependem de contextos supplier.
    A equipe downstream atua como cliente (customer) da equipe upstream (supplier). As equipes definem testes de aceitação automatizados que validam as interfaces que a equipe upstream fornecem. A equipe upstream pode então fazer alterações em seu código sem medo de quebrar alguma coisa da equipe downstream.
  • Conformist
    É o cenário onde as equipes downstream e upstream não estão mutuamente alinhadas e a equipe downstream precisa atender o negócio com o que a equipe upstream fornece mesmo não estando de acordo com as necessidades. A equipe downstream precisa aceitar este fato, se conformar com isto.
  • Partner
    Neste cenário duas equipes possuem dependências mútuas em seus contextos e precisam somar esforços de modelagem para se atenderem mutuamente.
  • Anti Corruption Layer
    Neste cenário a equipe downstream desenvolve uma camada adicional anti-corrupção para se comunicar com o contexto upstream, é o cenário típico onde o supplier é um sistema legado ou uma API mal desenvolvida.

Domain Model Pattern

É um padrão muito indicado para atender um bounded context, o domain model pattern atende diversas convenções do DDD como:

  • Aggregate Object
    Uma entidade que é a raiz agregadora de um processo do domínio que envolve mais de uma entidade.
  • Domain Model
    Uma entidade do domínio, possui estados e comportamentos, lógica de negócio, getters e setters AdHoc, etc.
  • Value Object
    Um objeto que agrega valor às entidades, não possui identidade e é imutável.
  • Factory
    Classe responsável por construir adequadamente um objeto / entidade.
  • Domain Service
    Serviço do domínio que atende partes do negócio que não se encaixam em entidades específicas, trabalha com diversas entidades, realiza persistência através de repositórios e etc.
  • Application Service
    Serviço de aplicação que orquestra ações disparadas pela camada de apresentação e fornece DTOs para comunicação entre as demais camadas e para o consumo da camada de apresentação.
  • Repository
    Uma classe que realiza a persistência das entidades se comunicando diretamente com o meio de acesso aos dados, é utilizado apenas um repositório por agregação.
  • External Service
    Serviço externo que realiza a consulta/persistência de informações por meios diversos.

E o código como fica?
O mais importante é entender os conceitos, uma vez que cada um deles estão claros escrever o código é a parte mais fácil. Num próximo material eu trarei uma implementação destes conceitos.

Resumindo

O conceito de bounded context deve ser aplicado buscando delimitar os comportamentos do domínio com base em suas intenções, dando claro entendimento do que precisa ser desenvolvido de forma independente e compartilhada.

Trabalhar com DDD não significa abordar uma arquitetura dividida em camadas responsáveis sendo uma delas a camada de domínio, significa trabalhar a complexidade do negócio em uma modelagem que atenda as necessidades de forma clara, coesa e respeitando as boas práticas de desenvolvimento.

Vaughn Vernon em seu livro Implementing Domain-Driven Design aborda o conceito de arquitetura hexagonal utilizando DDD, CQRS, Event Sourcing, Domain Events, SOA e etc. Neste livro é possível entender que cada bounded context pode possuir sua própria arquitetura hexagonal ou implementar alguma outra abordagem de arquitetura como já foi citado anteriormente neste artigo.

O DDD desde 2003 vem evoluindo bastante e já não está mais preso nos conceitos iniciais, está mais aberto e flexível, permitindo diversas abordagens de arquitetura entre outras implementações como eventos e mensagerias para integrações.

Referências


Se você estiver interessado em conhecer mais e aprender como desenvolver aplicações com uma arquitetura responsável utilizando DDD, TDD, BDD, aplicando os princípios SOLID, diversos design patterns e escrevendo testes de unidade conheça meus cursos:

Vamos continuar a troca de experiências, deixe seu comentário abaixo, se gostou e concorda com o artigo compartilhe com seus colegas para transmitirmos o conhecimento para o máximo de pessoas possíveis.

32 ideias sobre “DDD – Bounded Context

  1. Parabéns Eduardo mais um artigo top. Veio em ótima hora pois eu havia visto o 3º vídeo do asp.net cast da série sobre DDD e não entendi muito bem o conceito de bounded context. Agora ficou claro show de bola.

  2. Sidnei, eu fiz o curso de Arquitetura e posso te falar que vale muito a pena o investimento.

    Para mim, foi fantástico a abordagem entre entendimento do negócio empresarial e transformá-lo em código.

    Como o Eduardo disse no curso, o curso é muito alem do código. Se nós, desenvolvedores, não entendermos a organização empresarial como ela funciona, não saberemos desenvolver aplicações que atenda-a e, principalmente, não faremos um sistema realmente profissional.

    Particularmente, recomendo à todos este curso. Estou esperando ansiosamente o pessoal da MS lançar o RTM do Asp Net Core 1.0 para termos logo o curso de ASP .Net 5 com o Eduardo.

  3. Muito bom o artigo Eduardo.

    Algumas dúvidas sobre a implementação.
    É correto dizer que para cada bounded context eu tenha uma DLL no domínio da aplicação?

    Em caso afirmativo, a camada de Application deve ser numa DLL única, ou pode ser fracionada também?

    Obrigado pela ajuda!

    • Cada bounded context é uma arquitetura totalmente independente.
      Nesse caso você pode ter sim uma camada de Application para cada contexto.

  4. Parabéns pelo artigo Eduardo, deu para clarear bastante o assunto. Posso estar um pouco enganado, mas quando leio algo sobre Bounded Context sempre me remete a idéia dos Microservices.

    Abraço e aguardamos mais artigos

  5. Muito bom.
    Estou estudando muito arquitetura, soa, ddd, solid, IoC e etc…
    E você está sendo um grande referencial para estudos…

    Para aplicar na empresa onde trabalho.
    Eu tomei a idéia de domínio e classes desacoplada, com sua camada de serviço.

    E desenhando esses conceitos para mostrar para os demais de minha equipe, meio que inconscientemente eu fiz meio que essa separação de Bounded Contexts..

    Já estou matriculado na turma de Maio de arquitetura acredito que vai ser bem esclarecedor…

  6. Onde posso deixar uma classe que sobrescreve a ConfigurationManager dentre as camadas DDD, pois ela possui dependências da camada de Apresentação e ao mesmo tempo direciona a camada de Infraestrutura para uma base de dados especifica.

  7. Olá Eduardo,

    Achei muito intuitivo seu artigo. Obrigado por disponibilizá-lo. Fiquei com um certo receio sobre a afirmação “Duplicar código é ter a mesma responsabilidade em trechos de código diferentes.”, o que na verdade eu concordo. Porém, eu acho dificil o conceito de que dois contextos não compartilhem alguma responsabilidade concernente a uma entidade comum (embora modelada conforme seus respectivos contextos). Poderia explarecer isso melhor, ou incluir algo a respeito em seu novo artigo?

  8. Obrigado, por sempre dar a comunidade ótimos matérias e com uma explicação que por isso essa frase demonstra o todo (SOMOS TODOS EDUARDO PIRES) kkk melhor que tem um curso de arquitetura que Eduardo ministra e ensina esse tema com implementação . Fica a dica façam o curso.

  9. Oi Eduardo, confesso que tenho dificuldade na implementação do conceito

    será que seria correto uma implementação de Bounded Context utilizando C# assim:
    **Separar o a classe do dominio em namespaces diferentes;
    **Utilizar o modificador partial na classe que se quer contextualizar para “separar” as partes que mudam conforme o contexto?

    Ex: Em Marketing
    public partial class Produto
    {
    // Propriedades e methodos ref a marketin;
    }

    Ex: Em Vendas
    public partial class Produto
    {
    // Propriedades e methodos ref a Vendas;
    }

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *