No Domain-Driven Design (DDD) a organização de um sistema em Bounded Contexts (Contextos delimitados) é fundamental para garantir a clareza e a eficácia da arquitetura, sendo a relação entre eles algo muito relevante. Então, um tipo dessas relações é o Upstream-Downstream que destaca-se pela sua importância na comunicação e na interdependência entre diferentes partes de um sistema. Assim, aqui no artigo Bounded Contexts: Upstream-Downstream, exploraremos detalhadamente a relação Upstream-Downstream, seus diferentes aspectos e como ela influencia a arquitetura de software.
Aqui no blog temos muitos artigos, sendo algumas dezenas voltadas para o Domain Driven Design, como esse. Fique a vontade para explorar artigos como DDD Estratégico, DDD Tático, Bounded Contexts de dependência mútua, entre outros.
Sumário
Relação Upstream-Downstream
O Domain Driven Design considera que um software se organiza em contextos. Sistemas pequenos podem ou devem ser limitados a ter apenas um contexto. Sistemas maiores podem ser subdivididos em vários deles. Para Eric Evans alguns contextos têm características particulares ao se relacionar com outros. Pois bem, há 3 tipos de relação: dependência mútua, upstream-downstream ou livre.
Portanto, a relação upstream-downstream considera que um dos contextos tem mais poder ou importancia política do que outro. Entretanto entenda que um contexto é um pedaço do software – Claro! -; mas ele também pode ser um conjunto de atividades de processos de negócios; e também uma das áreas de operação da empresa. Entenda, então que um contexto pode nem se preocupar com outro: “O outro que se vire!”. Assim, vamos aqui explorar em detalhes como esse tipo de relação pode se dar.
O diagrama acima exibe a relação upstream-downstream com algumas formas particulares. Há o open-host Service e o published language, focados em relações cujo mote é a comunicação entre eles. Mas há também a relação customer/supplier onde é visto certo nível de respeito entre as partes. Seguindo há o conformist onde o downstream simplesmente aceita que alterações vão ocorrer no upstream e ele precisará se virar. Por fim há uma possível ponte entre o up e o down chamado anticorruption layer, para amenizar essas relações.
Exposição e comunicação
OHS: Open-host Service (Serviço de host aberto)
Essa relação se caracteriza pelo fato do upstream se oferecer como canal, disponibilizando funcionalidades para aqueles que podem se conectar. Nesse caso não há uma preocupação específica com o downstream, mas sim com a disponibilidade. Então, entenda que estamos falando de um protocolo ou interface de comunicação, tal como APIs HTTP poderiam fazer.
PL: Published Language (Linguagem Publicada)
Já nesse caso estamos falando mais específicamente do formato e da semântica envolvida na relação e não apenas na conexão (como é o caso do Open-host Service). O Published Language condidera formatos públicos amplamente aceitos. Por exemplo, um sistema poderia lidar com potenciais clientes e gerar arquivos sob o formato VCARD, reconhecido pela maioria dos gerenciadores de e-mail. Formatos como APIs utilizando SOAP ou OpenAPI também comporiam esse tipo.
OHS + PL: Open-host Service + Published Language
Fica fácil de perceber que o OHS e o PL trabalham muito bem juntos. É possível encontrar mapas de contexto que agrupam esse dois, como pode ser visto no artigo Modelando o Context Map do Zero. Nesse caso há a exposição de métodos para acessos e um padrão de linguagem bem estabelecido com semântica para as aplicações envolvidas,
Relação Customer/Supplier (Cliente/Fornecedor)
Já na relação customer-supplier consideramos que há dois contextos e em muitos casos dois setores da empresa se relacionando. Nesta relação o fornecedor tem poder sobre os clientes, entretanto, ele tem uma preocupação específica com eles tentando fazer com que os impactos de alterações desse contexto sejam reduzidos nos clientes.
Nessa relação o fornecedor estabelece formatos de comunicação que os clientes tenham condição de absorver. Além disso há ampla documentação, versionamento, plano de compatibilidade retroativa e obsolescência. Veja que uma API pública do ClimaTempo, por exemplo, tem tais preocupações e poderia ser entendida de maneira análoga a esse tipo de relação.
Relação Conformist (Conformista)
Já a relação conformist é o contrário da customer/supplier. Por mais que haja documentação, planos, etc. não há nenhuma preocupação específica do fornecedor com os potenciais clientes. Nesse caso, alterações feitas no upstream afetam diretamente o funcionamento do downstream, gerando bugs em muitos casos. O time de downstream precisa atuar o mais rápidamente possível para ajustar o seu contexto.
Podemos considerar como exemplos, sistemas que capturam dados diretamente de uma página de internet através de scrappers(quando não há API publicada). Nesses casos, alterações no layout podem causar impactos nos consumidores. Outro exemplo comum são o de orgãos reguladores do governo. Alterações neles impactam diretamente bancos (CVM, BACEN, etc.), escritórios de patentes (ANVISA, INPI), escritórios de advogadores (tribunais) entre outros.
ACL – Anticorruption layer (Camada anti-corrupção)
Pois bem, uma prática comum é tentar amortecer os impactos de alterações no upstream criando um downstream isolado. Nesse caso, ele é o único que sofre o impacto do upstream. Os downstreams passam a consumir dele que deve ter uma postura de Customer/Supplier: mais amistosa e de manipulação facilitada.
Conclusão de Bounded Contexts: Upstream-Downstream
Compreender eficazmente as relações Upstream-Downstream é essencial para o sucesso de um sistema baseado em Domain Driven Design com Bounded Contexts. Então, ao identificar claramente essas relações e aplicar estratégias adequadas, como a utilização de Open-host Services, Published Languages, e Anticorruption Layers, é possível minimizar conflitos e garantir a integridade e a evolução dos diferentes contextos de forma independente. Portanto, ao projetar arquiteturas de software baseadas em DDD, é fundamental considerar não apenas os limites dos contextos, mas também as interações entre eles, visando uma arquitetura flexível, escalável e resiliente.
Ele atua/atuou como Dev Full Stack C# .NET / Angular / Kubernetes e afins. Ele possui certificações Microsoft MCTS (6x), MCPD em Web, ITIL v3 e CKAD (Kubernetes) . Thiago é apaixonado por tecnologia, entusiasta de TI desde a infância bem como amante de aprendizado contínuo.