Arquitetura de Software

O que é DDD – Domain Driven Design

Por em

O que é DDD ou Domain Driven Design?

“É um conjunto de princípios com foco em domínio, exploração de modelos de formas criativas e definir e falar a linguagem Ubíqua, baseado no contexto delimitado.”

Os 3 princípios do DDD

Antes de percorrermos com mais detalhes os principais pontos do DDD, é fundamental que consigamos entender de forma clara seus três pilares e como os mesmos têm relação entre si.

O que é domínio?

Domínio é o coração do negócio em que você está trabalhando. É baseado em um conjunto de ideias, conhecimento e processos de negócio. É a razão do negócio existir. Sem o domínio todo o sistema, todos os processos auxiliares, não servirão para nada.

Se uma empresa existe, é porque ela tem um core business e, normalmente, esse core business é composto pelo domínio principal.

Resumindo, sempre que se falar em domínio, estaremos falando da razão daquele software existir. Sem aquele ponto principal, não há razão para o desenvolvimento do software.

Exploração de Modelos e Formas Criativas

Quando falamos em DDD – Domain Driven Design, não falamos apenas em desenvolver um software, mas sim em entender a modelagem do projeto como um todo.
Se você não souber modelar o software, não conseguirá fazê-lo crescer e ser mantido a médio e longo prazo.

O DDD preza que os desenvolvedores façam parte do processo, entendendo o negócio e todos os seus modelos nos diferentes ângulos e não somente participando de reuniões com especialistas.

Fazendo um relacionamento com o mundo dos serviços, o novo perfil dos desenvolvedores faz com que o time participe de todo o processo, desde o levantamento de requisitos até o contato com o Domain Expert. Antigamente, o desenvolvedor apenas codificava.

Como exemplo, podemos citar um sistema de imobiliária. Você precisa conhecer toda a terminologia, como: pé direito, m², etc. Para isso é necessário sentar com o Domain Expert para entender o funcionamento do negócio e evitar problemas de comunicação.

Suponha que você irá desenvolver um ERP, um sistema bem grande, que tenha diversas áreas e contextos. Quando esse sistema começa a crescer, pode ficar impossível mantê-lo, não necessariamente devido ao código, mas sim pelo fato de não saber mais a relação de uma entidade com a outra, de um ponto com o outro e suas relações de negócio.
Neste caso, o DDD ajudará no processo.

Linguagem Ubíqua

Um dos pontos mais importantes do DDD, onde 99% das pessoas acabam ignorando, que é falar e extrair a linguagem Ubíqua.

Linguagem Ubíqua é a linguagem falada no dia dia, no contexto da empresa. É a linguagem que utiliza as terminologias da realidade do negócio.

Como citado anteriormente, no sistema de imobiliária é necessário conhecer as terminologias que eles utilizam no dia a dia, como pé direito, m², tipo de acabamento, etc. Em um sistema para uma construtora é necessário saber os termos que o pedreiro utiliza com o mestre de obras, este com o engenheiro, o engenheiro com o arquiteto e assim por diante.
São termos que você, desenvolvedor, ignora e é fundamental conhecê-los, pois a falta de entendimento dessa terminologia do dia a dia é o primeiro passo para o software dar errado.

O contexto é tudo quando falamos em DDD.

Podemos falar do termo usuário. Alguns entenderão como alguém logado no sistema. Outros poderão chamar de cliente e ainda terão aqueles que entenderão como qualquer aplicação que se conecta com o sistema.

Veja que utilizamos a mesma palavra com significados diferentes e não estão errados. Esse termo terá um significado diferente, dependendo de cada negócio ou realidade empresarial.

Por esse motivo é importante extrair essa linguagem Ubíqua. O time de desenvolvimento falará diretamente com com o Domain Expert, que é a pessoa que trabalha na empresa e conhece o negócio, utiliza seus sistemas e opera muitas vezes seus processos.

História do DDD

O DDD é muito famoso e normalmente pessoas o conhecem pelo livro de capa azul. O autor é Eric Evans e foi publicado em 2003.
Antes do lançamento do livro ele já vinha falando sobre o assunto e o livro foi a consolidação do tema.

O Eric fala que o DDD é totalmente mutável e que pode se desenvolver conforme o tempo.
Atualmente, no mundo dos microserviços está evidente o “boom” do DDD, e porque DDD e micro serviços fazem total sentido.

Normalmente o DDD é utilizado para aplicações complexas e é muito fácil de entender.
Certamente você achará fácil e simples de entender, porém muito difícil de aplicar.

Podemos dizer que a grande sacada do DDD é que, na área técnica, ele utiliza vários padrões de projetos.

Preste atenção ao fato que, não é porque você utilizou alguns padrões em seu projeto, realizou algumas implementações , significa que você está utilizando DDD. Este é um erro comum entre as pessoas.

O livro do Eric Evans apresenta principalmente os conceitos DDD, porém, muitas pessoas o compram esperando aprender a codificar, com exemplos de código, etc; mas o livro apresenta os conceitos.

Os Pilares do DDD e alguns exemplos

O DDD possui três pilares: linguagem ubíqua, bounded contexts e context maps. Se você entender esses três principais pontos, terá uma base conceitual para começar a trabalhar com DDD. Entender esses pontos, significa compreender o propósito do DDD, não significa que você irá codificar.

Linguagem Ubíqua

Linguagem Ubíqua

A ideia principal é você fazer a ligação da Linguagem Ubíqua entre os Experts no Negócio e os desenvolvedores. Quando eles conseguem definir quais são os termos que eles mais irão utilizar, essa extração fará toda a diferença no processo de desenvolvimento e comunicação na aplicação. Quando utilizamos a Linguagem Ubíqua é muito importante que esteja tudo organizado e extraído.

Iniciaremos trazendo um exemplo de glossário do projeto que iremos simular aqui. O grande ponto é que existem diversas maneiras de você criar esse glossário. Alguns criam um documento no docs, outros fazem uma planilha no excel, criam uma página na intranet, enfim, o importante é criar este documento que será utilizado na interação com o Domain Expert e até para codificar, evitando qualquer problema de comunicação.

As palavras abaixo, isoladas, podem ter diferentes significados e até podemos utilizar alguns sinônimos. Por isso a importância da Linguagem Ubíqua, que coloca o preto no branco. A ideia é fazermos uma modelagem de uma mini Netflix.

Linguagem Ubíqua – Exemplo de Glossário
Playback:
Processo de execução de um vídeo
Vídeo:
Conteúdo que será visto pelo usuário
Capa:
Figura descritiva de um vídeo
Perfil:
Perfil gerado pelo usuário para separar os utilizadores e suas preferências e “Minha Lista”
Minha Lista:
Lista de vídeos usada pelo usuário para armazenar os vídeos que tem interesse em ver depois
Título:
Nome do vídeo
Pessoas:
Personagens que fazem participação em determinado vídeo
Gênero:
Estilo que define um tipo de vídeo. Ex.: drama, terror, comédia
Catálogo:
Catálogo de vídeos disponibilizados

Uma vez definido o glossário, as palavras serão utilizadas até o final do projeto.

Bounded Contexts

Os Bounded Contexts ou contextos delimitados, delimita os contextos da aplicação. Cada contexto possui suas responsabilidades claramente definidas que por sua vez pode ter sua própria linguagem Ubíqua. A utilização de histórias e levantamento do escopo do projeto com o Domain Expert auxilia no processo de delimitação de contexto.

Bounded Contexts – Exemplo de História
  1. Cria uma conta para acessar o sistema
  2. Faz o login
  3. Seleciona o plano de acesso e realiza a assinatura
  4. Cria um perfil de acesso
  5. Navega no catálogo de vídeos
  6. Realiza uma busca através do título e/ou gênero
  7. Adiciona os vídeos, que tem interesse, em sua lista
  8. Acessa o vídeo escolhido e faz o playback

Com os dados acima, já é possível extrair muitas informações para delimitar os contextos, definir as entidades e ações que iremos realizar.

Note que, quando definimos um sistema utilizando DDD, conseguimos ter uma visão geral e separar as entidades direcionando para o seu devido contexto.

Depois de entender a Linguagem Ubíqua e os Bounded Contexts e já ter uma ideia do funcionamento do sistema, criaremos uma modelagem estratégica.

Modelagem Estratégica

A Modelagem Estratégica é a definição dos contextos que utilizaremos no sistema.

Modelagem estratégica

Os itens acima são os contextos delimitados, que têm as suas regras, suas operações e muitas vezes a sua própria Linguagem Ubíqua.
Perceba que os itens estão separados por cor e estão relacionados.

Vídeo é um domínio principal, pois sem o vídeo esse sistema não funcionaria, porque ele é a razão de existir da Netflix, que é o sistema proposto.

Catálogo é considerado um domínio principal, pois sem ele não é possível acessar os vídeos.

Pagamento podemos chamar de domínio genérico, pois ele ajuda em todo o processo, faz com que o domínio principal funcione. É genérico porque ele trabalha independente e pode servir para diversas coisas, não somente para o pagamento de vídeo.

Assinatura também é um domínio genérico, porque pode servir para qualquer coisa, nesse caso, auxiliará no nosso sistema.

Perfil é considerado domínio genérico porque não é considerado o ponto principal do sistema. No caso da nossa aplicação, o perfil pode ser dos dados do usuário, como também estar relacionado com os tipos de vídeo que o usuário assiste, a faixa etária, etc.

A minha lista é domínio genérico, pois o sistema funcionaria independente da sua existência.

Autenticação é considerada um domínio auxiliar, pois a partir da autenticação que todo o sistema funcionará. Pode até ser confundida com domínio genérico, mas não é, pois ela auxilia, inclusive, os domínios genéricos a funcionarem.

Resumindo, quando conseguimos entender quais os contextos e tipos de domínios que temos na aplicação e como eles podem se relacionar, ficará muito mais fácil o desenvolvimento da aplicação.

Context Map

O terceiro pilar do DDD é o Context Map, que nada mais é que o mapeamento dos Bounded Contexts.

Context Map

Observe que neste Context Map a relação entre os domínios principais e genéricos são upstream/downstream, respectivamente. Isso porque o domínio principal é prioridade em relação ao genérico. Se alguma coisa mudar, terá que ser do lado do domínio genérico. É uma relação cliente/fornecedor. No nosso exemplo de mini Netflix, os contextos catálogo, minha lista, perfil e vídeo possuem um núcleo compartilhado e são parceiros.

No caso da relação entre domínios genéricos, prevalece o que não temos autonomia para alterar. No nosso exemplo, assinatura/pagamento, não temos controle sobre a API de pagamento, logo a relação é pagamento/assinatura, respectivamente upstream/downstream. Neste caso, chamamos de relação conformista. O que podemos fazer é criar uma camada anti-corrupção para não termos que refazer todo o processo de pagamento, caso haja alguma alteração na forma de pagamento.

Em relação a autenticação temos um núcleo compartilhado onde todos poderão acessar esse processo. Na relação do processo de autenticação também é possível criar uma camada anti-corrupção. Com isso, caso haja alteração na forma de autenticação, não haverá problemas com o resto do sistema, pois estaremos acessando a camada anti-corrupção.

Observando esse Context Map que organizamos, concluímos que o DDD é uma questão de relacionamento e de entendimento de linguagem ubíqua, assim como o funcionamento dos contextos e seus relacionamentos.

Arquitetura Contextual

A partir do momento que temos o Context Map definido, podemos avançar para a arquitetura, que já é uma forma mais técnica de entendimento.

Observe a imagem abaixo:

Arquitetura Contextual

Vamos analisar como a arquitetura foi montada.

Criamos três categorias: Web App Tier, Background Tier e Database Tier. Separamos em colunas os domínios que, neste caso, são: Catálogo, Vídeo, Assinatura, Pagamento, Perfil, Minha Lista e Autenticação. Note que estamos delimitando o contexto desse domínio de acordo como iremos modelar a aplicação em relação a esse contexto.

A primeira coisa a observar é que definimos que no level web todos utilizarão uma camada de Single Page Application (SPA).

Catálogo – utilizaremos Layers DDD onde falaremos de camadas de apresentação, a camada de negócios e processos e a camada de infraestrutura e utilizaremos um banco de dados NoSQL para ficar mais flexível trabalhar com os documentos do meu catálogo.

Vídeo – teremos acesso a um Data Layer e teremos como background acesso a um processamento de vídeo para podermos trabalhar com os vídeos e utilizaremos um banco de dados relacional.

Assinatura – utilizaremos DDD Layers com um banco de dados Relacional

Pagamento – utilizaremos um modelo de leitura e escrita com alguns processamentos externos, que é a parte de pagamentos, por exemplo, e a forma de trabalhar com o banco de dados, nesse caso, será CQRS, onde temos a divisão de base de leitura e de escrita e elas não precisam ser a mesma.

Perfil – será utilizado DDD Layers e NoSQL.

Minha Lista – utilizaremos DDD Layers e NoSQL.

Autenticação – definimos que o processo de autenticação trabalhará com Single Sign On e utilizará um banco de dados relacional.

É importante observar que começa ficar mais claro a forma que estamos arquitetando a aplicação. Qualquer pessoa que visualizar, terá uma visão macro do sistema e saberá como cada contexto será tratado.

Depois de ter entendido a linguagem ubíqua, a delimitação dos contextos, ter tido um exemplo de mapa de contexto e a arquitetura contextual da aplicação, começaremos a falar sobre os pontos de implementação. Vale ressaltar que muitas pessoas começam a trabalhar com DDD desse passo em diante, ignorando todos os passos anteriores, o que não é correto.

Domain Model Patterns

Quando trabalhamos com DDD, ele utiliza Domain Model Patterns, que são padrões de desenvolvimento e estruturação de aplicações cujo domínio é o principal foco, sendo que eles estão focados em entidades de agregadores, objetos de valor, repositórios e serviços.

Domain Model Patterns

Quando falamos em Entidade de Agregadores, estamos falando no ponto principal desse contexto, que nesse caso é o pagamento.
No caso do pagamento, sempre há uma transação, que também é considerada uma Entidade. Quando trabalhamos com DDD, chamamos essas entidades de agregadores ou Aggregate Objects.

Aggregate Objects

Aggregate Objects são diversas entidades que estão no mesmo contexto e que se consomem. Como exemplo, para cada pagamento realizado há um registro de uma transação. Logo, na tabela, para cada pagamento realizado há um registro ID de transação relacionado. Sempre que falamos em agregador, devemos informar quem é o root aggregator. Em nosso exemplo é o pagamento.

Um ponto importante para ressaltar é que quando falamos em DDD e Entidades, essas possuem as propriedades, métodos, validadores, para garantir que todas as informações que elas possuem estejam corretas. Vale lembrar que não estamos falando em Banco de Dados. O DDD prega que as entidades devem desconhecer a existência do Banco de Dados, diferentemente no caso da utilização do Active Record onde a entidade conhece o Banco de Dados.

Value Objects

Objetos de Valor (Value Objects) têm as seguintes características: são imutáveis, possuem coleção de atributos, normalmente não possuem métodos setters, a entrada de valor é por um construtor e possuem tipagem forte ao invés da utilização de dados primitivos.

Veremos o seguinte exemplo onde temos uma variável de endereço do tipo string:
String endereço= rua José da Silva, 82, Centro, São Paulo
Endereço endereço=construtor(“Rua José da Silva”, “82”, “Centro”, “São Paulo”)

Observe que se fizermos uma string, o endereço é aquele e ponto.
Se criarmos um objeto de valor onde a variável endereço é do tipo endereço, o endereço agora pode ter propriedades como: rua, número, bairro, cidade. Quando trabalhamos com esse tipo de objeto, conseguimos tipificar, melhorando as relações entre as entidades e também é possível validar as informações que são inseridas e garantir que estão no formato correto.

Repositories

Os Repositórios possuem acesso direto a camada de dados podendo persistir dados e realizar as consultas. Lembrando que devemos sempre utilizar um repositório por agregação. Um repositório também pode consultar diretamente serviços externos.

Domain Services

Os Serviços de Domínio implementam a lógica de negócios a partir da definição de um expert de domínio. Trabalham com diversos fluxos de diversas entidades e agregações, utilizam os repositórios como interface de acesso aos dados e consomem recursos da camada de infraestrutura, como: enviar email, disparar eventos, entre outros.

Consolidando

Recado final

Concluímos o assunto e esperamos que com isso você tenha uma base sobre DDD. Claro que há muito mais conteúdo, mas com essa base você terá entendido a ideia principal e filosofia que o DDD traz. Observe que DDD não é apenas separar as camadas, mas sim seguir todo um processo de desenvolvimento, desde entender o negócio com o Domain Expert, extrair a linguagem ubíqua, definir os contextos, criar o mapa de contexto para poder começar a trabalhar as entidades e poder desenvolver a aplicação.

Podemos também dizer que muitas vezes é possível pegar cada um desses contextos e transformá-lo em um microserviço. Não é uma regra, mas é possível.

Esperamos que este artigo tenha lhe ajudado e que com esse conteúdo você tenha adquirido uma base sobre DDD – Domain Driven Design.

Fontes:
Domain – Driven Design – Eric Evans – 2003
Implementing DDD – Vaughn Vernon – 2013

https://gojko.net/2010/06/11/eric-evans-domain-driven-design-redefined/
https://martinfowler.com/tags/domain%20driven%20design.html