Total de visualizações de página

Pesquisar este Blog

Translate

quarta-feira, 1 de abril de 2020

DDD - Domain-Driven Design



O DDD (Domain-Driven Design) 



Quando estudei MVC pela primeira vez no livro falava muito sobre DDD (Domain-Driven Design). Pelo que eu entendi na época, a ideia do DDD era simplesmente programar o software com foco no desenvolvimento da camada de domínio.
Depois disso, lendo sobre o processo de análise e projeto em orientação a objetos tive a impressão de que sempre que programamos um software orientado a objetos damos essa ênfase na camada de domínio, começando por ela e usando os requisitos pra montar ela corretamente.
Isso faz parecer que o DDD prega basicamente a mesma coisa que o processo de análise e projeto em orientação a objetos. Dessa forma, o que realmente é o DDD e quando ele se aplica de verdade? Quais as vantagens de se usar DDD em um projeto?


O DDD (Domain-Driven Design) é uma técnica de desenvolvimento divulgada por Eric Evans desde 2003. “Divulgada” porque nem tudo foi criação dele. Ele percebeu que um conjunto de boas práticas de desenvolvimento, trabalho em equipe e estratégias de negócio podem contribuir para que um projeto complexo seja bem sucedido.
O livro de Evans é um grande catálogo de Padrões, baseados em experiências do autor ao longo de mais de 20 anos desenvolvendo software utilizando técnicas de Orientação a Objetos. O que seria um Padrão?
Um padrão é uma regra de três partes que expressa a relação entre um contexto (1), um problema (2) e uma solução (3).
DDD pode ser visto por alguns como a volta da orientação a objetos. É verdade que o livro é um chamado às boas práticas de programação que já existem desde a época remota do SmallTalk. Quando se fala em Orientação a Objetos pensa-se logo em classes, heranças, polimorfismo, encapsulamento. Mas a essência da Orientação a Objetos também tem coisas como:
  • Alinhamento do código com o negócio: o contato dos desenvolvedores com os especialistas do domínio é algo essencial quando se faz DDD (o pessoal de métodos ágeis já sabe disso faz tempo);
  • Favorecer reutilização: os blocos de construção, que veremos adiante, facilitam aproveitar um mesmo conceito de domínio ou um mesmo código em vários lugares;
  • Mínimo de acoplamento: Com um modelo bem feito, organizado, as várias partes de um sistema interagem sem que haja muita dependência entre módulos ou classes de objetos de conceitos distintos;
  • Independência da Tecnologia: DDD não foca em tecnologia, mas sim em entender as regras de negócio e como elas devem estar refletidas no código e no modelo de domínio. Não que a tecnologia usada não seja importante, mas essa não é uma preocupação de DDD.
Eric Evans dividiu o livro em quatro partes, que apresentaremos a seguir.

1)  Colocando o modelo de domínio para funcionar:  
Para ter um software que atenda perfeitamente a um determinado domínio, é necessário que se estabeleça, em primeiro lugar, uma linguagem comum, com termos bem definidos, que fazem parte do domínio do negócio e que são usados por todas as pessoas que fazem parte do processo de desenvolvimento de software. Nessa linguagem estão termos que fazem parte das conversas diárias entre especialistas de negócio e times de desenvolvimento. Todos devem usar os mesmos termos tanto na linguagem falada quanto no código.

2) Blocos de construção do Model Driven Design (MDD)
Uma vez que decidimos criar um modelo usando MDD, precisamos, inicialmente, isolar o modelo de domínio das demais partes que compõem o sistema. Essa separação pode ser feita utilizando-se uma arquitetura em camadas, que dividirá uma aplicação em quatro partes:
Interface de Usuário – parte responsável pela exibição de informações do sistema ao usuário e também por interpretar comandos do usuário;
Aplicação – essa camada não possui lógica de negócio. Ela é apenas uma camada fina, responsável por conectar a Interface de Usuário às camadas inferiores;

Domínio – representa os conceitos, regras e lógicas de negócio. Todo o foco de DDD está nessa camada. Mas 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.

Infra-estrutura – fornece recursos técnicos que darão suporte às camadas superiores. São normalmente as partes de um sistema responsáveis por persistência de dados, conexões com bancos de dados, envio de mensagens por redes, gravação e leitura de discos, etc.
Camada de Domínio - Para modelar a camada de domínio, utilizamos alguns Padrões propostos em DDD. Esses padrões são chamados de blocos de construção e serão utilizados para representar nosso modelo abstrato. Esses blocos podem ser:
Entidades – classes de objetos que necessitam de uma identidade. Normalmente são elementos do domínio que possuem ciclo de vida dentro de nossa aplicação: um Cliente, por exemplo, se cadastra no sistema, faz compras, se torna inativo, é excluído, etc.;
Objetos de Valores – objetos que só carregam valores, mas que não possuem distinção de identidade. Bons exemplos de objetos de valores seriam: strings, números ou cores. As instâncias de Objetos de Valores são imutáveis, isto é, uma vez criados, seus atributos internos não poderão mais ser modificados. Em Java, temos, por exemplo, a classe BigDecimal, muito utilizada para fazer cálculos com valores grandes.
Agregados – compostos de Entidades ou Objetos de Valores que são encapsulados numa única classe. O Agregado serve para manter a integridade do modelo. Elegemos uma classe para servir de raiz do Agregado. Quando algum cliente quiser manipular dados de uma das classes que compõem o Agregado, essa manipulação só poderá ser feita através da raiz;
Fábricas – classes responsáveis pelo processo de criação dos Agregados ou dos Objetos de Valores. Algumas vezes, Agregados são relativamente complexos e não queremos manter a lógica de criação desses Agregados nas classes que o compõem. Extraímos então as regras de criação para uma classe externa:
Fábrica de Serviços – classes que contém lógica de negócio, mas que não pertence a nenhuma Entidade ou Objetos de Valores. É importante ressaltar que Serviços não guardam estado, ou seja, toda chamada a um mesmo serviço, dada uma mesma pré-condição, deve retornar sempre o mesmo resultado;
Fábrica de Repositórios – classes responsáveis por administrar o ciclo de vida dos outros objetos, normalmente Entidades, Objetos de Valor e Agregados. Os repositórios são classes que centralizam operações de criação, alteração e remoção de objetos. Em linguagens como Java e .NET, repositórios são comumente implementados usando-se frameworks como Hibernate ou Nhibernate. Já em RubyOnRails, o ActiveRecord faz o papel de repositório;
Fábrica de Módulos – abstrações que têm por objetivos agrupar classes por um determinado conceito do domínio. A maioria das linguagens de programação oferecem suporte a módulos (pacotes em Java, namespaces em .NET ou módulos em Ruby). Um anti-padrão comum é a criação de módulos que agrupam as classes segundo conceitos de infra-estrutura. Um exemplo seria, ao se trabalhar em Java, criar um pacote que conterá todas as Actions do sistema. Ao usar DDD devemos agrupar classes se esse agrupamento faz sentido do ponto de vista do domínio, ou seja, do negócio. Se tivermos, por exemplo, várias classes que compõem diversas informações de um objeto num sistema, podemos criar um módulo chamado nome-objeto e colocar as classes do objeto num mesmo pacote.
3) Refatorando para compreender profundamente o modelo

Depois de elaborar um modelo de dados que reflete o seu domínio, usando os blocos de construção do MDD, o processo de aperfeiçoamento do modelo continua. O modelo deve ser refatorado e melhorado na medida em que se obtém maior compreensão de conceitos importantes do domínio. Muitas vezes alguns conceitos do domínio estão implícitos no código. O trabalho do desenvolvedor é tentar identificar esses conceitos implícitos e torná-los explícitos. Alguns padrões podem ajudar a compreender mais profundamente o modelo:
Interface de Intenção Revelada – usar nomes em métodos ou classes que dizem exatamente “o que” essas classes ou métodos fazem, mas não “como” elas fazem. Dizer “como” no nome do método quebra o encapsulamento, uma vez que quem chama o código saberá detalhes de implementação;

Funções sem Efeitos-Colaterais – tentar deixar o código com o maior número possível de métodos que não alterem o estado dos objetos, concentrando esse tipo de operação (alteração de estado) em Comandos;

Asserções – para os Comandos que alteram estados, criar testes de unidade que rodem automaticamente, ou colocar asserções no código que validem, após a chamada dos comandos, as alterações de estado esperadas.

4) Projeto estratégico:
As técnicas de criação e refinamento do modelo (como o uso da Linguagem Simples e MDD) são importantes para começarmos a entender como desenvolver um sistema dirigido pelas regras de negócio do domínio, ou seja, como aplicar DDD. 
Mas a parte mais importante e difícil de Domain Driven Design é quando começamos a lidar com sistemas complexos. Como deve ser a interação entre sistemas que interagem entre si? Como dividir nosso trabalho, de maneira que foquemos nossos esforços naquilo que tem maior valor para o negócio? Como fazer a comunicação entre as equipes que desenvolvem esses sistemas?
Temos alguns padrões que nos ajudam a dividir nosso software em várias partes, que chamamos de contextos. Cada Contexto Delimitado deve estar bem claro para todos que estão envolvidos no processo de desenvolvimento. A fronteira entre contextos deve ser clara para todos, ou seja, todo mundo deve saber a qual contexto um determinado pedaço de código pertence.
Os padrões que nos ajudarão a estabelecer qual é a relação existente entre os vários times são:
Mapa de Contextos – uma forma pragmática de documentar claramente os vários Contextos Delimitados que fazem parte de um sistema complexo. No mapa de contextos devemos ressaltar os vários componentes do software e como as equipes que cuidam desse sistema interagem. Além disso, criaremos um mapa de tradução que servirá para facilitar a comunicação. Muitas vezes, existem termos usados para um mesmo conceito em vários contextos.

Todas essas coisas são bem exemplificadas e mostradas na forma de vários padrões em DDD. Mas o livro também mostra muitos padrões que não dizem respeito a código ou modelagem. Aparecem coisas que estão mais ligadas a processos (como Integração Contínua) ou a formas de relacionamento entre times que fazem parte do desenvolvimento de um sistema complexo.  
Conhecido pelo seu livro “Domain-Driven Design – Atacando as Complexidades no Coração do Software”, Evans apresenta uma mudança de paradigma tão grande sobre a forma de entender e solucionar problemas complexos, que inspirou diversos outros ótimos livros sobre o assunto.
O modelo padrão de análise e desenvolvimento de software no qual os analistas de negócio, em conjunto com os especialistas de negócio e/ou usuários-chave, farão um levantamento funcional, e elaborarão um extenso documento de especificação funcional, em boa parte dos dos casos esse modelo não irá funcionar. Entre as razões possíveis, podemos citar:
  • A visão do analista de negócios pode não ser técnica o suficiente para entender os riscos, prazos e impactos da solução;
  • O entendimento de um negócio é algo crescente. Dificilmente a primeira versão de uma especificação funcional é a que soluciona adequadamente o problema;
  • O arquiteto, ou responsável técnico, vai desenhar a solução de acordo com a especificação, que pode mudar ao longo do projeto. Ou seja, a arquitetura proposta no início pode não ser a mais adequada no final;
  • O arquiteto ou responsável técnico, se não tiver um contato próximo ao time de desenvolvimento, pode tomar decisões arquiteturais ou de implementação não compatíveis com o time, seja por competências técnicas ou mesmo por estilo de desenvolvimento;
  • Se o arquiteto tem uma visão limitada sobre o problema a solucionar, os desenvolvedores têm em dobro: além da especificação funcional que tende a ficar defasada, estão trabalhando numa arquitetura imposta que não necessariamente soluciona o problema de negócio. Pode resolver problemas que não existem, como a troca de um banco de dados que pode nunca acontecer, e não ser flexível o bastante para o crescimento da aplicação, por exemplo;
  • Os desenvolvedores vão dar o seu melhor para atender o prazo e os requisitos dentro da arquitetura imposta. Porém quando o projeto for disponibilizado aos usuários, talvez meses depois da análise de negócios, os usuários tenham entendido que não era bem isso que eles queriam.


As mudanças serão necessárias para atender as necessidades atuais dos usuários, e não as de meses atrás. Mas os desenvolvedores podem encontrar dificuldades em implementar as mudanças dentro de um padrão imposto. Isso gera complexidade técnica acidental. O código muitas vezes fica mais complexo do que deveria porque precisa seguir certos padrões definidos no início. À medida que o sistema vai crescendo, a complexidade técnica acidental fica maior do que a própria complexidade do negócio.
O domínio do desenvolvimento do código reflete no domínio da mesma linguagem dos especialistas de negócio e usuários. Termos estritamente técnicos são substituídos por termos que o usuário compreenda. Talvez alguns diagramas possam servir de apoio, mas ao invés de documentos extensos e detalhados, temos um código rico, claro e coeso.
A equipe de desenvolvimento de software como um todo se torna responsável pela arquitetura do projeto. O papel do arquiteto de software pode até continuar a existir, mas numa posição muito mais colaborativa e próxima do dia a dia de desenvolvimento.
A implementação da solução é emergente. Começa simples, e cresce junto com o entendimento do domínio, e não em etapas separadas. Pode ser que em algum momento, perceba-se que a arquitetura não atenda mais. Um conceito chave que impacta na clareza do domínio (código) pode ser percebido, gerando a necessidade de refatoração parcial. E tudo bem se isto acontecer.
Não se investe tempo em padrões e abstrações que não são necessárias. A energia da equipe, do técnico ou do usuário, não é direcionada para um único objetivo: solucionar o problema de domínio, de uma forma em que o código reflita o domínio do negócio.
Em resumo, mesmo o DDD não sendo um padrão de arquitetura, ele afeta como as decisões arquiteturais são tomadas, e o próprio papel do arquiteto na equipe de desenvolvimento do software.
O DDD é voltado para domínios complexos, e depende da quebra de barreiras de comunicação entre especialistas de negócio e especialistas técnicos, além do engajamento do time técnico em programar de forma que o código reflita o domínio. Se uma dessas variáveis for negativa, provavelmente o DDD não serve para o cenário que você está lidando.
Já está claro que o DDD não é uma arquitetura, nem uma bala de prata que resolverá qualquer problema que vier. Mas caso seu time identifique que o domínio em questão é complexo, e esteja disposto programá-lo de forma que a representação do domínio seja clara até para o especialistas de negócio, e perceba que o cliente ou empresa está interessado em colaborar constantemente com o entendimento do domínio e validação da solução, talvez o DDD seja uma boa abordagem de desenvolvimento.
Para aplicar o DDD como modelo de aplicação, deverá ser levado em consideração:
A cultura da empresa: uma empresa que está acostumada com ITIL ou semelhante, com papéis bem definidos e times segregados, terá dificuldades em romper essas barreiras para um modelo colaborativo. Pode ser que, dentro do possível, as coisas estejam indo bem dessa forma, então não há a necessidade de mudar. Mas caso o modelo atual de trabalho esteja impactando as entregas, gerando desgastes, documentação defasada e código de baixa qualidade, entre outros efeitos, talvez os gestores sintam a necessidade de mudança. Se sim, pode ser válido conversar sobre DDD, o que não garante que os gestores se sintam confortáveis com as mudanças propostas. Em outras palavras, as pessoas envolvidas precisam querer e acreditar nessa mudança, a ponto de se comunicarem e colaborarem diretamente com o desenvolvimento do software, e não apenas com a especificação e prazos;
    O engajamento dos desenvolvedores: Para que o código reflita o domínio, uma série de práticas de desenvolvimento são recomendadas. Existem muitas formas de resolver o mesmo problema, e muitas formas são aceitas, contanto que ao analisar a aplicação, seja possível entender qual o domínio principal, suas regras e peculiaridades, quais os domínios auxiliares, como eles se relacionam, etc. Não basta apenas metade dos desenvolvedores estarem engajados em codificar refletindo o domínio, todos precisam assumir essa responsabilidade.



    O que não é DDD? O DDD não é uma tecnologia ou uma metodologia. Pode ser utilizado independente da linguagem. Não importa se é C# ou Java, se é MVC ou Windows Forms. Não é arquitetura em camadas e não impõe processos rígidos para a equipe de desenvolvimento de software.





    BDD - Behavior Driven Development



    O BDD (Behavior Driven Development) 


    É uma técnica de desenvolvimento Ágil de software, que encoraja colaboração entre desenvolvedores, setores de qualidade e pessoas não-técnicas ou de negócios num projeto de software, relaciona-se com o conceito de verificação e validação. 

    BDD é uma técnica de desenvolvimento de software ágil que surge através de uma crítica de Dan North ao Test Driven Development(Desenvolvimento orientado a testes), onde ele visava otimizar o conceito de ‘verificação e validação’ já aplicado, e tornar mais eficiente a construção de cenários a serem testados e/ou desenvolvidos.

    Para Kent Beck, criador do TDD, os testes devem ser escritos antes do código do software, assim irão falhar. Logo após, os desenvolvedores irão se basear nestes cenários falhos, irão implementar a aplicação de maneira a fazer os testes passar, e refatorar seu código até que fique mais limpo. De maneira cíclica. O que foi chamado de Red-Green- Refactor.
    O BDD é uma técnica que foca no comportamento do software, com essa metodologia podemos criar testes e integrar as regras de negocio com a programação. A definição do comportamento geralmente é realizada por user stories onde os cenários devem ser escritos de uma forma curta com uma descrição simples da feature.

    Ao contrário do que alguns podem pensar, esse conceito não se aplica apenas a profissionais de qualidade, mas para sua correta implantação todos os membros do time precisam entendê-lo, e estar comprometidos com um pensamento que gira em torno das necessidades de um usuário real.
    O BDD deveria ser utilizado para verificar as partes mais importantes do aplicativo utilizando testes end-to-end, para os testes de integração, que a escrita devem ser simples, mas de modo que faça sentido para o negócio. 
    O BDD deverá ser aplicado em testes de unidade desde que haja beneficio para o negócio, quando precisamos validar o comportamento de uma aplicação.
    O BDD não é necessário em testes unitários que validem a implementação real, pois dessa forma seria um obstáculo a sua reformulação, uma vez que estes testes não passam por validação de um Stakeholder por serem escritos em códigos e a maioria dos Stakeholders não validam código.
    Em todo e qualquer projeto deve sempre haver uma cooperação muito grande com o negócio, além disso a implementação do BDD é documentar o sistema de modo que qualquer pessoa do time possa e consiga ler o teste.
    O foco do BDD é a prevenção de falhas de comunicação, onde nesta metodologia as equipes  sofrem frequentemente com um processo de comunicação baseados em exemplos reais, pois assim todas as experiências reais são trazidas e compartilhadas entre todos. A equipe de negócio pode somar seu conhecimento do negócio com a capacidade e domínio técnico das técnicas de desenvolvimento de software na elaboração das estórias.
    O principal ganho deste processo é que os Analistas de Negócio podem expandir mais o seu conhecimento entendendo a técnica aplicada em cada cenário, e os desenvolvedores e os Quality Assurance podem ter uma ideia mais clara das necessidades do negócio. 
    Então o que podemos resumir é que ferramentas de BDD são complementares á essa metodologia ágil, utilizar de uma ferramentas de automação ou escrever os testes em Gherkin são apenas parte do processo.
    E está correto, porém a grande vantagem desta prática não é gerar testes, e sim pensar no design e nas regras negócios antes de escrever qualquer linha de código.
    Assim surge o BDD, como uma prática que levaria o time de desenvolvimento a pensar no comportamento do usuário para entender o que deve ser feito. E atualmente através de  conceitos e ferramentas, ele já pode ser aplicado por todos os membros do time, e não apenas pelos desenvolvedores.
    O BDD apresenta um framework baseado em três princípios:
    • .A área de negócios e o time de desenvolvimento precisam se referir a mesma parte do sistema da mesma forma;
    • Toda parte do sistema precisa ter um valor identificável e verificável para o negócio;
    • Analisar, projetar e planejar tudo de cima a baixo tem retorno decrescente;

    Podemos definir o BDD como a união de várias práticas consideradas ágeis e úteis no desenvolvimento de software, cuja ênfase está nas funcionalidades de alto valor e na redução dos custos de mudança por meio da identificação do que de fato está sendo testado/desenvolvido.


    TDD - Test-Driven Development




    O TDD (Test-driven development)  

    É o chamado "Desenvolvimento de Software Orientado por Testes". 

    O TDD tem se tornado sem dúvidas uma prática recorrente entre bons desenvolvedores. 
    O conceito é bem simples, é o  desenvolvimento de  software baseado em testes que são desenvolvidos antes de escrevermos o código de produção
    Para que o TDD dê certo é necessário trabalhar rigorosamente com um ciclo contínuo de ações sem pular nenhuma fase.
    Para facilitar isso, existe já tem muitos anos os algorítimos e fluxogramas que auxiliam muito a lógica de programação na execução dessa tarefa.

    Por Ana Mercedes Gauna
    Analista de Sistemas Senior