Skip to main content


Domínio do Negócio


Vamos explorar a identificação dos desafios do empreendimento, a compreensão dos problemas, a formulação de uma linguagem unificada para a comunicação com a empresa, a modelagem de um domínio e seus subdomínios, e a elaboração das ferramentas necessárias para comunicação e documentação com o cliente. Adicionalmente, abordaremos os Contextos Delimitados e seu papel crucial no DDD.



Descoberta e formação do conhecimento


Estabelecemos o desafio de desenvolver sistemas, exploramos Domínios, Subdomínios, Domain Experts e técnicas para mapear histórias. Mas como podemos unir esses aspectos?


Como já destacado, o DDD visa compreender as necessidades do negócio e identificar o que realmente agrega valor.



O desafio do negócio


Quando discutimos o desafio do negócio, estamos abordando as atividades, processos e obstáculos que o negócio enfrenta. Não se trata apenas de listar o óbvio, mas sim de compreender profundamente a realidade operacional, reconhecendo que nossa percepção do Domain Expert é limitada ao que é expresso e observado no presente.


Para avançarmos, é essencial uma comunicação clara e bidirecional entre os Domain Experts e os desenvolvedores. Ambas as partes precisam entender e serem entendidas mutuamente.



A linguagem Ubíqua


Durante a descrição do cenário, o Domain Expert usa termos específicos do negócio, que podem ter diferentes significados em diversos contextos da organização. Por isso, é essencial definir claramente esses termos para cada cenário e subdomínio, garantindo uma comunicação eficaz entre o negócio e a equipe de desenvolvimento.


Esses conceitos fazem parte da linguagem ubíqua, que utiliza terminologias específicas do contexto do negócio para facilitar a comunicação e compreensão. No entanto, durante o mapeamento, podem surgir problemas como termos ambíguos e sinônimos. Para lidar com isso, é importante estabelecer definições claras para cada termo, evitando conflitos e ambiguidades no futuro.


Diferença entre Ambíguo e Sinônimo:

  • Termos Ambíguos
    Dentro de um subdomínio, um mesmo termo pode ter vários significados. Por exemplo, o termo "política" pode se referir a uma lei regulatória ou a uma regra interna de uma organização. Para lidar com isso na linguagem ubíqua, é necessário definir claramente cada termo, estabelecendo uma definição para cada significado.

  • Termos Sinônimos
    Dentro de um subdomínio, um único termo pode ser usado para diferentes significados que têm distinções importantes. Por exemplo, na área de TI, usamos frequentemente o termo "login" para se referir tanto ao ato de autenticação no sistema quanto à conta do usuário. É crucial, sempre que possível, distinguir esses termos e fornecer definições únicas e específicas na linguagem ubíqua para evitar conflitos e ambiguidades futuras.



Modelagem do Domínio


Ao elaborar um modelo do Domínio, estamos criando uma representação abstrata de um processo no qual buscamos resolver um problema específico. Essa documentação desempenha um papel crucial ao conduzir discussões com os Domain Experts e ao extrair todas as informações necessárias para compreender o problema em questão. A linguagem ubíqua, mencionada anteriormente, desempenha um papel fundamental na harmonização da comunicação entre todas as partes envolvidas.


É fundamental destacar que, à medida que avançamos na elaboração do modelo, também realizaremos refinamentos. Os princípios discutidos anteriormente, como a distinção entre a realidade atual e o desejo futuro, serão aplicados durante as iterações do modelo. O foco naquilo que é essencial e a utilização de uma linguagem comum (ubíqua) nos auxiliará na criação de um modelo mais preciso e na formulação de uma solução que reflita fielmente as necessidades identificadas.


Existem várias ferramentas disponíveis para catalogar modelos e manter um dicionário da linguagem ubíqua. Entre essas ferramentas, destacam-se as Wikis, plataformas de colaboração como o Notion.io, entre outras. Independentemente da ferramenta escolhida, é crucial manter todas as informações atualizadas à medida que as interações ocorrem.



Ferramentas


Como observamos até o momento, é de suma importância mantermos um controle detalhado de todas as atividades que realizamos, garantindo que tudo seja devidamente catalogado. Isso nos permite compartilhar informações facilmente e manter tudo atualizado conforme avançamos.


Não há uma solução única ou "fórmula mágica" para isso, mas é essencial estabelecer uma estrutura que ofereça suporte e seja fácil de ser utilizada por todos os envolvidos no processo de desenvolvimento. Um exemplo prático é a criação de uma Wiki que centralize todos os recursos relacionados ao projeto, incluindo:


  • Uma seção na Wiki contendo uma descrição detalhada do projeto.
  • Outra seção dedicada à equipe do projeto, especialmente se houver mais de um time envolvido.
  • Páginas individuais para cada subdomínio do projeto, garantindo uma abordagem organizada e detalhada para cada aspecto.
  • Uma seção específica para a linguagem ubíqua, funcionando como um "Dicionário" para termos e conceitos utilizados no contexto do projeto.
  • Uma área destinada aos cenários desenvolvidos, incluindo suas premissas e limitações.
  • Links para um repositório do GitHub contendo os códigos fonte do projeto e sua documentação correspondente.
  • Links para ferramentas de gestão do projeto que estão sendo utilizadas.

Embora seja uma estrutura simples, sua implementação pode fazer toda a diferença no progresso e na eficiência do projeto.

Contextos Delimitados


Até este ponto, discutimos a importância de compreender o negócio em colaboração com o Domain Expert para projetar uma solução baseada nos processos empresariais. Identificamos o domínio e seus subdomínios, entendendo como cada um contribui para a estratégia da empresa.


Agora, começamos a estabelecer limites para nossa solução, que não são definidos pelos subdomínios, mas sim por contextos delimitados, também conhecidos como Bounded Contexts. Aqui estão alguns pontos-chave a serem considerados:

  • Não há uma regra fixa para determinar o tamanho de um contexto delimitado; isso depende da análise do arquiteto. A linguagem ubíqua é uma métrica valiosa nesse processo: se a terminologia e os processos de negócio são semelhantes em dois contextos, pode ser vantajoso agrupá-los; caso contrário, separá-los pode ser mais benéfico.

  • O tamanho de um contexto não determina necessariamente a quantidade de recursos necessários. Mesmo que um contexto seja grande, não significa que requer um grande time de desenvolvimento. É crucial entender as dependências entre os recursos e evitar paralelismos desnecessários no desenvolvimento.

  • O número de contextos delimitados pode refletir o número de times de desenvolvimento envolvidos, mas esse número pode ser refinado conforme o modelo evolui, com a integração gradual de contextos e a redução da quantidade.

  • Em alguns casos, um único contexto delimitado pode abranger toda a solução, especialmente se for pequena. Por outro lado, sistemas grandes e complexos podem exigir múltiplos contextos delimitados sem agrupamento.


É importante destacar que cada contexto delimitado é trabalhado por um único time e não é compartilhado entre equipes, embora um time possa trabalhar em vários contextos. Isso ocorre, pois, os times criam uma linguagem própria para se comunicar, que muitas vezes está atrelada à linguagem ubíqua e aos processos de negócio que estão trabalhando.


Contextos delimitados são limites que impomos em um modelo de domínio. Esses limites contêm termos e definições, propriedades e operações que compartilham uma linguagem única, a linguagem ubíqua.



Trabalhando com Contextos Delimitados


Contextos delimitados fornecem clareza em relação a cada componente que desejamos construir, no entanto, devemos ter em mente que são criados vários contextos, cada um com sua linguagem específica, exceto em casos excepcionais, que serão abordados posteriormente.


O sucesso não depende de um único contexto, mas sim de vários e de suas interações. Agora vamos abordar exatamente esse ponto: como podemos integrar esses contextos, o que devemos observar, como planejar e lidar com cada situação.


Cada contexto delimitado será desenvolvido por uma equipe simultaneamente, o que exige disciplina na comunicação e compreensão do que está sendo feito, já que a integração é uma parte fundamental de todo o processo de negócios. Hoje, estaremos trabalhando com os padrões de design do DDD, que definem as integrações e como os contextos se unem.



Parceria


O modelo inicial de design que possuímos é o de colaboração, onde a comunicação flui de maneira contínua e os times se mantêm informados sobre as alterações em andamento, fornecendo tempo e documentação ao outro time para que possa ajustar seu contexto e manter a conexão. Essa abordagem pode ser considerada como a forma de integração, com a linguagem utilizada (não a de programação, mas sim a empregada para conectar os contextos), o tempo de resposta às adaptações e outros aspectos.


Alguns pontos cruciais a serem observados nesse modelo incluem a comunicação extremamente frequente e a normalidade das mudanças, especialmente nos estágios iniciais do desenvolvimento, durante as discussões em busca da melhor solução.


A figura abaixo demonstra os times trabalhando nos Contextos Delimitados em Formato de Parceria. Fonte: Elaborado pela FIAP (2023)

Times trabalhando nos Contextos Delimitados em Formato de Parceria



Kernel Compartilhado


Outro exemplo de colaboração que encontraremos é o de Kernel compartilhado, ou seja, uma parte do modelo que é comum a todos os contextos envolvidos e deve seguir as definições de todos para funcionar corretamente. Em nosso cenário, temos um caso desse tipo, onde observamos que dois contextos nos quais estamos trabalhando compartilham o CRM e os Relatórios, como ilustrado na figura abaixo - "Equipes trabalhando nos contextos que possuem um Kernel compartilhado". Fonte: Elaborado pela FIAP (2023)

Equipes trabalhando nos contextos que possuem um Kernel compartilhado


Com base no contexto fornecido, parece que a comunicação é crucial neste caso, pois viola o princípio de contextos isolados. Múltiplas equipes estão trabalhando nas soluções, e há demandas distintas ocorrendo na mesma solução. O desafio aqui é que qualquer mudança na solução afeta todos os contextos envolvidos. Portanto, qualquer alteração deve ser testada para todos os cenários em todos os contextos.


A implementação de um kernel compartilhado é desafiadora, pois envolve compartilhar o mesmo código com todas as equipes envolvidas. No entanto, esse tipo de modelo é desencorajado, mas, se absolutamente necessário, deve ser analisado e coordenado com muita atenção para evitar perda de dados ou problemas de execução.


Há casos em que o uso de um kernel compartilhado é inevitável, como em sistemas legados que não foram construídos para separar seus contextos. Nessas situações, o compartilhamento do kernel é essencial durante a modernização da solução.


Para resumir, a comunicação deve ser essencial, e a implementação de um kernel compartilhado é desafiadora, mas necessária em certos casos, como na modernização de sistemas legados.



Cliente-Fornecedor


Transitamos agora para o segundo modelo de design que podemos encontrar, denominado Cliente-Fornecedor, em que:

  • Fornecedor (Upstream):
    Fornece um serviço.

  • Cliente (Downstream)
    Consome um serviço.


Neste modelo, os times que desenvolvem os contextos podem fazê-lo separadamente, mas existe uma dependência de um serviço. Nessa situação, os times podem enfrentar desafios de integração, semelhantes ao modelo de parceria. Agora, os times têm autonomia para decidir como desejam se integrar. Vamos analisar nosso cenário, conforme ilustrado na figura abaixo - "Cenário que exibe os contextos, times e seus relacionamentos". Fonte: Elaborado pela FIAP (2023)

Cenário que exibe os contextos, times e seus relacionamentos


Conforme podemos observar na figura acima, temos 3 contextos, cada um com sua equipe de desenvolvimento, e já elaboramos o fluxo de serviços, ou seja, quem fornece e quem consome.



Conformista


No nosso cenário, optamos por empregar um serviço de terceiros que opera com OAuth 2.0, visto que já utilizamos os serviços desse provedor. No entanto, é necessário desenvolver nossa própria camada de gerenciamento de identidade e acesso para controlar as permissões de acesso em nosso ambiente.


Como o serviço de autenticação é fornecido por um provedor externo, o qual atende a diversos clientes globalmente, não podemos negociar para que ele se adapte às nossas necessidades. Nesse caso, quem dita as regras na relação é o fornecedor, ou seja, precisamos nos ajustar para trabalhar com o padrão estabelecido e adaptar nossa solução para utilizar esse padrão, como ilustrado na figura abaixo - "Cenário em que o cliente se adapta ao que é fornecido pelo provedor". Fonte: Elaborado pela FIAP (2023)

Cenário em que o cliente se adapta ao que é fornecido pelo provedor


Quando o padrão de serviço é definido pelo fornecedor (U) e este não abre mão de seu protocolo, ou seja, ignora as solicitações do cliente, este último precisa se adaptar e ajustar-se ao que é fornecido pelo fornecedor. Esse é o modelo de conformidade.



Anti-Corruption Layer


Agora que possuímos a integração do nosso contexto de identidade e acesso, ele deve fornecer serviços para os contextos que estão "abaixo", conforme ilustrado na figura abaixo - "Cenário em que um contexto fornece serviços aos demais contextos". Fonte: Elaborado pela FIAP (2023)

Cenário em que um contexto fornece serviços aos demais contextos


Entretanto, haverá uma situação em que o CRM, com o Time 1 e o Time 2 trabalhando, não aceita o padrão vindo do Time 3, do contexto de identidade e acesso. O Time 3 não tem intenção de alterar seu protocolo para atender à demanda do CRM, que por sua vez também não tem intenção de modificar seu protocolo para se adequar ao anterior, resultando em uma falta de conformidade. Diante disso, os Times 1 e 2 optam por criar uma camada para abstrair o protocolo de identidade e acesso e convertê-lo para seu próprio modelo, preservando assim a integridade de sua solução.


Essa camada é conhecida como camada anticorrupção, ou anti-corruption layer (em inglês), abreviada como ACL. Dessa forma, nosso modelo de integração fica conforme a figura abaixo - "Cenário em que um contexto interno cria uma camada anticorrupção". Fonte: Elaborado pela FIAP (2023)

Cenário em que um contexto interno cria uma camada anticorrupção


Você pode estar se indagando: em que circunstâncias é aconselhável utilizar uma ACL?

  • Quando o contexto do Cliente (D) possui um subdomínio principal. Isso previne a corrupção ou interferência na implementação do domínio principal, isolando os códigos.

  • Quando o modelo do Fornecedor (U) é ineficaz ou não atende completamente às necessidades do cliente. Neste caso, uma ACL é criada para filtrar apenas o essencial. Esta solução é frequentemente empregada em integrações com sistemas legados.

  • Quando o Fornecedor (U) altera frequentemente seu protocolo, o que aumenta a complexidade da solução. Com uma ACL, a manutenção é centralizada neste código.



OHS - Open-Host Service


Nos casos anteriores, discutimos situações em que o fornecedor (U) tinha o controle da solução e "forçava" o cliente a se adaptar à sua realidade. No entanto, e quando o cliente (D) tem a preferência na integração?


Agora, o fornecedor (U) fornece uma camada de integração na qual expõe seus serviços, permitindo que o cliente (D) não precise se adequar, mas sim utilizar algo padronizado que não muda com o tempo. Isso auxilia o fornecedor (U) a separar seus desenvolvimentos internos do que é disponibilizado aos clientes (D) e permite que estes se conectem usando um protocolo que permanece inalterado e está aberto. Esse é o Serviço de Host Aberto ou Open-Host Service (OHS).



Linguagem Publicada (Published Language)


O protocolo que discutimos anteriormente refere-se à linguagem utilizada pelo cliente (D) ou pelo fornecedor (U). Aqui, daremos um passo além do Serviço de Host Aberto (OHS), pois além de publicar o protocolo, o fornecedor (U) pode criar uma abstração adicional, que é a linguagem utilizada pelo cliente (D), como exemplificado na figura abaixo - "Cenário em que, além do serviço de host aberto, também temos as linguagens do cliente implementadas". Fonte: Elaborado pela FIAP (2023)

Cenário em que, além do serviço de host aberto, também temos as linguagens do cliente implementadas


Dessa maneira, além de o fornecedor (U) conseguir desenvolver sua solução internamente sem afetar seus clientes, ele mantém diversas versões personalizadas de linguagem, uma para cada cliente, mantendo seu protocolo aberto e não impactando o cliente (D).


Alguns dos mercados que utilizam muito essa tecnologia são:

  • Mercado financeiro, com bancos, adquirências (Stone, Cielo, Rede, entre outras), cartões de crédito etc.
  • Mercado logístico, transporte (integração de documentos de transporte), controle de estoque (EDI para monitoramento de estoques e automação de pedidos de compra).
  • Mercado de manufatura (discreta e de processos), integração entre diversos fornecedores e clientes, padronização de protocolos etc.


Caminhos separados


Existe um modelo em que os times simplesmente não se integram. Isso acontece quando os times não têm possibilidade de comunicação, o custo de integração é muito alto em comparação com a criação de uma solução interna e não faz sentido expor o serviço a outros contextos.


No nosso caso, os times 1 e 2 decidem que seus contextos são muito distintos e optam por dividir suas soluções de relatórios. Isso ocorre porque a complexidade da estrutura tornaria a integração muito cara, e as necessidades de suas áreas são muito diferentes em relação ao que esperam de suas soluções. Com isso, a estrutura ficaria como demonstrado na figura abaixo - "Cenário em que o contexto de relatório é duplicado, um em cada contexto". Fonte: Elaborado pela FIAP (2023)

Cenário em que o contexto de relatório é duplicado, um em cada contexto


Outras situações em que podemos encontrar essa abordagem de times que não se integram incluem:

  • Sistemas de Autenticação: Em alguns casos, os sistemas de autenticação podem ser mantidos separadamente entre diferentes times ou contextos, especialmente quando existem requisitos de segurança específicos ou quando os sistemas operam em ambientes distintos que não podem compartilhar recursos de forma eficiente.

  • Sistemas de Log: Da mesma forma, os sistemas de log podem ser gerenciados separadamente por diferentes times ou contextos. Isso pode ocorrer devido a diferenças nos formatos de log necessários para cada contexto, nas políticas de retenção de dados ou até mesmo na necessidade de isolamento de registros para cumprir regulamentações específicas.



Grande Bola de Lama


Vaughn Vernon (2013), em seu livro “Implementando Domain-Driven Design”, cita a Grande Bola de Lama (Big Ball of Mud), um modelo que é encontrado em sistemas muito grandes, em que os contextos não são bem limitados e são inconsistentes. Nesse caso específico, as recomendações são:

  • Desenhe uma linha de limite em torno e chame de Grande Bola de Lama.
  • Não tente aplicar nenhum método sofisticado de modelagem.
  • Cuidado, pois essa Bola de Lama pode contaminar outros contextos.


Mapa de Contexto


Agora que criamos as integrações considerando todos os modelos, podemos finalmente desenhar o nosso mapa de contexto, que é a materialização visual dos nossos contextos delimitados e como estes se integram. Com isso, obtemos uma visão estratégica do conjunto, como é possível analisar na figura abaixo - "Mapa de contexto demonstrando todas as integrações e contextos". Fonte: Elaborado pela FIAP (2023)

Mapa de contexto demonstrando todas as integrações e contextos


O Mapa de contexto não é estático, é um documento dinâmico que requer atualizações constantes. Como mencionado anteriormente, o mapa reflete a integração dos contextos e assegura a coesão dos subdomínios.