Domain Driven Design - Quando o gavião come a barata?
Enviado em 5 de Setembro de 2008
Publicado por Felipe Rodrigues
Há algum tempo (mais ou menos 4 anos) venho estudando e aplicando Domain Driven Design em diversos projetos. Normalmente meu trabalho nos projetos é planejar e construir a arquitetura dos sistemas ou avaliar e corrigir arquiteturas criadas por outras pessoas. Não precisa nem dizer qual dos dois eu prefiro né?
Para que eu possa expressar melhor o motivo que me levou a especialização em Domain Driven Design preciso voltar ao meu primeiro curso de Orientação a Objetos. Lá estava eu (há 7,5 anos atrás) com experiência em linguagens como C, Pascal, Object Pascal (Delphi), mas sem nenhuma noção do que era um "objeto". Após uma breve explicação dos conceitos, vieram os exemplos de meu professor:
Lê-se: "Gavião é uma Ave que é um Vertebrado que é um Animal" e "Barata é um Inseto que é um Invertebrado que é um Animal".
Quando eu comecei a entender essas relações eu imediatamente comecei a pensar nas diversas interações entre esses objetos. E comecei a pensar em como expressar as situações utilizando esses objetos. Como exemplo, pense na seguinte situação:
"O Gavião normalmente come a Barata."
Uma forma de expressar isso em orientação a objetos seria:
Que resultaria em :
Pronto… código muito simples e de fácil compreensão. Isso não passa de orientação a objetos. O importante é entender a quantidade de práticas envolvidas neste exemplo e que só pude perceber depois que comecei a estudar Domain Driven Design.
O processo
Implementar Domain Driven Design implica modificar a cultura de desenvolvimento de software que hoje está impregnada nas maioria das empresas. Domain Driven Design significa desenhar software de acordo com o domínio (conjunto de informações e situações) relacionado ao problema que o software se propõe a resolver.
Esse domínio deve ser definido já no começo do projeto, pelo menos de forma superficial, para que você saiba o objetivo do software. Depois disso começa o aprofundamento no domínio. É importante lembrar que sua arquitetura e seu ambiente de desenvolvimento deve preparado para evolução, protegido por integração contínua e TDD para garantir a evolução do domain. Práticas de desenvolvimento ágil são muito úteis para isso.
Em algum momento na caminhada iremos começar a desenvolver software e consequentemente trabalhar com o domain, aprofundando o conhecimento da equipe. Existem algumas dicas para obtenção do conhecimento, exploração de conceitos ocultos e implicitos, para garantir que o domain reflita a situação em um nível aceitável.
O fator fundamental é dialogar muito com os domain experts (pessoas que possuem experiência no processo de negócio do qual o domain trata). Sem os domain experts não é possível realizar domain driven design (Alguém ve alguma semelhança com agile?) São eles que vão determinar quais são as informações e situações que o domain deve tratar. Isso exige postura por parte de quem desenvolve, já que a pessoa que desenvolve deve ser a mesma que irá obter o conhecimento.
Voltando ao nosso exemplo, a frase "O Gavião normalmente come a Barata." representa uma explicação ou definição do domain expert e portanto deve fazer parte do domain. Essa situação de negócio pode ser expressada graficamente da seguinte forma:
Esse é um exmplo simples, mas com esse tipo de notação pode-se expressar processos de negócio complexos, o que ajuda muito na visualização do domain. É importante observar que nesta notação bem simples, temos todos os conceitos explicitos. Isso nos dá o gancho para o próximo item que é a criação de uma linguagem comum para o time.
Ubiquitous Language
Um importante conceito do Domain Driven Design é a criação e manutenção de uma linguagem comum, tanto para o cliente quanto para o time de desenvolvimento. A premissa diz que ambos devem expressar o negócio da mesma forma e isso visa melhorar a comunicação e o entendimento entre as partes.
Essa linguagem comum deve estar presente no dia-a-dia da equipe incluindo a obrigação de ser expressada em documentos e no código também. No nosso exemplo o código expressa exatamente o conceito antes comunicado pelo Domain Expert (a frase "O Gavião normalmente come a Barata." ), comunicada pelo diagrama:
Isso é conseguido através de algumas técnicas de Supple Design (um dos mais interessantes conceitos de Domain Driven Design) e é facilitado com a aplicação da técnica de Fluent Interface.
Refactoring
Pensando na situação do exemplo, "O Gavião normalmente come a Barata" nos deixa com muitas dúvidas sobre esse contexto. De onde veio a barata? De onde veio o gavião? O que acontece quando o gavião come a barata? O que o domain expert quer dizer com "normalmente"? Onde está o wally?
Podemos aprofundar nosso conhecimento a partir do momento que o domain expert responder essas perguntas. Mas essas perguntas podem gerar novas perguntas e consequentemente, mais conhecimento a ser expressado. Continuando no exemplo:
Pergunta de desenvolvedor:
- Por que você (o domain expert) diz com "O Gavião NORMALMNETE come a Barata"? O que quer dizer "normalmente"?
Resposta do Domain Expert:
- O Gavião normalmente come a barata, mas tem vezes em que a barata consegue escapar do gavião.
Pergunta de desenvolvedor:
- Então a barata luta para não ser comida?
Resposta do Domain Expert:
- Sim. A barata tenta se esconder na hora em que o gavião começa a sobrevoa-la. Se a barata escapa então o gavião procura outra presa. Se a barata não consegue então o gavião come a barata. Mas isso é tão obvio que eu nem falei antes.
Nesse momento nosso conhecimento sobre o processo de negócio é mais profundo. Isso exige um refactoring em nossa ubiquitous language. Devemos modificar os documentos, a forma de falar, os diagramas e o código. Vejamos como ficaria nesse caso:
Nesse pequeno exemplo pudemos identificar a variação entre um conceito solto do processo e um pequeno detalhe "óbvio" que o domain expert não mencionou porque era obvio. Quantos problemas você já enfrentou porque deixou passar algum "detalhe óbvio"? Agora que temos o processo de negócio refatorado podemos partir para a implementação do código:
Percebam que na hora de implementar o código, vários detalhes aparecem (as ações gaviao.comeu?() e gaviao.caçar()). Por isso é fundamental que o dialogo com os domain experts sejam constantes. O conhecimento evolui e nossa imaginação pode dar direções diferentes para uma situação, por isso validar o conhecimento com o domain expert é muito importante. Além disso podemos melhorar a implementação desse código (técnicamente falando) de várias formas. Talvez o do…while não seja a melhor opção para expressar este caso. Isso deve sempre ser realizado em inspeções de código, trazendo uma visão de fora para verificar a clareza e eficiência do código. Alguém se dispõe a otimizar esse algorítimo?
Conclusão
Praticar Domain Driven Design é algo deve ser feito em equipe, com foco em negócio e nas situações do ponto de vista dos domain experts. O DDD foca em expressar negócio em forma de software para que possamos minimizar complexidade desnecessária e consequentemente custos de produção e manutenção. A orientação a objetos, apesar de um conceito isolado ao DDD, vem para ajudar na implementação de um bom design orientado a domínio. O DDD por outro lado oferece um processo que facilita muito a aplicação de Orientação a Objetos na forma mais pura e por isso eu costumo dizer que Domain Driven Design oferece a nós desenvolvedores um caminho de volta à orientação a objetos. Confiram em breve mais artigos sobre DDD e sua práticas aqui no blog.