Domain Driven Design é uma abordagem para construção de softwares complexos e ambiciosos onde o foco primário da implementação é o negócio (domínio).
Apresentarei como remover as distrações de infraestrutura aplicando padrões de modelagem de domínio
como Aggregate, Entity, Value Object e Repository. E um diálogo sobre como a conexão entre pessoas
desenvolvedoras e especialistas de domínio podem trazer resultados positivos na modelagem e arquitetura
de uma aplicação.
3. O que é DDD?
Domain-Driven Design (DDD) é uma abordagem de desenvolvimento para
softwares de necessidades complexas que conecta profundamente a
implementação a um modelo em evolução dos conceitos centrais de negócio.
Original: Domain-driven design (DDD) is an approach to developing software for complex needs by
deeply connecting the implementation to an evolving model of the core business concepts.
https://dddcommunity.org/learning-ddd/what_is_ddd/
4. Como?
Colocando o foco nas regras de negócio e só depois pensando na
infraestrutura necessária.
5. Exercício - Lista de Desejo
A especialista de domínio chega para a equipe de desenvolvimento e solicita
uma nova funcionalidade para a plataforma de e-commerce.
Desenvolvedora A
Que legal! Vai ser daquele jeito que havíamos conversado?
Cada usuário vai poder criar uma lista de desejos dando um
nome pra lista, certo?
Especialista de domínio
Oi, gente!
Para essa sprint, trabalharemos na funcionalidade de Lista de
Desejos.
6. Exercício - Lista de Desejo
Especialista de domínio
Isso mesmo! Não esquece de pôr um limite de no máximo 30
caracteres no nome e mínimo de 3. Senão vai ficar estranho no
App.
Desenvolvedora A
Então o nome da lista é único por cliente, né?
Especialista de domínio
Isso, a gente vai identificar a Lista de desejo pelo nome da lista
e pelo cliente. O nome da lista é o cliente que vai definir.
7. Exercício - Lista de Desejo
A equipe de desenvolvimento começa a discutir como vão começar a nova
funcionalidade:
Desenvolvedor B
Vai ser moleza! A gente vai precisar de um endpoint, que vai
receber um POST para criar o registro no banco de dados. O
banco de dados vai precisar de uma unique key para o nome
da lista com o id do usuário.
8. Exercício - Lista de Desejo
A equipe de desenvolvimento começa a discutir como vão começar a nova
funcionalidade:
Desenvolvedora A
Hmm… Eu estava lendo sobre DDD e gostaria de saber se vocês
concordam em fazer um exercício onde foquemos primeiro na
regra de negócio e depois nos detalhes de infraestrutura.
Desenvolvedor B
Vai ser moleza! A gente vai precisar de um endpoint, que vai
receber um POST para criar o registro no banco de dados. O
banco de dados vai precisar de uma unique key para o nome
da lista com o id do usuário.
9. Desenvolvedor B
Mas o que acontece se o nome da Lista de desejos mudar?
Exercício - Lista de Desejo
ListaDeDesejos
--------------------
id: ListaDeDesejosID
nome: String
ListaDeDesejosID
----------------------
usuarioId: UsuarioID
nome: String
Desenvolvedora A
A ListaDeDesejos é uma entidade a identidade dela é baseada
na identidade do usuário e no nome da lista de desejos.
10. Exercício - Lista de Desejo
Especialista de domínio
Legal! Esse tipo de coisa sempre ajuda nossos canais de
televendas e também nas compras nas nossas lojas físicas.
Ele pode sempre começar em 1 (um) para cada usuário? Isso
facilita na hora dos usuários decorarem o código.
Desenvolvedora A
Então não podemos usar o nome da Lista de Desejos como
identificador. Vamos precisar de um número que vai ser gerado
no cadastro da lista de desejo.
Especialista de domínio
Isso é um caso real! O usuário pode mudar o nome da lista de
desejos.
11. Desenvolvedora A
Sim! A gente não pode esquecer da limitação de tamanho do
nome também!
Desenvolvedor B
Que legal! Agora falta o principal! Os produtos 🤣
Exercício - Lista de Desejo
ListaDeDesejos
--------------------
id: ListaDeDesejosID
nome: String
ListaDeDesejosID
----------------------
usuarioId: UsuarioID
numero: Long
Desenvolvedora A
Legal! Temos a identidade da nossa lista de desejos!
12. Exercício - Lista de Desejo
ListaDeDesejos
-------------------------
id: ListaDeDesejosID
nome: NomeDaLista
desejos: Lista<Produto>
-------------------------
adicionarProduto(produto)
removerProduto(produto)
renomearLista(nome)
ListaDeDesejosID
----------------------
usuarioId: UsuarioID
numero: Long
Produto
--------------------
produtoId: ProdutoID
Desenvolvedora A
Agora nosso modelo parece completo. Vamos validar com a
Especialista em domínio?
13. Exercício - Lista de Desejo
Desenvolvedora A
Legal! Pode deixar!
Especialista de domínio
Massa! É isso aí! Só não se esqueçam que a lista de produtos não
pode ter produtos repetidos, viu? Pode ignorar se houver
duplicidade
14. Modelagem
ListaDeDesejos
-----------------------------
id: ListaDeDesejosID
nome: NomeDaLista
desejos: Lista<Produto>
-----------------------------
adicionarProduto(produto)
removerProduto(produto)
renomearLista(nome)
ListaDeDesejosID
----------------------
usuarioId: UsuarioID
numero: Long
Produto
--------------------
produtoId: ProdutoID
aggregate
value object
entity id
AGGREGATE: Um cluster/agregador de objetos
que só fazem sentido serem modificado como
uma unidade.
VALUE OBJECT: Um objeto imutável que tem
como identidade todos os seus atributos. Ex:
Dinheiro e Endereço.
ENTITY: Um objeto que pode sofrer mudanças,
naturalmente é persistido e tem uma
identidade única.
15. Modelagem
VALUE OBJECT
new Dinheiro(10) == new Dinheiro(10)
new Dinheiro(20) != new Dinheiro(10)
ENTITY
new Pessoa(“0.0.0.0”, “Nike”) == new Pessoa(“0.0.0.0”, “Nike”)
new Pessoa(“0.0.0.0”, “Nike”) == new Pessoa(“0.0.0.0”, “Mike”)
16. Hora do Código!
A equipe de desenvolvimento trabalhou em representar o modelo que
desenharam em formato de código.
Vamos ver como ficou?
https://github.com/carlosmaniero/ddd-manipulando-mais-que-bytes
17. Hora do Código!
Nada de mais aqui!
Só a definição da classe com
os atributos e um construtor
com base no ID e no Nome da
lista de desejos.
18. Hora do Código!
Um ponto legal aqui é que
estamos criando as operações
com os nomes que o negócio
usa. Em Java, naturalmente o
método renomearLista,
facilmente seria chamado de
setNome.
Há um mecanismo seguro que
garante que a classe
ListaDeDesejos vai retornar
uma cópia da lista de
produtos. Garantindo que
ninguém externamente, altere
a lista de produtos
ex:
lista.produtos().add(produto).
Não altera o estado da lista de
desejos.
19. Hora do Código!
O .equals() é baseado no ID
da da LivroDeVisitas. Fazendo
com que sua igualdade seja
baseada na sua identidade.
20. Hora do Código!
O NomeDaLista tem uma
Fábrica estática que valida o
nome para garantir que só
nomes válidos sejam criados.
21. Repositórios
A criação da Lista de Desejos depende de duas regras de criação:
- Não pode permitir duas listas com o mesmo nome
- O número da Lista de Desejo deve ser incremental por usuário
- Para simplificar, vamos assumir que nunca é possível remover uma lista de desejo, então
podemos utilizar o total de lista de desejos + 1
Repositórios têm um papel essencial na implementação do DDD. São os
repositórios responsáveis em responder esse tipo de pergunta.
23. Fábricas
A criação da Lista de Desejos com todas essas validações não é algo trivial.
Fábricas são nossas amigas nesses momentos. Elas asseguram que só haverá
uma forma de criar a Lista de Desejos e tiram essa complexidade de dentor do
modelo da Lista de Desejos.
24. Hora do Código!
Vamos ver agora como ficou a Fabrica e o repositório da Lista de Desejos.
https://github.com/carlosmaniero/ddd-manipulando-mais-que-bytes
26. Falando a linguagem do negócio
Para a implantação do DDD é necessário que negócio e equipe de
desenvolvimento falem a mesma lingua. O modelo que a gente desenhou, foi
todo baseado em palavras-chave que a Especialista de Domínio falou.
27. Mas isso é só um detalhe técnico...
Novamente o sucesso do DDD está na comunicação. Nunca assuma que algo é
só um detalhe técnico.
Assim que os desenvolvedores falaram que teriam que usar um ID para identificar
a Lista de Desejos a Especialista de domínio encontrou valor e definiu regras
para esse ID. Já pensou se a equipe estivesse usando algum banco que criasse
como ID um UUID os usuários jamais poderiam tomar vantagem disso!
28. Não falamos em nenhum momento de
infraestrutura
Para essa aplicação ser uma aplicação real, ela precisaria de um banco de
dados, uma forma de comunicação com aplicações de terceiros como HTTP, etc.
O mais legal de desenvolver orientado a domínio. É que nada disso importa!
Agora que você tem seu modelo, basta conectar tudo isso com o seu Framework!
Aprendizados: Não brigue de mais com o seu framework! Ele é seu amigo.