Quem disse que para desenvolver uma aplicação é só sentar e escrever código? Para o desenvolvimento de uma simples aplicação é necessário ter contexto das regras do negócio da sua aplicação e qual o resultado final que se deseja obter. Para alcançar isso e facilitar manutenções futuras do código, é interessante que o código reflita sobre a lógica da vida real do produto. Esse casamento entre as regras de negócio e código em si é chamado de DDD — Domain Driven Design. Em tradução literal, Design Direcionado por Domínio.  

Em contextos de domínios complexos, a divisão de subdomínios dentro de uma aplicação pode ser muito grande. A manutenção desses subdomínios pode significar uma alta complexidade técnica para a entrega de uma simples funcionalidade. Mas, para entender como fazer uma divisão inteligente, é necessário que todo time esteja engajado nas decisões estratégicas.

Ao estabelecer fronteiras entre as lógicas de negócio dentro do código bem definidos, o código se torna mais reutilizável e de manutenção mais fácil. Com facilidade de reconhecer onde fazer as alterações no código, os ciclos de desenvolvimento ficam mais curtos e acaba existindo maior colaboração, compartilhando todo o conhecimento de negócio. 

Nessa leitura, você vai entender os conceitos DDD, que permitem que todo esse engajamento entre a aplicação, as pessoas desenvolvedoras e experts de negócio aconteça. Confira: 

O que é DDD (Domain Driven Design), como surgiu e quem criou?

O DDD — Domain Driven Design — é um conceito que foi introduzido à literatura por Eric Evans, em 2004, no seu livro Domain Driven Design: Tackling Complexity in the Heart of Software. Em tradução literal, Domain Driven Design: Atacando as complexidades no coração do software. Antes do lançamento do livro, Evans já falava sobre o assunto, mas o livro é considerado um marco para disseminação do conceito. 

Uma das características do DDD, segundo Evans, é a sua mutabilidade que pode ser desenvolvida com o tempo. Essa característica fica evidente num contexto de microsserviços, em que cada um tem uma responsabilidade definida e que pode ser desenvolvida de forma independente. Um microsserviço pode alterar uma parte do seu contexto sem ser necessária a alteração de todas as aplicações que o utilizam. 

Como DDD se trata de um conceito, ele pode estar presente em arquiteturas de projeto distintas. No entanto, o fato de seguir o DDD em algumas implementações não significa que se utiliza DDD para toda aplicação. Para isso, é importante entender os seus conceitos e abstraí-los para aplicar no processo de desenvolvimento diariamente. 

O que é domínio?

O domínio de um software é dado pelas atividades realizadas pela pessoa usuária e todas as regras relacionadas a essas atividades

Assim como sua definição é ampla, um domínio pode ser complexo e possuir subdivisões dentro dele também de grande complexidade. 

Quais os 3 pilares/princípios do Domain Driven Design? 3 exemplos!

O DDD é composto por 3 pilares: 

  • ubiquitous language, na tradução literal, linguagem ubíqua;
  • bounded contexts, na tradução literal, contextos delimitados;
  • context maps, na tradução literal, mapas de contextos. 

Esses pontos são descritos a seguir. Entendendo cada um deles, você terá uma base conceitual necessária para começar a trabalhar utilizando DDD.

Linguagem Ubíqua

A linguagem ubíqua, do inglês ubiquitous language, é a linguagem de comum entendimento das pessoas expertas das regras do negócio e as pessoas desenvolvedoras. Ou seja, todo vocabulário forma um glossário que reflete conceitos comuns para essas pessoas. 

A definição das palavras que compõem esse glossário é feita em conjunto e é essencial para facilitar todo o processo de desenvolvimento e comunicação, pois, uma vez estabelecida, é muito fácil tirar dúvidas das pessoas envolvidas sabendo que se está falando de um mesmo conceito. 

Vamos levar em consideração o contexto em que será construída uma aplicação de aluguel de bicicletas. Considere o glossário: 

Bicicletas – Objeto que será alugado, cujas características serão armazenadas na aplicação

Usuário/Cliente – Pessoa que alugará a bicicleta, cujos dados serão armazenados na aplicação

Perfil – Espaço na aplicação onde a pessoa visualiza seus dados e pode editá-los

Estação – Local físico onde a pessoa poderá retirar sua bicicleta, cujos dados ficam armazenados na aplicação

Localização – Entidade responsável por verificar a localização da pessoa usuário no momento do aluguel

Meu histórico – Lista o histórico de aluguéis da pessoa usuária com localização da estação de retirada e de entrega e data/hora do aluguel

Pagamento – Parte em que o usuário efetua o pagamento do aluguel único da bicicleta

Observe que, com essas palavras fora de contexto, elas podem significar coisas completamente diferentes. Por isso, ao estabelecer a Linguagem Ubíqua, salva-se o tempo de todas as pessoas envolvidas no projeto, além de facilitar todo o processo de comunicação. 

Bounded Context

Os contextos delimitados, do inglês Bounded Contexts, são os contextos com fronteiras bem definidas. Cada contexto da aplicação deve ter responsabilidades bem definidas e uma linguagem ubíqua relacionada a ele. Para elaboração das funcionalidades, é importante a descrição detalhada do escopo de cada história. 

Um exemplo para nossa aplicação de Aluguel de bicicletas, considerando o caminho feliz apenas, seria: 

Exemplo de História de uso do aplicativo:

  1. Criar uma conta na aplicação.
  2. Fazer login na aplicação.
  3. Adicionar seus dados para salvar em seu Perfil.
  4. Habilitar o GPS para compartilhar a localização com a aplicação. 
  5. Visualizar uma mensagem de confirmação se a Estação em que se localiza corresponde à captada pelo GPS. 
  6. Habilitar a câmera para captar os dados da Bicicleta via QR Code.
  7. Visualizar mensagem de confirmação de dados coletados. 
  8. Visualizar tela para preenchimento das informações de Pagamento
  9. Inserir as informações de Pagamento.
  10. Visualizar mensagem de confirmação da Bicicleta liberada.

Uma vez que definimos as informações acima é muito mais fácil delimitar os contextos, definir as entidades da aplicação e as ações particulares a cada uma. Isso permite que o time tenha uma visão geral do produto e assim direcionar o desenvolvimento pelo domínio, ou seja, utilizando DDD. 

Context Maps

Os mapas de contexto, do inglês Context Maps, é o mapeamento dos Bounded Contexts

Mapas de Contexto Domain Driven Design

Fonte da Imagem: A autora

Observe que nesse Context Map existe a relação entre domínios principais e domínios genéricos. Os domínios principais são upstream, ou seja, têm prioridade em relação aos genéricos, que são downstream. Isso significa que na ordem de prioridade, quando alguma coisa mudar, será prioritariamente do lado dos domínios genéricos.

Já na relação entre domínios genéricos, a regra é dita pelo que não temos autonomia para alterar. Por exemplo, no caso dos domínios de Localização e Estação, considerando que vamos utilizar uma API de Localização do Google, só temos controle sobre as requisições a ela, mas não no seu funcionamento de ponta a ponta. Logo, a depender de como a API de Localização funciona, será definido como será a Estação. Esse tipo de relação é denominada relação conformista

Caso haja alguma alteração na API de localização, o que podemos fazer para contornar essa alteração é uma camada de anticorrupção, cujo nome é auto explicativo: ela garante que o domínio que utiliza dos serviços de outro (no nosso caso Estação) não seja corrompido pelas alterações desse (a API de Localização). Outra situação que podemos empregar a camada de anticorrupção seria na autenticação, caso ela seja via API. 

Agora, com os três conceitos DDD bem definidos, fica evidente que DDD se baseia no entendimento dos contextos e seus relacionamentos, fortalecidos da linguagem ubíqua estabelecida. Com isso entendido, podemos partir para entender como modelar nossa aplicação. 

O que é o Modelo e para que serve?

Segundo Evans, o modelo é uma abstração de um conceito que define o domínio. É uma interpretação da realidade que abstrai alguns aspectos dela para resolver o problema em questão.

Vamos imaginar a partir do nosso exemplo de uma aplicação para aluguel de bicicletas: são coisas intuitivas que fazem parte do nosso domínio e que determinam o nosso modelo. Por exemplo, a pessoa usuária, o seu pagamento e a própria bicicleta, precisam de abstrações dentro do nosso código para refletir a situação real

Exemplo de um Modelo em DDD

Fonte: imagens na referência e esquema da autora

São características de um modelo: 

  • Permitir a comunicação assertiva entre membros do time, pois o conceito do negócio definido dentro da aplicação aliado à linguagem ubíqua permite que todos participem da construção do modelo. 
  • Garantir que a especificação das características de cada conceito sejam implementadas.
  • Definir a estrutura dos conceitos da aplicação de maneira que torna possível a abstração por parte das pessoas desenvolvedoras de outras partes do código, relativas às atividades dos modelos, por exemplo. 
  • Simplificar os conceitos, permitindo a estruturação do conhecimento de todo o domínio

Modelagem evolutiva e mutável 

A modelagem de conceitos é evolutiva e mutável. A cada interação entre as pessoas expertas de domínio e as pessoas desenvolvedoras, o modelo se torna mais profundo com relações e aspectos mais ricos. Assim como também outros modelos podem ser criados e definidos a fim de que a aplicação reflita a realidade da forma mais fiel possível. 

À medida que novas funcionalidades são criadas e novas regras de negócio são adicionadas à aplicação, os modelos podem ser alterados para fazer com que o negócio evolua de maneira fiel à realidade. 

Blocos de construção

Para manter toda essa dinâmica de construção é necessário não só uma boa comunicação entre o time, como também a adoção dos blocos de construção da Domain Model Patterns, que tem como foco o desenvolvimento de aplicações a partir de seu domínio. São eles: 

  • Entities — uma entidade é um objeto potencialmente mutável. As entidades têm vida própria no modelo de domínio, o que permite obter um histórico de transição. 
  • Value Objects — são entidades imutáveis, um exemplo é o endereço de uma Estação.
  • Aggregate Objects — são compostos por uma entidade ou um conjunto de entidades e Value Objects que compartilham um mesmo contexto. Por exemplo, o pagamento e uma transação realizada.
  • Repositories — fazem a comunicação com o banco de dados e garantem a persistência dos dados.
  • Domain Services — são os serviços de domínio que implementam as lógicas de negócios estabelecidas pela pessoa especialista de domínio
  • Factories — oferecem uma abstração na construção de objetos. São uma alternativa para a construção de objetos.
  • Services — são objetos sem estado que executam operações específicas de domínio que podem envolver outros objetos de domínio. 
  • Domain Event — são eventos disparados quando acontece alguma alteração ao domínio. Isso ocorre para que outras partes tenham conhecimento da alteração que aconteceu.

Atenção! Todos esses conceitos são essenciais para definição do DDD mas existem princípios relacionados a eles que, quando presentes, não necessariamente significam que sua aplicação utiliza DDD. 

São princípios de arquiteturas e Design Patterns independentes do DDD mas que podem auxiliar o desenvolvimento com DDD: 

  • Arquitetura de camadas que isola subdomínios da aplicação em camadas
  • Uso de aggregates para monitorar objetos
  • Isolar responsabilidades a partir de representações bem definidas de modelos (entidades, objetos, módulos, factories, repositórios, etc)

Como montar um modelo efetivo?

Para construir um modelo efetivo, é importante combinar os seguintes fatores: 

  • A implementação deve refletir o modelo real de acordo com a necessidade de cada contexto. 
  • Construção de um modelo evolutivo, ou seja, que fica mais profundo e rico em conhecimento à medida que são acrescentadas alterações e novas regras ao domínio. 
  • Refinar o modelo adicionando e retirando conceitos à medida que necessário, com as mudanças acrescentadas ao domínio. 
  • Estabelecer uma linguagem baseada no modelo entre as pessoas especialistas de domínio e pessoas desenvolvedoras, que seja entendida por ambos. A linguagem é desenvolvida desde a primeira interação mas todos ficam fluentes ao longo do processo. 
  • Muita experimentação e estratégias de interações entre pessoas desenvolvedoras e experts de domínio. Quanto mais o domínio fica evidente e a linguagem é bem estabelecida entre o time, mais fácil é o processo de desenvolvimento como um todo. 

Conheça a arquitetura em camadas do Domain Driven Design

Apesar de não andarem sempre juntas, é interessante vermos como é uma arquitetura em camadas em DDD. Para isso, consideremos uma arquitetura em que temos 5 camadas: 

Arquitetura em camadas

Fonte da Imagem: A autora

  • Apresentação ou User Interface é a camada visual que representa a interface com a pessoa usuária (UI). Exemplos: Aplicação Desktop, Aplicação Web, Aplicação Mobile. Essa camada tem referência direta às camadas da Aplicação, Domínio e Infraestrutura. 
  • Serviços é a camada que faz comunicação com outras aplicações e APIs. Exemplos: Web API, WebSockets. 
  • Aplicação é a camada responsável por se comunicar diretamente com o domínio e nela estão implementados: as classes dos serviços da aplicação, interfaces (ou contratos), Data Transfer Objects (DTO) e AutoMapper. 
  • Domínio é onde o DDD acontece, e nela estão: entidades, interfaces para serviços e repositórios, classes dos serviços do domínio e validações.
  • Infraestrutura é camada que dá suporte a todas as demais camadas e pode ser dividida em: repositórios, mapeamento e persistência de dados.

Quais as vantagens do Domain Driven Design?

  • Iterações (ciclos) de desenvolvimento mais rápidos
  • Alta colaboração entre membros do time 
  • Torna o código reutilizável, manutenível e legível 
  • Facilita a manutenção da complexidade com a definição da complexidade dos limites definidos

Quais as desvantagens do Domain Driven Design? 

Cada situação é única e deve ser estudada caso a caso, mas é importante levar em consideração nos contextos de:  

  • Complexidade técnica — quando as tecnologias envolvidas já são muito complexas e envolve um esforço grande do time para refatorar o que existe com DDD. Ou mesmo quando dividir um domínio exige divisões em serviços que exigem habilidades técnicas distintas, o DDD pode não ser a melhor opção. 
  • Complexidade de domínio — quando existem muitos subdomínios dentro de um outro, e a manutenção de uma funcionalidade simples exige mexer em muitos subdomínios. 

É muita informação, não é? Mas juntando esses conhecimentos e colocando em prática no dia a dia do seu desenvolvimento, você consegue colocar em prática o DDD, pois significará que você conseguiu entender a filosofia do DDD. 

Lembre-se de que o DDD não é apenas separar a arquitetura da sua aplicação em camadas, ele envolve todo o processo de desenvolvimento, incluindo entender o domínio do seu problema em questão, elaborar a linguagem ubíqua, definir os contextos, criar um mapa de contexto e então começar a trabalhar na modelagem dos conceitos. 

E o mais importante é que todo esse processo seja evolutivo e mutável, afinal, a aplicação sofre alterações e seus modelos podem mudar conforme as regras de negócio se atualizam e modificam. Utilize de ferramentas como brainstorming, diagramas e nunca se limite para conversar com seu time sobre o seu entendimento do escopo. Tudo isso conta imensamente na hora de desenvolver um domínio melhor. 

Gostou do nosso texto? Conheça agora a Arquitetura Orientada a Serviços, a SOA!

Deixe um comentário
Você também pode gostar