Domain-Driven Design: guia básico sobre DDD

Neste artigo você vai ver:

Conhecimento nunca é demais não é mesmo? Ainda mais quando o assunto é Domain-Driven Design (DDD), que se destaca por reunir boas práticas de design estratégico e design tático, apoiando todo o ciclo de desenvolvimento de software e possibilitando criar sistemas de alta complexidade.

Quem nunca recebeu uma pergunta matadora em um processo seletivo? Quando vamos responder, tentamos reunir diversas informações, abrindo um leque de tópicos sobre o assunto para consolidar um argumento conciso sobre o tema.

Podemos dizer que questionamentos como “O que é Domain-Driven Design?” ou “Como você aplicaria Domain-Driven Design?“, devem ser consideradas como perguntas desta magnitude. 

Principalmente, devido a tamanha dificuldade de se chegar a uma boa definição de um conceito extremamente denso como esse, que nos impede de responder essa pergunta de pronto e com total convicção. 

Tenho a intenção nesse artigo de criar uma base sobre o assunto, de forma a encaixar os seus principais pontos, como um primeiro passo nos estudos do DDD.

Afinal, o que é Domain-Driven Design?

O Domain-Driven Design, também conhecido pela sigla DDD, fornece uma estrutura para tomada de decisões, combinando práticas de design e desenvolvimento de software. 

Centrada na lógica de negócios, ou domínio, sua ideia básica propõe, por meio de uma coleção de padrões e princípios de design, auxiliar todo o ciclo do desenvolvimento,para construir aplicações que reflitam o real entendimento dos processos e regras do negócio.

O DDD está além da forma de pensar, desenhar e desenvolver o software, mesmo não sendo um padrão arquitetural, afeta em como as decisões de construir um software são tomadas.

Voltando à história, a origem do termo surgiu com o livro escrito por Eric Evans, em 2003. Desde então, uma comunidade de profissionais desenvolveu ainda mais os princípios, gerando outras importantes obras. 

Evans identificou e catalogou em seu livro os principais elementos conceituais, com foco na ideia de que para desenvolver softwares com um domínio complexo, precisaríamos construir uma linguagem ubíqua, ou seja, onipresente.

Principais pílulas de conhecimento do DDD 

Na literatura de TI, temos ótimos livros a serem explorados sobre DDD, porém neste primeiro momento irei destacar dois deles:

– “The Blue Book”: escrito por Eric Evans, em 2003, com o título “Domain-Driven Design: Atacando as complexidades no coração do software”;

– “The Red Book”: escrito dez anos mais tarde, em 2013, por Vaughn Vernon, sob o título “Implementando Domain-Driven Design”

Como disse antes, temos em mãos um assunto bastante denso, onde somando o rico conteúdo dos dois livros são mais de mil páginas de informações, para quem tem interesse em se aprofundar no assunto.

Vamos ver se você entende a referência: a fonte canônica do DDD, escrita por Eric Evans, é representada pela pílula azul; e, o livro de Vaughn Vernon, que assim como a cor de sua capa, representa a pílula vermelha. Qual se deve escolher?

Foto de uma clássica cena do filme The Matrix (1999), em que o personagem Morpheus oferece duas pílulas para o protagonista. Na foto, com um fundo bastante escuro, temos uma pessoa, porém o foco da imagem não nos permite ver o resto do corpo, somente suas mãos. A pessoa, que é negra, está com suas duas mãos estendidas oferecendo pílulas: na mão direita, temos uma pílula de cor vermelha, e na direita uma pílula de cor azul, sugerindo que existe o poder de escolha entre os dois tipos de pílulas.

Por mais que o livro de Evans não seja uma das leituras mais fáceis na literatura de software, ainda assim possui um conteúdo substancial e de extrema riqueza para toda a comunidade. 

Desta forma, a união com o conteúdo escrito por Vernon é perfeita. Sendo que esta tem como foco principal a implementação prática do DDD, trazendo consigo uma ótima representatividade sobre o design estratégico. 

Com isso, concluo que os livros são complementares e que, neste caso, o ideal seria provar as duas pílulas. 

Diferente do que acontece em The Matrix. ?

Domain-Driven Design – Décadas de conhecimento

Muita gente acredita que o DDD é um conceito moderno, uma ideia nova recém-descoberta. Na verdade, ele nasceu entre os anos 50 e 60 com o surgimento dos primeiros conceitos orientados a objetos, criados para solucionar problemas muito complexos, no qual uma abordagem procedimental não era suficiente.

No final da década de 60, surge o que muitas pessoas consideram ser a primeira linguagem orientada objeto (OOP, sigla em inglês para Object-Oriented Programming), o Simula 67, que apresentava um resumo de todos os conceitos e experiências reunidos até o momento naquela direção.

Na ilustração, temos uma linha do tempo com início nos anos 50. Em 1967, temos o marco do surgimento da primeira linguagem orientada a objeto (OOP), passando pelos anos 70 e 80. Em seguida, 1982 temos o OOAD e em 2003 chega o DDD. Mas você terá mais detalhes sobre isso nos próximos parágrafos.

Anos mais tarde, em 1982, surge um novo estágio evolutivo da OOP, porém dessa vez unindo o resultado da experiência adquirida com os anos de uso do Simula 67 e de outras Linguagens Orientadas a Objeto, com o conteúdo de novos White Papers, gerando a Análise e Design Orientado a Objetos (também conhecido como OOAD, sigla em inglês para object-oriented analysis and design).

Em 2003, surge um novo marco, com o livro escrito por Eric Evans, declarando a comunidade um novo termo: DDD. Na obra, é apresentada as melhores práticas e novos conceitos com base em anos de experiências reunidas, gerando uma estruturação evolucionária do OOAD.

Resumindo toda a experiência coletada nos próximos 10 anos após a publicação do livro de Evans, em 2013, Vaughn Vernon define o próximo estágio da evolução do DDD. 

Podemos considerar que o conteúdo aqui explicado tem pelo menos 50 anos de sabedoria e experiência da comunidade de desenvolvedores de software, sobre como lidar com domínios de problemas complexos.

Entendendo o Domain do Driven Design

Para definir o Domain-Driven Design, primeiro precisamos consolidar nosso entendimento sobre o Domain ou Domínio, em português. O termo é de extrema relevância, visto que o nosso design passa a ser orientado por esta palavra-chave, que representa simplesmente a razão do software existir.

A necessidade de um software ser construído está relacionada a um contexto delimitado de ideias, conhecimentos, processos e problemas que se deseja resolver, no qual uma empresa está inserida. 

Trazendo para o mundo real, o domínio de nosso projeto será formado por todo conhecimento absorvido sobre a empresa, assim como o modelo que ela opera.

Isso significa observar o envolvimento de regras de negócio, processos e possíveis integrações com sistemas existentes como parte da solução, sejam eles internos, de parceiros ou fornecedores.

Portanto, o Domínio representa o coração do negócio em que estamos trabalhando, com todas as suas regras e peculiaridades que o DDD visa atacar, conforme está explícito no título do livro de Evans: “Atacando as complexidades no coração do software”.

DDD – Atacando as complexidades do software

Adquirimos a habilidade de lidar com a complexidade do software, em grande parte tentando e eventualmente falhando, sendo que até mesmo com pouca vivência na área de desenvolvimento de software, percebemos que nem tudo sai conforme o planejado.

Muitas vezes, paralelo à construção do software, surgem novas necessidades, assim como aparecem pontos cegos no entendimento de um negócio, que não enxergávamos no começo do projeto. 

Principalmente para softwares complexos, temos dificuldades de solucionar o problema adequadamente, baseado na primeira versão de especificação funcional, o que dificulta sermos assertivos na melhor arquitetura a ser utilizada.

Os fatores acima, às vezes aliados à falta de engenharia bem definida ou até mesmo ao excesso de engenharia (Software Overengineering), dificultam o atendimento de mudanças impostas por novas necessidades do negócio, gerando desta forma complexidade técnica acidental.

Apresentado nesta ilustração um gráfico, onde na vertente vertical temos a Complexidade do Domínio, na horizontal, temos a complexidade técnica acidental. Em meio ao gráfico, saindo da base sobe uma linha diagonal representando a evolução da complexidade do software, que se resulta através da multiplicação da complexidade do domínio pela complexidade técnica acidental.

Conforme imagem acima, a complexidade do software resulta da complexidade do domínio/negócio, multiplicado pela complexidade técnica acidental. 

Em suma, o gráfico nos mostra que conforme o sistema cresce, a complexidade técnica acidental se torna maior que a complexidade do negócio, dificultando desta forma a manutenção e a sua evolução, problema conhecido no DDD como Big Ball of Mud.

Design estratégico x Design tático

O DDD nos apresenta dois tipos de ferramentas de design. 

A primeira delas nos ajuda a resolver problemas relacionados à modelagem de software, o design estratégico

Enquanto o design tático, que ocorre após a fase estratégica, se concentra no desenvolvimento do produto, focado nos detalhes de implementação.

O design estratégico agrupa um conjunto de princípios e padrões, para dividir um problema complexo de negócio em vários blocos com limites claros e responsabilidades específicas, construindo desta forma uma topologia de design de software de alto nível.

Já o design tático, por sua vez, possui um conjunto de padrões de abstração de componentes de nível médio e baixo do software. Com seus padrões práticos, o tático refina o resultado do design estratégico aplicado, convertendo-o em código.

O Domain-Driven Design é um processo em evolução que consiste em ciclos iterativos de aplicação de design estratégico e tático. Você começa com o design estratégico, seguido pelo design tático.

Pessoas desenvolvedoras atuam com as ferramentas de design tático, mas se tivermos conhecimento e uma boa compreensão das ferramentas de design estratégico, isso nos ajudará a arquitetar um software melhor.

Design estratégico ou modelagem estratégica

Agora que a gente já entendeu as diferenças e a relação entre design estratégico e design tático precisamos nos debruçar no design estratégico, também chamado de modelagem estratégica.

O design estratégico é um dos pilares do DDD que tem como principal objetivo definir os Bounded Contexts, a Linguagem Ubíqua e os Context Maps. Tudo com a colaboração de toda a equipe do projeto, composto pela equipe técnica e os especialistas do domínio ou Domain Expert.

Para entendermos claramente o design estratégico, precisamos entender melhor cada um desses conceitos relatados acima, formando uma base conceitual para começar a trabalhar com DDD.

Domain Expert, quem conhece o negócio

Agora, com um melhor entendimento sobre o Domain, é essencial entender o papel de um Domain Expert. 

É essa pessoa que, com todo o seu conhecimento sobre as necessidades do negócio, apoia o time de desenvolvimento de software na modelagem do domínio, descrevendo o que o sistema deve fazer, com o objetivo de que o código escrito pelo time realmente expresse o negócio.

Para construir um bom software, se faz necessário um excelente conhecimento prévio sobre o negócio. Não seria razoável criar um software complexo, sem nunca ter tido contato com aquele segmento, certo?

Vejamos o exemplo de um sistema de análise de contas médicas:

O sistema seria criado para uma empresa de planos de saúde, onde identificariam objetos de domínio, tais como remessas, lotes, guias e procedimentos médicos. Temos também as regras que regem o negócio, como: “O valor da Guia Médica deve ser igual à soma dos itens” ou “Um lote só pode ser fechado após análise, quando todas as Guias Médicas estiverem concluídas e analisadas”. Assim como podemos ter análises mais complexas, como “Procedimentos pediátricos não podem ser pagos quando realizados em adultos” ou “Procedimentos de alto custo não devem ser pagos se não autorizados pelo plano de saúde”.

Ao desenvolvermos precisamos obter o conhecimento do domínio, que pode ser extraído de documentações ou manuais de procedimento de negócios, porém certamente perguntas mais complexas surgiram, visando ser mais assertivos, precisaremos de especialistas naquele domínio. 

Voltando no exemplo da análise de contas médicas, a pessoa Domain Expert provavelmente seria um analista de contas médicas, com vasto conhecimento e autoridade no assunto, que se tornaria no futuro um usuário-chave do sistema.

Mas teremos casos onde Expert nunca usará o sistema, como profissionais de engenharia de produção que conhecem todo o processo da linha de produção, enquanto os futuros usuários do sistema serão os operadores, ou seja, nem todo usuário será uma pessoa Domain Expert. 

Não podemos nos esquecer que para alguns casos, será necessário mais Domain Experts para cobrir todas as frentes que aquele sistema abrange. Por exemplo, um ERP (Enterprise Resource Planning) precisaria de um especialista por domínio.

Afinal, o que é Linguagem Ubíqua?

As pessoas desenvolvedoras, com seu viés técnico, pensam em como transformar a necessidade do negócio em objetos, relacionamentos entre eles, aplicar abstração, herança, polimorfismo, patterns, frameworks, entre outros.

Domains Experts, por sua vez, conhecem a fundo o negócio, porém desconhecem essas terminologias. 

Levando em consideração que o software não lida bem com ambiguidades, a Linguagem Ubíqua entra em cena construindo uma linguagem comum, compartilhada entre toda a equipe, indiferente do seu papel no projeto. A fim de reduzir o enigma exposto pelo James Shore no texto abaixo.

“É um enigma. As pessoas que são especialistas no domínio – os especialistas de domínio – raramente estão qualificadas para escrever software. As pessoas que estão qualificadas para escrever software – os programadores – nem sempre entendem o domínio-problema.”

James Shore.The Art of Agile Development, página 126. Tradução livre do autor.

Ilustração simplificando o que seria a linguagem ubíqua, por meio de dois círculos: um amarelo, representando a linguagem do desenvolvimento, e o segundo de cor azul, representando a linguagem do negócio. A posição dos círculos forma uma intersecção entre eles, nesta área que os dois círculos se cruzam, temos a linguagem ubíqua, representada pela cor verde. A cor foi escolhida propositalmente devido a combinação das cores azul e amarelo.

Ao aplicá-la, traduzimos termos técnicos em expressões compreensíveis a todo mundo envolvido, o mesmo ocorre para as terminologias utilizadas pelo negócio, gerando uma intersecção entre as partes. 

Este trabalho em conjunto gera um curto ciclo de feedback, fortalecendo os laços entre especialistas do negócio e o time de desenvolvimento, produzindo desta forma um software que faz mais sentido para o negócio.

Bounded Context 

Ao lidarmos com grandes domínios, no decorrer de sua modelagem se torna complexa a construção de um modelo unificado. Visto que cada área de negócio usará um vocabulário sutilmente diferente com base no contexto que vivencia em seu dia a dia, geralmente levando a muita confusão.

Uma das principais ferramentas contidas no design estratégico, o Bounded Context ou Contexto Delimitado, nos apoia a lidar com grandes modelos de domínio, estabelecendo limites ao dividi-los em contextos menores, criando inter-relacionamento explícito entre eles.

Dentro destes limites conceituais, todos os termos e frases têm um significado específico refletindo a linguagem ubíqua, guiando o time a entender melhor o negócio e sinalizando até onde vai a responsabilidade de cada parte do sistema. 

Afinal, a fronteira entre contextos deve ser clara para todos. Além de cada contexto poder ter sua própria linguagem ubíqua, o mesmo é válido para a arquitetura do software.

Context Map 

Context Map ou Mapa de Contexto nos apresenta uma visão global do software, uma forma pragmática de gerar um documento, um rascunho, uma imagem, ou um esboço que facilite o entendimento dos contextos da aplicação. Não precisa ser nada complicado, sendo uma boa opção desenhar a mão com o uso de um quadro branco, por exemplo.

Inicialmente, desenhe um Mapa de Contexto visual da situação atual do projeto, um diagrama simples que captura o terreno existente, ele será o esboço inicial do nosso mapa. Mapeando o presente, não o futuro imaginado. Afinal, precisamos ter uma forte compreensão de onde estamos, antes mesmo de saber para onde gostaríamos de seguir.

Por não ser um documento oficial, deve ser simples, de alto nível e informal. Não se limitando a um diagrama arquitetural do sistema, mas sim abrangendo a compreensão das relações entre os contextos delimitados da corporação.

O mapa vai ajudar a equipe do projeto a entender o domínio do negócio, as fronteiras entre os contextos ou como elas podem ser integradas. Conforme o projeto avança, o diagrama deve ser atualizado, seguindo os novos cenários propostos.

Fazendo uma analogia: podemos imaginar o continente da América do Sul, com base na sua colonização, representando nosso domínio. Conforme imagem abaixo, devido ser um mapa moderno, algumas regiões foram extrapoladas pelo exemplo.

Ilustração do mapa da América do Sul, no ano aproximado de 1700, porém devido ser um mapa moderno, algumas regiões foram extrapoladas pelo exemplo. Com intuito de apresentar os territórios dos cinco países colonizadores da época. Em verde, o território hoje pertencente ao Brasil, colonizado por Portugal. Fazendo fronteira com o Amapá, em azul no mapa, temos a atual Guiana Francesa, território colonizado pela França. Ao seu lado esquerdo, em laranja claro, está o Suriname, país colonizado pela Holanda. Continuando para a esquerda, agora em cinza escuro, colonizado pela Inglaterra, o território hoje pertencente à Guiana. Os demais países, da Venezuela até a Colômbia, descendo por toda extensão que faz fronteira com o Brasil, contemplando a cordilheira dos Andes e seu entorno, até chegar ao extremo sul do mapa, temos o território em laranja escuro, colonizado pela Espanha.

A região foi colonizada por cerca de cinco países distintos, a divisão entre eles formaria nossos contextos limitados, através de fronteiras. Cada país teria seu próprio idioma onipresente, onde as leis ou regras que regem cada nação seriam o modelo de domínio. As regras estabelecidas nas fronteiras entre os países e os tratados sobre comércio entre as partes, seriam nossas integrações.

Design Tático

O Design Tático agrupa um conjunto de ferramentas a serem utilizados na construção do seu modelo de domínio, aplicados em um único contexto delimitado, refinando o resultado do trabalho realizado através das ferramentas de Design Estratégico.

Quando utilizados ​​corretamente os padrões de Design Tático, você pode enriquecer seu modelo de domínio (Domain Models), o que consequentemente refletirá o negócio com maior clareza no software desenvolvido. Conforme imagem abaixo, o Design Tático pode ser dividido em dois grupos.

Texto alternativo: A ilustração mostra dois retângulos separando as responsabilidades do Domain Models em verde, com Entities, Aggregates e Value Object. No retângulo azul, temos as responsabilidades do Domain Services, com Repositories, External Services e Cross-aggregate Behavior.

Por se complementarem, ter um conhecimento profundo do Design Tático é tão importante quanto do Design Estratégico no DDD.

Domain Models

Domain Models ou Modelo de domínio mantém o conhecimento estruturado do problema a ser resolvido com o software, representando o vocabulário e conceitos-chave do domínio, identificando os relacionamentos entre todas as entidades, atuando como uma ferramenta de comunicação, em conjunto com a linguagem ubíqua.

Deve representar claramente o problema que está sendo resolvido, assim como a solução proposta. Também pode ser expresso através de um diagrama, ou até mesmo uma documentação escrita, desde que seja acessível e compreensível por todo mundo que tem envolvimento no projeto.

Domain Service

Domain Services ou Serviços de Domínio representa uma estrutura sem estado que fornece comportamentos do mundo real dos negócios, por ser uma extensão do domínio, atua com fluxos de diversas entidades e agregações. Por ser relevante apenas para a lógica de negócios, não deve entrar em contato com detalhes técnicos. 

De forma simples, podemos entender que absorve responsabilidades do Domain que o Model não poderia realizar.

Como o modelo de domínio geralmente lida com comportamentos mais refinados, que focalizam alguns aspectos específicos do negócio, um serviço de domínio tende a seguir os mesmos princípios, fornecendo soluções para contextos de negócios que são muito complexos para serem armazenados em uma única Entidade ou Objeto de Valor.

O Serviço de Domínio não tem nenhuma semelhança com os Serviços de outras camadas, exceto o nome.

Camada Anticorrupção

Temos um conceito do DDD que tem ficado cada vez mais em evidência, principalmente devido ao alto uso dos microsserviços (microservices) nos últimos tempos, Anti Corruption Layer ou Camada Anticorrupção, em português.

A Camada Anticorrupção, acaba sendo um valioso mecanismo na proteção do domínio contra conceitos que não fazem parte do seu contexto, garantindo inclusive que o design da sua aplicação não seja corrompido por dependência de microsserviços ou sistemas externos a ele, reduzindo o acoplamento de forma que o sistema possa evoluir independente. 

Em resumo a camada anticorrupção pode ser considerada um intermediador que de maneira isolada permite apenas a troca de dados que sejam válidos entre os dois sistemas, prevenindo que não dependam do design um do outro.

Alavancas do Domain-Driven Design

Penso que uma das principais vantagens do Domain-Driven Design, está relacionado a um pilar importantíssimo em qualquer projeto: a comunicação. Enfatizando estabelecer desde o início uma linguagem comum e ubíqua relacionada ao modelo de domínio do projeto.

Assim facilitando o uso de termos da área de negócio, reduzindo o uso de jargão técnico ao discutir aspectos do aplicativo, visto que equipes de desenvolvimento usam a mesma linguagem que especialistas de domínio, resultado em um design de software que faz mais sentido para o usuário final.

Temos um alinhamento mais preciso, pois a pessoa desenvolvedora tem melhor comunicação e compreensão ao falar com a equipe de negócios usando a mesma linguagem, reduzindo o risco de possíveis confusões ou mal-entendidos.

As definições de contexto e limites tornam o software mais flexível à mudanças, pois as divisões geradas pelas separações das responsabilidades, unido com a forte base do DDD em conceitos de análise e design orientado a objetos, sugere que quase tudo dentro do modelo de domínio será baseado em um objeto. 

Portanto será bastante modular e encapsulado, diminuindo impactos ao realizarmos mudanças. Além de estabelecer boas práticas, fomentando o uso de padrões de design, obtendo desta forma gerando um código mais limpo e confiável, protegendo o conhecimento do domínio. 

Desafios do Domain-Driven Design

O Domain-Driven Design oferece diversas vantagens, mas não necessariamente funcionará para todas as situações. 

Por incentivar práticas iterativas recorrentes, o que seria uma vantagem para alguns cenários, esse quadro se distorce. Pois as organizações, muitas vezes, estão altamente ligadas a modelos de desenvolvimento menos flexíveis, como o modelo em cascata, por exemplo.

Embora seja ótimo na construção de softwares onde a lógica de negócios seja bastante complexa, pode não funcionar bem em projetos altamente técnicos, podendo ser desafiador o seu entendimento para profissionais Domain Experts e causando problemas no futuro, caso os requisitos ou limitações técnicas não forem totalmente compreendidos por todo mundo na equipe.

Citei algumas vezes neste artigo sobre o foco do DDD em domínios complexos, porque se o domínio for relativamente simples pode ser muito demorado implementar o projeto, não havendo a necessidade de separações por contextos. Com isso, caímos em outro ponto importante: se você não precisa de uma pessoa especialista em domínio dedicado, provavelmente não precisa do DDD.

Quer saber mais sobre Domain-Driven Design? Então assista a essa live em nosso canal no YouTube:

Conclusão sobre Domain-Driven Design

Importante entendermos que o DDD vai muito além do código, ele torna a equipe mais colaborativa e focada no que mais importa, gerando facilidades ao atender os complexos processos de negócio. 

Vantagens como uma efetiva comunicação entre especialistas de negócio e especialistas técnicos, tornando mais eficiente a interação entre os diversos papéis das pessoas que integram o processo de desenvolvimento de software, de forma que o código desenvolvido reflita o máximo possível o domínio.

Não se trata de uma bala de prata, altamente eficaz na resolução de todos os problemas de software. 

Assim como qualquer arquitetura de software, metodologia ágil, framework, componente ou ferramenta, temos as suas vantagens e desvantagens, onde nos requer conhecimento e análise para cada cenário, para entendermos se sua aplicabilidade realmente funciona.

Espero ter te inspirado a se aprofundar no assunto. Inclusive, devido ao seu conteúdo extremamente denso, sugiro que, antes de iniciar um projeto utilizando Domain-Driven Design, continue estudando e ampliando seus conhecimentos nos tópicos abordados neste artigo. Seja realizando a leitura de livros sobre o assunto, tais como os recomendados acima, seja assistindo vídeos e até mesmo participando de cursos específicos, se possível.

Referências

Capa do artigo sobre Domain-Driven Design (DDD), em que temos um programador negro com fone de ouvido trabalhando remotamente em casa. É possível ver detalhes da sua casa e da mesa, além de várias telas com código de programação.
foto - Danilo Masotti
Engineering Manager
Apaixonado por tecnologia, inovação e transformação digital. Em constante aprendizado, com intuito de disseminar conhecimento, de forma a impactar positivamente as pessoas ao redor, assim como o mercado de TI.

Artigos relacionados

Este site utiliza cookies para proporcionar uma experiência de navegação melhor. Consulte nossa Política de Privacidade.