Domain-Driven Design, do início ao código
👉 This article is also available in English on my blog
Quando se fala em Domain-Driven Design (DDD), muitos desenvolvedores logo se pensam no estilo arquitetural e nos tactical patterns do DDD.
E é claro que nós somos apaixonados por isso, afinal somos desenvolvedores! ❤️
Porém, para trabalhar com DDD precisamos desenvolver mais alguns skills, como aprender a modelar domínios de forma efetiva, e, para isso, precisamos nos tornar o que o Eric Evans chama de Knowledge Crunchers — processadores de conhecimento — alguém preparado para receber, filtrar e organizar uma avalanche de informação.
Domain-Driven Design é, antes de tudo, comunicação. No DDD modelagem e implementação andam juntas.
Especialistas do domínio (usuários, analistas e outros especialistas da área), juntamente com os desenvolvedores e arquitetos trabalham de mãos dadas com um objetivo em comum: construir software guiado pelo domínio para atender as necessidades do cliente.
Para fazer isso, em primeiro lugar, é necessário que todos usem uma linguagem em comum e que não haja tradução na comunicação entre os membros do time.
O time desenvolve, portanto, uma linguagem ubíqua (geral e universal) que expressa o conhecimento dos especialistas de negócio para o modelo de domínio (para o código).
Ok, eu devo guiar meu projeto pelo domínio, mas o que exatamente é o domínio?
O domínio de um software são as atividades desempenhadas pelo usuário e a área de interesse destes.
O domínio pode ser tão complexo quanto os processos e dados que ele compreende.
E o modelo?
Um modelo é, de acordo com Evans (2004, p. 2) “uma simplificação. É uma interpretação da realidade que abstrai os aspectos relevantes para resolver o problema em questão e ignorar detalhes alheios a isto” (tradução livre).
Com um modelo conseguimos:
- Abstrair a complexidade do negócio através de uma representação simplificada do mesmo — um modelo.
- O modelo serve como algo comum e palpável a todos os membros do time, que, junto com a linguagem ubíqua, permite que todos possam participar ativamente da construção progressiva do mesmo.
- O modelo (desde que feito corretamente) garante que aquilo que está sendo especificado é o que está sendo implementado.
- O modelo é o meio de comunicação usado pelo time. Graças ao vínculo entre o modelo e a implementação, os desenvolvedores podem falar na linguagem do software ao comunicarem-se com os especialistas do domínio (sem ter que traduzir a mensagem).
- O modelo é o conhecimento destilado — é o modo como o time concorda em estruturar o conhecimento extraído do domínio.
EVANS (2004)
O modelo é evolutivo: A cada iteração entre especialistas de domínio e a equipe técnica, o modelo se torna mais profundo e expressivo, mais rico, e os desenvolvedores transferem essa fonte de valor para o software.
Assim, o modelo vai sendo gradualmente enriquecido com o expertise dos especialistas do domínio destilado pelos desenvolvedores, fazendo com que o time ganhe cada vez mais insight sobre o negócio e que esse conhecimento seja transferido para o modelo (para o código) através dos blocos de construção do DDD.
Quando novas regras de negócio são adicionadas e/ou regras existentes são alteradas ou removidas, a implementação é refatorada para refletir essas alterações do modelo no código.
No final, o modelo (que em última instância será o software) vai expressar com riqueza de conhecimento o negócio.
Como explica Evans (2004, p. 23) “DDD coloca um monte de conhecimento no modelo que reflete profundamente o domínio.”
Isso só é possível através da colaboração entre quem conhece o domínio e quem sabe criar software. 🤝
E como o desenvolvimento é iterativo, essa colaboração continua durante todo o andamento do projeto.
Ou seja, o Domain-Driven Design nos leva a construir softwares guiados pelo conhecimento e modelagem do negócio antes de qualquer apelo por tecnologia.
Dito isso, para que possamos implementar o modelo de domínio, obviamente, precisamos programar. 😎
E para isso, o DDD nos oferece os seus design patterns táticos, dentre eles eu destaco:
- Isolamento do domínio com Layered ou Clean Architecture (a.k.a. Ports and Adapters, Hexagonal Architecture).
- Representação do modelo através de Entities, Value Objects, Aggregates e Modules.
- Gerenciamento do ciclo de vida dos objetos do modelo com Aggregates e Repositories.
- Domain Services para abstrair rotinas que não se encaixam dentro do Domain Model.
- Factory Methods para simplificar a criação de instâncias de objetos de domínio complexos.
Demonstrarei na prática cada um deles nos próximos artigos desta série sobre Domain-Driven Design. Mas agora voltemos à teoria, pois é necessário antes ter um bom fundamento se quisermos construir um modelo realmente efetivo.
Os 5 ingredientes de um modelo efetivo:
- Vincular o modelo com a implementação: esse vínculo é feito desde o início, quando o modelo ainda é primitivo e será mantido até o fim. Esse vínculo é profundo, a implementação deve refletir 100% o modelo.
- Cultivar uma linguagem baseada no modelo: no início será necessário que os desenvolvedores e os domain experts entendam cada um os termos do outro, mas depois ambos falarão a mesma linguagem, organizando as sentenças da comunicação numa estrutura consistente com o modelo e sem ambiguidades.
- Desenvolver um modelo rico em conhecimento: objetos têm dados e comportamentos associados. O modelo não deve ser apenas uma estrutura de dados (modelo anêmico), ele deve capturar o conhecimento do domínio para resolver os problemas do domínio.
- Destilar o modelo: o modelo deve ser refinado. Assim como conceitos importantes devem ser adicionados, conceitos que não tem relevância devem ser removidos. A cada iteração o modelo ficará mais rico e terá mais valor.
- Brainstorming e experimentação: a interação direta entre os desenvolvedores e domain experts, através de brainstormings e diagramas feitos na hora, transformam as discussões em laboratórios do modelo, no qual diversas variações de experimentos podem ser exercitadas e o resultado pode ser usado se mostrar valor ou descartado caso contrário.
EVANS (2004)
O modelo deve ser rico! 💰
- O modelo deve ser rico em conhecimento.️️️ ✔️
- Um modelo rico é composto de código expressivo, de regras de negócio e processos bem definidos. ✔️
- Ele expressa o conhecimento nele contido e resolve problemas do domínio.✔️
- É o contrário de um modelo anêmico onde as classes são apenas esquemas de dados sem comportamento. 😷
Conclusão
Da próxima vez que você for inferir se um projeto está usando Domain-Driven Design, antes de olhar para a Solution Explorer da IDE em busca do estilo arquitetural e dos patterns, veja primeiro se a equipe está usando um método ágil e fazendo knowledge crunching.
Eu já vi muitos projetos autodenominados “com DDD”, que apesar de implementarem alguns dos tactical patterns do DDD, o modelo estava bem longe de refletir o domínio.
Referências
Evans, Eric. Domain-Driven Design: Tackling Complexity in the Heart of Software. 2004.
Veja a continuação dessa série:
Maicon Heck
.NET Senior Developer | Software Craftsman | Domain-Driven Design practitioner