<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Thiago Henrique</title>
    <description>The latest articles on DEV Community by Thiago Henrique (@thiagosilva95).</description>
    <link>https://dev.to/thiagosilva95</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F644364%2F5ee08675-41ca-4295-9cc4-488b76417dbc.jpg</url>
      <title>DEV Community: Thiago Henrique</title>
      <link>https://dev.to/thiagosilva95</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thiagosilva95"/>
    <language>en</language>
    <item>
      <title>SAGA Pattern para microservices</title>
      <dc:creator>Thiago Henrique</dc:creator>
      <pubDate>Thu, 17 Jun 2021 04:24:36 +0000</pubDate>
      <link>https://dev.to/thiagosilva95/saga-pattern-para-microservices-2pb6</link>
      <guid>https://dev.to/thiagosilva95/saga-pattern-para-microservices-2pb6</guid>
      <description>&lt;p&gt;Hoje em dia sabemos que a utilização de microsserviços está bastante difundida em vários projetos e em várias empresas. E entre vários desafios que esse modelo arquitetural carrega, está o de lidar com consistência de dados em operações que envolvem mais de um serviço e possivelmente vários bancos de dados.&lt;/p&gt;

&lt;p&gt;E dentro desse cenário de sistemas distribuídos, e com a necessidade de lidar com contexto transacional, temos um padrão que cai como uma luva, o &lt;strong&gt;SAGA Pattern&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Apesar de muitos já terem ouvido falar, talvez nem todos tenham compreendido. Porém, podemos afirmar que uma vez entendido, ao tentar implementá-lo podem surgir questionamentos e desafios.&lt;/p&gt;

&lt;p&gt;Existe bastante material na internet sobre esse pattern, porém meu objetivo aqui é tentar contribuir de alguma forma para o seu bom entendimento.&lt;/p&gt;

&lt;h3&gt;
  
  
  Origem e conceito
&lt;/h3&gt;

&lt;p&gt;Bom, a ideia original do SAGA surgiu na verdade em 1987 através de um paper de dois cientistas da computação da universidade de Princeton. Em sua concepção o objetivo era suportar transações ou operações de longa duração, o que eles deram o nome de LLTs (Long Lived Transactions).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl2h4oxzhsbwcmmpqfan1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl2h4oxzhsbwcmmpqfan1.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mais recentemente, as sagas foram aplicadas para ajudar a resolver problemas de consistência em sistemas distribuídos modernos - conforme documentado em um artigo de sagas distribuídas de 2015.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvi5fscylfravw8sxdpga.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvi5fscylfravw8sxdpga.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Desde então o SAGA evoluiu e passou a se encaixar bem em situações onde você precisa lidar com operações que envolvam diversos microsserviços que precisam apresentar alguma consistência nos dados.&lt;/p&gt;

&lt;p&gt;Se no modelo monolítico você faz uma transação no banco e grava tudo, no modelo de microsserviços essa transação será "virtualizada" uma vez que a operação em si é composta por transações que acontecem em cada serviço participante.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffnv4vze5c3okkqjijqs7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffnv4vze5c3okkqjijqs7.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A ideia é simples, é fazer com que cada microsserviço execute uma operação alterando sua base de dados . No final do processo todos estarão com suas bases de dados atualizadas e consistentes.&lt;/p&gt;

&lt;p&gt;Se ocorrer alguma falha na execução do processo em algum serviço, esse processo faz com que &lt;strong&gt;ações compensatórias&lt;/strong&gt; sejam executadas nos serviços que operaram antes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiqz6xeld2qhfwi99cpgc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiqz6xeld2qhfwi99cpgc.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vale ressaltar aqui que não importa para o SAGA falhas condicionais ou parciais. &lt;/p&gt;

&lt;p&gt;Deixa eu me explicar. Se em um sistema de e-commerce a falha acontece no serviço de payment devido o cartão do buyer estar inválido ou algo do tipo, o sistema ainda sim poderia tentar concluir a transação utilizando outros cartões que o cliente possa ter cadastrado na plataforma ou outras formas de pagamento disponíveis (aqui não entro no mérito se essa funcionalidade faz sentido ou não). &lt;/p&gt;

&lt;p&gt;Só após esgotadas todas as tentativas do sistema concluir a transação ele deve “avisar” aos demais para dar início às ações compensatórias. O padrão SAGA se interessa por sucesso definitivo ou falha definitiva.&lt;/p&gt;

&lt;p&gt;SAGA também pode ser mais um nome dado para consistência eventual. Mas de certa forma ele expõe a ferida, no sentido que temos que pensar em um tratamento caso as operações do seu sistema não tenham sucesso, que seria as ações compensatórias.&lt;/p&gt;

&lt;p&gt;Então se pudesse resumir o padrão em uma frase e de forma bem informal, caberia dizer que é basicamente um conceito de pilha, porém com uma funcionalidade de “Desfazer (CTRL+Z)”.&lt;/p&gt;

&lt;p&gt;E, obviamente, sempre que se fala em SAGA precisamos falar sobre as duas estratégias que existem para sua implementação (Orquestração e coreografia).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Orquestração&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhodmphx7m723qzq0ea5s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhodmphx7m723qzq0ea5s.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No modelo orquestrado existe um componente central que se encarrega de acionar todos os serviços que fazem parte de uma SAGA. Caso sucesso, o agente ativa o próximo serviço. Caso falhe, esse agente orquestra as ações compensatórias. Esse componente é também conhecido como &lt;strong&gt;Saga Execution Coordinator (SEC)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Nesse modelo se tira dos microsserviços o conhecimento sobre o fluxo. Existe um outro componente que conhece o fluxo e vai coordenar a execução da operação de modo que os microsserviços vão se concentrar em fazer suas operações.&lt;/p&gt;

&lt;p&gt;Aqui não devemos nos prender em uma estratégia de comunicação sempre síncrona. É bastante comum o uso de um Message Broker dando suporte ao fluxo possibilitando que os serviços sejam  acionados ao receberem uma mensagem de um tópico que lhe interessa e poste de volta um novo evento como resultado da sua execução. Esse evento disparado permite que o orquestrador acione o próximo processo a ser executado.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyjkf9qen486fb7yg4k9r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyjkf9qen486fb7yg4k9r.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vale ressaltar também que o agente orquestrador pode ser usado como uma espécie de máquina de estado das diversas SAGAS que passam por ele.&lt;/p&gt;

&lt;p&gt;Tá, mas nem tudo são flores! Algumas questões podem vir à nossa mente sobre os desafios que essa estratégia trás. Alguns deles seriam:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;E se um step da saga demorar demais para ser executado?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Pode acontecer o que o seu negócio precisar que aconteça! Seu sistema pode trabalhar com um tempo de timeout que cancela a operação e a partir daí pode-se executar retentativas ou consultar o serviço chamado para saber se a operação foi concluída antes de realizar algum tipo de reprocessamento ou início de ações compensatórias. Aqui quem manda é o negócio!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Para a abordagem orquestrada, ao usarmos ela, não estaríamos criando um single point of failure?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Acredito que é preciso pensar na criticidade disso e principalmente ter maneiras de saber que sua SAGA foi interrompida. Por isso, considero que é ideal utilizar um serviço de mensageria para ter o registro da mensagem para ser trabalhada. Talvez não tentar fazer com que o erro seja impossível mas que quando aconteça, que ele seja visível.&lt;/p&gt;

&lt;p&gt;Além disso, pode ser legal utilizar a "máquina de estado" do orquestrador para sabermos em que estado ele estava quando houve a falha.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Será que sempre conseguiríamos fazer o orquestrador ser de fato apenas um orquestrador?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;É um ponto de atenção importante pois vejo um grande risco de termos anomalias no desenho da solução. O modelo orquestrador pode até ser mais “agradável aos olhos”, mais "visual". Porém com o passar do tempo pode receber regras de negócio que não deveria. Regra de negócio dos microsserviços “vazando” para o orquestrador.&lt;/p&gt;




&lt;p&gt;Existe, entre outros, um framework em Java que propõe uma implementação do padrão SAGA para microsserviços em Java utilizando a estratégia orquestrada com JDBC/JPA e Spring Boot/Micronaut: &lt;a href="https://github.com/eventuate-tram/eventuate-tram-sagas" rel="noopener noreferrer"&gt;Lib Eventuate Tram&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Coreografia&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxcmsuhd64zs6lrt7644d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxcmsuhd64zs6lrt7644d.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Essa outra estratégia é baseada em eventos. Cada “bailarino”, ou cada serviço sabe qual evento disparar e qual evento ouvir para que a saga seja completa. Caberá a cada serviço "avisar" ao seu sucessor que conseguiu realizar a operação com sucesso ou ao seu antecessor caso ocorra alguma falha.&lt;/p&gt;

&lt;p&gt;Já de antemão, essa abordagem possui a vantagem de não introduzir um ponto único de falha, já que as responsabilidades são distribuídas entre os participantes do Saga.&lt;/p&gt;

&lt;p&gt;A própria utilização de um mecanismo de mensageria já traz consigo algumas boas possibilidades de resiliência como retentativas caso haja qualquer tipo de indisponibilidade em algum serviço no meio do processo, por exemplo.&lt;/p&gt;

&lt;p&gt;Além disso, essa estratégia pode se encaixar bem para fluxos de trabalho simples que exigem poucos participantes e não precisam de uma lógica de coordenação.&lt;/p&gt;

&lt;p&gt;Mas novamente, não existe solução perfeita. Podemos citar algumas fraquezas desse modelo como por exemplo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Risco de dependência cíclica entre os participantes do Saga porque eles precisam consumir os comandos uns dos outros;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Quanto maior os passos, mais difícil o tracking do caminho por onde acontece a execução da SAGA;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;O fluxo de trabalho pode ficar confuso ao adicionar novas etapas, pois é difícil controlar quais participantes do Saga ouvem quais comandos.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Qual a mais adequada?
&lt;/h3&gt;

&lt;p&gt;Aqui vale a tão famosa resposta: &lt;strong&gt;Depende!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A decisão de qual estratégia utilizar vai depender muito da característica que seu negócio possui, além da expertise do time para implementar o pattern e também das ferramentas disponíveis para suportar tal abordagem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Outros pontos importantes a serem considerados
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Existem SAGAS onde as operações ocorrem em paralelo. Não necessariamente precisam ser sequenciais;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Para incluir um sistema em uma SAGA, não é algo tão trivial. Seu método, operação ou transação precisa ser reversível;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tempo de duração: Uma SAGA pode demorar alguns segundos ou pode demorar mais tempo como alguns dias, dependendo da característica do seu sistema.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cenários com as ações compensatórias
&lt;/h3&gt;

&lt;p&gt;Compartilho aqui questionamentos ou cenários que imaginei enquanto me aprofundava sobre o tema das ações compensatórias dentro desse pattern e possíveis formas de tratá-los.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mas se a ação de compensação também estiver sujeita a falhas?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Podemos usar aqui padrões de resiliência como Retry e Circuit Breaker em um cenário de comunicação síncrona, mais comum no modelo orquestrado.&lt;/p&gt;

&lt;p&gt;No cenário de coreografia, pode-se utilizar ferramentas de mensageria que já incorporem certa resiliência como no caso em que ela envie a notificação e não receba o Ack ela mantém a mensagem na fila e tenta reenviar algumas vezes até enviar e receber o ack do Consumer/Subscriber.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Devo sempre realizar um "rollback"?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Uma ação compensatória pode não ser simplesmente voltar para o status que estava antes. Por exemplo: num caso de falha no processamento de uma pagamento de uma compra, o correto seria realizar o estorno do valor pago e não voltar o saldo como era pois pode ter havido outras transações na conta do usuário.&lt;/p&gt;

&lt;p&gt;Um outro exemplo emblemático dessa não trivialidade seria uma da etapa do processo ser o envio de e-mail. Se houver falha que interrompa a SAGA em execução, não tem como desfazer esse envio. O correto seria, suponho, enviar outro e-mail de errata.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Devo realmente disparar uma compensação para falha em toda e qualquer transação?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No exemplo utilizado nas ilustrações acima, pode não fazer sentido para o negócio que seu sistema atende já acionar o cancelamento de uma order quando o gateway de pagamento estiver indisponível momentaneamente e, como consequência, impactando a execução da transação dentro do serviço de payment. Isso seria prejudicial já que se perderia uma venda e o cliente impactado talvez não voltasse a comprar em tal e-commerce novamente. O ideal seria ter mecanismos de tratamento e retentativas para ser possível concluir toda a SAGA e garantir a efetivação daquela intenção de compra.&lt;/p&gt;




&lt;p&gt;Com isso, podemos afirmar que uma das coisas mais difíceis é pensar em como lidar com as ações compensatórias. É necessário projetar as etapas de sua saga de forma que você sempre consiga dar rollback de uma visão negocial. Inclusive, projete seu sistema de forma que uma vez que você concluiu uma etapa e precisa dar um rollback você não tenha que dar rollback do rollback.&lt;/p&gt;

&lt;h2&gt;
  
  
  Considerações Finais
&lt;/h2&gt;

&lt;p&gt;Acredito que para uma boa implementação do padrão SAGA, o que manda no final das contas é a regra de negócio da sua aplicação. A arquitetura da sua solução tem que estar totalmente alinhada com as necessidades que seu sistema propõe atender. &lt;/p&gt;

&lt;p&gt;Apesar de bastante útil e eficiente em diversos cenários. Talvez essa complexidade de uma SAGA não seja necessária pelo o que diz a regra. Além disso, ele pode não ser tão adequado quando se tem transações fortemente acopladas ou até mesmo dependências cíclicas.&lt;/p&gt;

&lt;p&gt;Por fim, espero ter contribuído de alguma forma para o entendimento desse pattern importante para lidar no mundo onde sistemas distribuídos estão cada vez mais presentes no nosso dia a dia. Obrigado pelo tempo dedicado à leitura!&lt;/p&gt;

&lt;h3&gt;
  
  
  Referências
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://dzone.com/articles/distributed-sagas-for-microservices" rel="noopener noreferrer"&gt;Distributed Sagas for Microservices&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/pt-br/azure/architecture/reference-architectures/saga/saga" rel="noopener noreferrer"&gt;Saga distributed transactions&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://microservices.io/patterns/data/saga.html" rel="noopener noreferrer"&gt;Pattern: Saga - Chris Richardson&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.cs.cornell.edu/andru/cs711/2002fa/reading/sagas.pdf" rel="noopener noreferrer"&gt;Sagas paper - Hector Garcaa-Molrna and&lt;br&gt;
Kenneth Salem - 1987&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/aphyr/dist-sagas/blob/master/sagas.pdf" rel="noopener noreferrer"&gt;Distributed Sagas paper - Caitie McCaffrey - 2015&lt;/a&gt;&lt;/p&gt;

</description>
      <category>sagas</category>
      <category>microservices</category>
      <category>architecture</category>
      <category>distributedsystems</category>
    </item>
    <item>
      <title>Um pouco sobre Domain Driven Design</title>
      <dc:creator>Thiago Henrique</dc:creator>
      <pubDate>Sun, 13 Jun 2021 00:00:39 +0000</pubDate>
      <link>https://dev.to/thiagosilva95/um-pouco-sobre-domain-driven-design-gfa</link>
      <guid>https://dev.to/thiagosilva95/um-pouco-sobre-domain-driven-design-gfa</guid>
      <description>&lt;p&gt;Entender o Domain Driven Design a primeira vista parece ser confuso, principalmente quando você traz consigo alguns &lt;strong&gt;PRÉ&lt;/strong&gt;-conceitos sobre tal tema. A meta desse post é tentar, ainda que de forma geral, visto que o assunto pode ser muito mais complexo do que parece, abrir o caminho para seu entendimento de forma eficiente.&lt;/p&gt;

&lt;p&gt;Gostaria de começar dizendo que o DDD não é uma receita para desenvolver softwares em camadas e também não é um padrão arquitetural. O DDD é uma abordagem de modelagem de software que segue um conjunto de práticas com o objetivo de facilitar a implementação de regras complexas ou processos de negócios que tratamos como domínio.&lt;/p&gt;

&lt;p&gt;Mesmo não sendo um padrão arquitetural, ele afeta como as decisões arquiteturais são tomadas. O DDD é muito mais sobre a forma de pensar, desenhar e desenvolver aplicações que tem como objetivo implementar o melhor design possível baseado em modelos que refletem a competência da organização.&lt;/p&gt;

&lt;p&gt;Essa abordagem tem como precursor Eric Evans, autor do livro &lt;em&gt;“Domain-Driven Design – Atacando as Complexidades no Coração do Software”&lt;/em&gt; (o livro azul) publicado em 2003. Evans mostra como um conjunto de &lt;em&gt;best practices&lt;/em&gt; de desenvolvimento, boas estratégias de negócio e uma equipe alinhada podem ser benéficos para que um projeto com uma grande complexidade possa ter sucesso. &lt;/p&gt;

&lt;p&gt;Outras grandes referências sobre o DDD são as obras de Vaughn Vernon que trazem  uma leitura menos densa, usam de uma linguagem mais acessível e demonstram aplicações práticas sobre a abordagem. Ainda estou no processo de leitura, mas acredito que hoje ainda são o que há de mais completo sobre o tema.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1v5b2pg9kihqzlsu215n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1v5b2pg9kihqzlsu215n.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Complexidade do Software = Complexidade do domínio x Complexidade técnica acidental
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw3psn4ax789uv8z038v9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw3psn4ax789uv8z038v9.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Com um pouco de vivência no processo de desenvolvimento de software é possível perceber que nem tudo sai como o esperado. O entendimento de um negócio é algo dinâmico e que precisa ser um processo contínuo. Dificilmente a primeira versão de uma especificação funcional é a que soluciona adequadamente o problema. &lt;/p&gt;

&lt;p&gt;Lá trás, talvez o mais comum seria o arquiteto de software pensar em uma arquitetura robusta e demasiadamente detalhada para atender à necessidade do negócio especialmente quando a especificação é construída. Começando, por exemplo, pela camada de banco de dados, definição de componentes para atender a integrações com serviços externos como envio de e-mail, etc.&lt;/p&gt;

&lt;p&gt;Porém o conhecimento do negócio possui necessidades que não conseguimos ver no começo. O projeto cresce. O entendimento do negócio cresce. As necessidades mudam.&lt;/p&gt;

&lt;p&gt;As mudanças serão necessárias pois ao decorrer do tempo as necessidades do usuário mudam e uma aplicação criada para tal domínio precisa atendê-las e não as necessidades de meses atrás. Com isso, os desenvolvedores podem encontrar dificuldades em implementar as mudanças dentro de um padrão imposto inicialmente. Isso gera &lt;strong&gt;complexidade técnica acidental&lt;/strong&gt;. O código muitas vezes fica mais complexo do que deveria porque precisa seguir certos padrões imposto anteriormente. À medida que o sistema vai crescendo, a complexidade técnica acidental fica maior do que a própria complexidade do negócio. O resultado disso é o que o DDD chama de &lt;em&gt;Big Ball of Mud&lt;/em&gt;. O software fica tão complexo que dar manutenção e evolui-lo se torna uma dor de cabeça.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1mzvr00qo2xznkeopmsh.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1mzvr00qo2xznkeopmsh.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O DDD entra nessa história justamente para trazer a tona que o entendimento do domínio do negócio é um processo crescente, que necessita da cooperação e comunicação da equipe como um todo. Ao invés do modelo tradicional, em que a comunicação ocorre em apenas algumas etapas do projeto, temos um fluxo de comunicação contínua e colaborativa, por meio de uma única linguagem. O DDD nos instrui a começar mais simples e ir evoluindo a medida que o negócio também evolui.&lt;/p&gt;

&lt;h2&gt;
  
  
  Domínio
&lt;/h2&gt;

&lt;p&gt;Uma palavra chave no DDD, inclusive já mencionei ela várias vezes até o momento, e importantíssima para que compreendamos suas diretrizes é entender o que representa o &lt;strong&gt;domínio&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Poderíamos defini-lo como tudo que compreende o software e faz com que ele funcione. O espaço problema que a equipe está inserida. O principal assunto do seu projeto.&lt;/p&gt;

&lt;p&gt;E o processo de modelar o domínio é algo semelhante a um documentário sobre a vida de uma pessoa. Não se registra cada passo, cada acontecimento e detalhe em uma biografia, e sim nos pontos importantes para que a mensagem desejada seja bem compreendida. Da mesma forma, quando falamos em projetos de software, devemos colocar o esforço necessário no que a aplicação precisa para funcionar.&lt;/p&gt;

&lt;p&gt;Para fazer uma analogia, podemos lembrar de um jogo bem conhecido, o Banco Imobiliário. Podemos imaginar que ele é um modelo de algo bem mais abrangente e complexo, o mercado imobiliário (domínio).&lt;/p&gt;

&lt;h2&gt;
  
  
  Design estratégico x Design tático
&lt;/h2&gt;

&lt;p&gt;O DDD nos fornece o design estratégico e design tático como ferramentas para suportar as atividades de modelagem e design do domínio de uma aplicação. E para melhor compreendermos, trago uma definição feita pelo autor Vaughn Vernon:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Design estratégico é como fazer o rascunho antes de entrar nos detalhes da implementação. Destaca o que é estrategicamente importante para o seu negócio, como dividir o trabalho por importância e como fazer integrações da melhor maneira."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;O design estratégico é como esse rascunho, enquanto o design tático é implementação, o detalhamento. O autor ainda diz sobre design estratégico:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“DDD é primariamente sobre modelar uma linguagem ubíqua em contexto delimitado” — Vaughn Vernon&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Contexto delimitado é uma barreira semântica onde todos os componentes do modelo terão um significado específico. Já a Linguagem Ubíqua fornece as palavras que existirá nesse contexto. Ubíqua porque ela vai estar implementada no código do software. Entrarei nos detalhes desses itens a seguir.&lt;/p&gt;

&lt;h3&gt;
  
  
  Os pilares do Design Estratégico
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Linguagem Ubíqua
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb3mkq1aa7xoyze29ix46.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb3mkq1aa7xoyze29ix46.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Quando se estuda DDD pode ficar até cansando em falar na linguagem ubíqua. Acontece que ela é essencial para fortalecer os laços entre os especialistas do negócio e o time de desenvolvimento.&lt;/p&gt;

&lt;p&gt;Ao aplicá-la, termos estritamente técnicos são substituídos por termos que o usuário compreenda. Essa linguagem universal, como também é conhecida, fica mais próxima da área de negócio do que dos desenvolvedores e ao mesmo tempo que é utilizada entre todos os membros do time (incluindo os Domain Experts), também é implementada como código fonte. É essencial que a Linguagem Ubíqua seja rigorosa e precisa. Uma vez definida, deve ser utilizada até o fim.&lt;/p&gt;

&lt;p&gt;Talvez um bom exercício para saber se você está conseguindo utilizar a esse princípio do DDD da maneira correta seria extrair um diagrama de classe e mostrar a um especialista e mostrar para o usuário. Ao fazer isso, ele conseguiria entender e validar o modelo de negócio? Se sim, está próximo do DDD.&lt;/p&gt;

&lt;h4&gt;
  
  
  Bounded Contexts
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzc5jq218ez2ettvusmts.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzc5jq218ez2ettvusmts.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Serve para sinalizar até aonde vai a responsabilidade de cada parte do sistema. Cada contexto possui suas responsabilidades claramente definidas (Pagamento, assinatura, frete).&lt;br&gt;
Um ponto importante é que cada contexto pode ter sua própria abordagem de arquitetura (camadas de aplicação, persistência, infraestrutura  e etc) inclusive sua própria linguagem ubíqua. Se você trabalha em departamento de vendas, por exemplo, um cliente pode ser alguém que faz ordem de serviço. &lt;br&gt;
Mas para alguém do setor de Marketing pode ser o consumidor de propagandas etc. Isso acontece poque entidades com mesmo nome podem ser encontradas em contexto diferentes.&lt;br&gt;
A utilização de histórias e levantamento do escopo do projeto com o domain expert auxilia no processo de delimitação dos contextos e isso deve ser feito de uma forma mais efetiva possível.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8z06cvcl8nkwewmqv9nc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8z06cvcl8nkwewmqv9nc.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O Vernon Vernon dá uma dica para quando você está em reuniões com pessoas de negócio e elas tem visões diferentes sobre o domínio e precisa-se delimitar os contextos que serão utilizados no projeto. Segundo o autor, quando isso acontece, ou todo mundo tem razão e deve separar os domínios ou a pessoa responsável não está no momento.&lt;/p&gt;

&lt;p&gt;Existem algumas referências descrevendo que perguntaram ao Eric Evans se ele pudesse modificar algo no seu livro, o que seria. Ele respondeu que começaria falando primeiro ou focaria mais em Bounded Contexts devido a sua complexidade e importância para a abordagem do DDD.&lt;/p&gt;

&lt;p&gt;Em uma fase mais avançada no projeto de uma aplicação, cada Contexto precisa ser transformado em código. Um insight interessante que essa estratégia pode trazer é que normalmente cada contexto definido pode ser transformado em um microsserviço.&lt;/p&gt;

&lt;h4&gt;
  
  
  Context Maps
&lt;/h4&gt;

&lt;p&gt;O mapa de contexto nada mais é do que um documento, uma imagem, um rascunho anexado na parede, qualquer coisa que facilite o entendimento dos contextos da aplicação.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgkt0ftkwz5jgx9w1cyxb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgkt0ftkwz5jgx9w1cyxb.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pilares do Design Tático
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy0vcadu3yybrxvjncyou.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy0vcadu3yybrxvjncyou.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Em linhas gerais iremos falar de padrões de desenvolvimento e estruturação de aplicações cujo &lt;strong&gt;domínio&lt;/strong&gt; é o principal foco. As ferramentas de design tático do DDD se preocupam com os detalhes da implementação. Geralmente trata dos componentes dentro de um contexto delimitado. Ao contrário do design estratégico, espera-se que o design tático&lt;br&gt;
sofra mudanças durante o desenvolvimento do produto&lt;/p&gt;

&lt;h3&gt;
  
  
  Value Objects
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fth0xyquwc2o1rqorhlrd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fth0xyquwc2o1rqorhlrd.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Value Objects é uma coleção de atributos que são &lt;strong&gt;imutáveis&lt;/strong&gt;. Isso significa que normalmente não possuem métodos seters e a entrada dos valores se dá através do construtor. Além disso, possui uma tipagem forte ao invés de dados primitivos. O próprio VO deve conter sua regra de consistência e ele mesmo deve se validar.&lt;/p&gt;

&lt;h3&gt;
  
  
  Entidade
&lt;/h3&gt;

&lt;p&gt;A principal diferença entre entidade e value object é que entidades possuem &lt;strong&gt;identidade&lt;/strong&gt;. Ou seja, deve ser exclusiva para o objeto mapeado. Nela se encontram as principais lógicas de negócios, mas não fazem persistência. Entidades também possuem estados e comportamentos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Aggregates
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5i4ld3v2mjcepekb4sbl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5i4ld3v2mjcepekb4sbl.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Podemos dizer que Aggregate é uma entidade com características diferentes. Ou ainda, um conjunto de entidades usadas e referenciadas juntas. Quando um dado é alterado essas entidades são tratadas como uma só.&lt;br&gt;
Possui uma raiz de agregação (Aggregation Root) que é a entidade mais "forte" do conjunto e que mantém a integridade do objeto.&lt;/p&gt;

&lt;p&gt;Na imagem abaixo, temos exemplos de agregações compostas por sua entidade raiz (azul), demais entidades (cinza) e alguns value objects (branco).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuh2ooy606fcqxlvxa6sj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuh2ooy606fcqxlvxa6sj.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;É importante dizer que quando a entidade está isolada, ela é sua própria raiz de agregação.&lt;/p&gt;

&lt;p&gt;O Aggregation Root tem entre seus principais objetivos proteger/evitar o acesso direto aos objetos filhos e certificar que o estado desses objetos está sempre consistente.&lt;/p&gt;

&lt;p&gt;Outro detalhe que vale mencionar é que deve existir apenas um repositório por agregação.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcmwmmywatx1ytgej62e6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcmwmmywatx1ytgej62e6.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Na imagem acima, como podemos entender o limite dessas &lt;code&gt;Cliente&lt;/code&gt; e &lt;code&gt;Endereço&lt;/code&gt;? São entidades distintas ou devem compor uma agregação? Os limites de uma agregação são determinados pela regra de negócio. Então, para entender o limite entre as duas devemos nos perguntar se esse endereço serve pra outra coisa além de pertencer a um cliente. Caso não, deveria compor uma agregação que tem &lt;code&gt;Cliente&lt;/code&gt; como raiz.&lt;/p&gt;

&lt;h3&gt;
  
  
  Repositório
&lt;/h3&gt;

&lt;p&gt;Os repositórios possuem acesso direto a camada de dados. Eles persistem os dados utilizando as entidades. Possui os métodos necessários para consultar, inserir, atualizar e excluir registros de uma fonte de dados.&lt;/p&gt;

&lt;h3&gt;
  
  
  Serviços de domínio
&lt;/h3&gt;

&lt;p&gt;Os Domain Services trabalham com diversos fluxos de diversas entidades e agregações. Utilizam os repositórios como interface de acesso aos dados, consumem recursos da camada de infra como enviar e-mail, disparar eventos, entre outros. Basicamente fazem tudo o que o model não deve fazer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Event storming
&lt;/h2&gt;

&lt;p&gt;Apresentados todos esses conceitos é comum olhar tudo isso, entender, mas não conseguir traçar um plano claro sobre como colocá-lo em prática. Para isso existe uma técnica extremamente poderosa para esse fim, o Event Storming.&lt;/p&gt;

&lt;p&gt;Se trata de um exercício para criação de modelos de domínios para design estratégico. É basicamente um whorkshop de Brain storming que engaja especialistas do domínio de negócios com desenvolvedores focando mais nos processos de negócio do que em abstrações técnicas (classes, entidades…).&lt;/p&gt;

&lt;p&gt;Normalmente se colocam post-its em um quadro para indicar quais eventos de domínio acontecem, a quem interessa, quem provocou, tudo de forma ordenada numa linha de tempo para que se desenhe um caminho que o software irá percorrer. Isso pode clarificar muitas coisas para os membros da equipe. &lt;/p&gt;

&lt;p&gt;Essa materialização visual pode ajudar ao desenvolvedor a ter noção do seu papel no contexto do domínio. Acredito que deve ser imprescindível codificar e saber em que ponto você está.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foodyo7fehqy543ye9hcp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foodyo7fehqy543ye9hcp.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Considerações Finais
&lt;/h2&gt;

&lt;p&gt;Uma provocação válida seria perguntar se vale a pena usar DDD pra tudo? A resposta que eu daria seria: Vale a pena pra quase tudo!&lt;/p&gt;

&lt;p&gt;O DDD é voltado para domínios complexos, usá-lo implica em uma efetiva comunicação entre especialistas de negócio e especialistas técnicos, esforço dos devs em programar de forma que o código reflita o domínio. Se um desses pontos não se aplicar ao contexto em questão, provavelmente o DDD não serve para o cenário que você está lidando.&lt;/p&gt;

&lt;p&gt;Espero que tenha ficado claro que o DDD não é nenhuma bala de prata, assim como o Clean Architecture que foi tema do meu &lt;a href="https://dev.to/thiagosilva95/clean-architecture-o-que-e-vantagens-e-como-utilizar-em-aplicacoes-na-pratica-4ej8"&gt;post anterior&lt;/a&gt;, para resolver todos os problemas de um software. O importante é ter em mente que ao identificar que o domínio em questão é complexo, que existe a intenção de desenvolve-lo para que a representação do domínio seja clara até para os Domain Experts e mais, que o cliente está interessado em colaborar com o entendimento do domínio e validação da solução, provavelmente o DDD seja uma boa escolha como abordagem de desenvolvimento.&lt;/p&gt;

&lt;p&gt;Tenho ciência que para explanar por completo essa "filosofia" de desenvolvimento de software seria necessário muito mais que esse post. Então espero ter atingido o objetivo de sumarizar os princípios do Domain Driven Design através desse compilado de informações e sirva, por que não, de insumo para discursões construtivas sobre esse tema riquíssimo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=QxRXB1B9m8E" rel="noopener noreferrer"&gt;Domain-Driven Design: uma visão geral&lt;/a&gt; — Eriksen Costa&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=NryGGD21O20" rel="noopener noreferrer"&gt;DDD: Boas Práticas na escrita e validação de Entidades de Domínio&lt;/a&gt; - Eduardo Pires&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=eUf5rhBGLAk&amp;amp;t=1620s" rel="noopener noreferrer"&gt;Aprenda DDD (Domain Driven Design) do jeito certo&lt;/a&gt; - Full Cycle&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/playlist?list=PLZBNtT95PIW3BPNYF5pYOi4MJjg_boXCG" rel="noopener noreferrer"&gt;Course #1 Mastering the art of Microservices Architecture&lt;/a&gt; - Alpha Code&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>development</category>
      <category>bestpractice</category>
      <category>ddd</category>
    </item>
    <item>
      <title>Clean Architecture: o que é, vantagens e como utilizar em aplicações na prática</title>
      <dc:creator>Thiago Henrique</dc:creator>
      <pubDate>Sat, 12 Jun 2021 22:48:36 +0000</pubDate>
      <link>https://dev.to/thiagosilva95/clean-architecture-o-que-e-vantagens-e-como-utilizar-em-aplicacoes-na-pratica-4ej8</link>
      <guid>https://dev.to/thiagosilva95/clean-architecture-o-que-e-vantagens-e-como-utilizar-em-aplicacoes-na-pratica-4ej8</guid>
      <description>&lt;p&gt;Ultimamente estamos ouvindo falar bastante sobre termos como "Clean Architecture", "Hexagonal Architecture", "SOLID", "DRY", "DDD", etc. Todos eles são princípios, práticas ou abordagens no mundo de desenvolvimento de software que, em essência, convergem para o objetivo de tornar o software mais robusto, escalável e flexível, deixando-o tolerante a mudanças, facilitando a implementação de novos requisitos para a evolução e manutenção do sistema.&lt;/p&gt;

&lt;p&gt;Quando se fala em &lt;strong&gt;Clean Architecture&lt;/strong&gt; temos algumas características como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Arquitetura FOCADA nas regras de negócio: suas regras não devem conhecer o "mundo lá fora" (Frameworks, Ferramentas, Tecnologias, etc).&lt;/li&gt;
&lt;li&gt;Inversão de dependências: Por exemplo, seu banco de dados deve depender das suas regras, e não suas regras do seu banco. Sua UI? Mesma coisa!&lt;/li&gt;
&lt;li&gt;A melhor decisão é a que você pode tomar depois? Isso não é preguiça, é arquitetura incremental. &lt;/li&gt;
&lt;li&gt;Regras de negócio devem ser 100% TESTÁVEIS e INDEPENDENTES!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O diagrama que utilizei na parte superior deste post, segundo Uncle Bob, é uma tentativa de integrar todos esses conceitos e boas práticas arquiteturas em uma única ideia.&lt;/p&gt;

&lt;p&gt;Um sistema bem estruturado possui baixo acoplamento e alta coesão, portanto, uma das soluções encontradas é a divisão do sistema em camadas.&lt;/p&gt;

&lt;p&gt;Surge então a &lt;strong&gt;Regra de Dependência&lt;/strong&gt; que, acordo com a figura, nos mostra que a seta apenas segue para dentro, ou seja, a camada mais externa visualiza e utiliza a mais interna. O inverso não pode acontecer. Isso não faz com que o software fique dependente ou restritivo, muito pelo contrário, a aplicação dessa regra diminui as limitações do código o tornando organizado e acessível. Não ultrapassar essas barreiras é essencial para otimizar o funcionamento do sistema.&lt;/p&gt;

&lt;h3&gt;
  
  
  Entities
&lt;/h3&gt;

&lt;p&gt;Na camada de entidades, deve ser alocada a lógica de negócio e as regras de alto nível. Essa camada pode ser usada por todas as outras, tendo em vista que possui regras mais gerais do software, ou seja, as entidades são usadas pelas classes mais externas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Cases
&lt;/h3&gt;

&lt;p&gt;Neste nível do software, cabe a aplicação das regras de negócio para cada caso. Estas são mais específicas e dizem respeito a validações por exemplo. &lt;/p&gt;

&lt;h3&gt;
  
  
  Interface Adapters
&lt;/h3&gt;

&lt;p&gt;Esta camada tem uma função bem específica como todas as outras. Função esta que é converter as informações vindas das camadas internas (entidades+casos de uso) para o reconhecimento dos elementos pertencentes no próximo nível.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frameworks and Drivers
&lt;/h3&gt;

&lt;p&gt;Composta pelos elementos mais externos: Frameworks, Banco de dados, bibliotecas e derivações.&lt;/p&gt;

&lt;h2&gt;
  
  
  Aplicação prática
&lt;/h2&gt;

&lt;p&gt;Para ilustrar como podemos aplicar o conceito de Clean Architecture na prática, trago aqui uma situação onde temos um projeto de API de cadastro utilizando a liguangem &lt;em&gt;NodeJs&lt;/em&gt; e algumas bibliotecas como o &lt;em&gt;Express&lt;/em&gt;, &lt;em&gt;MongoDB&lt;/em&gt;, &lt;em&gt;BCrypt&lt;/em&gt; para criptografia de senha e &lt;em&gt;Validator&lt;/em&gt; para validar o e-mail recebido.&lt;/p&gt;

&lt;p&gt;Sei que esse exemplo é de baixa complexidade, mas acredito que é suficiente para entender a abordagem proposta nesse post.&lt;/p&gt;

&lt;p&gt;A imagem abaixo talvez represente a forma como geralmente estruturamos esse tipo de projeto quando não se conhece a abordagem arquitetural que estamos discutindo aqui.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frwm25y8qto523eawnci1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frwm25y8qto523eawnci1.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nesse cenário temos componentes como o &lt;code&gt;SignUpController&lt;/code&gt; e &lt;code&gt;SignUpRouter&lt;/code&gt; acloplados a biblioteca de terceiros, além de termos componentes que possuem muitas "responsabilidades". Se precisarmos em algum momento trocar o Express por outro framework, será necessário alterar todos os controllers.&lt;/p&gt;

&lt;p&gt;Então para dar início a uma transformação na arquitetura do nosso sistema podemos iniciar focando em desacoplar nossos controllers do Express. Esse tipo de decisão em um cenário ideal deveria ser uma tarefa muito fácil. Mas aqui temos que essa biblioteca praticamente "toma conta" do sistema.&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;SignUpController&lt;/code&gt; aponta para o Express por isso o primeiro passo seria usar o padrão de inversão de dependência (dependency inversion) para fazer com que o Express olhe para nossos controllers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa158364nclisdyoousq9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa158364nclisdyoousq9.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para isso, podemos criar um adapter entre os dois que terá a tarefa de converter as interfaces do controller para a realidade do Express. Uma das particularidades do Express é que ele espera receber o (req, res) como parâmetros nas rotas definidas. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fahsjc7yvimdplg8da378.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fahsjc7yvimdplg8da378.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Também não podemos permitir que o adapter dependa diretamente do &lt;code&gt;SignUpController&lt;/code&gt;. Devemos fazer com que ele possa adaptar qualquer controlador, assim, criamos uma camada &lt;strong&gt;Presentation&lt;/strong&gt; e dentro dela uma interface &lt;code&gt;Controller&lt;/code&gt;, que irá servir como um limite desta camada para fazer a inversão de dependência. O adapter precisa de qualquer classe que utilize a interface.&lt;br&gt;
Com isso a dependência inverteu. Se eu precisar trocar, só altero o adapter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxjqyzrfjv0r2aswnn6u4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxjqyzrfjv0r2aswnn6u4.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Seguindo em frente, precisamos agora desacoplar a biblioteca para validar e-mail para que nosso presentation layer não dependa de um componente externo. Criamos um &lt;code&gt;EmailValidatorAdapter&lt;/code&gt; semelhante ao adapter criado anteriormente.&lt;br&gt;
Assim, em vez de o &lt;code&gt;SignUpController&lt;/code&gt; depender diretamente desse adapter, definimos, ainda na camada de apresentação, uma nova interface &lt;code&gt;EmailValidator&lt;/code&gt; que diz o que esse componente deve fazer e "alguém" de fora implementa a interface definida. Dessa forma desacoplamos e se outros controladores precisarem usar esse validador poderemos facilmente reutilizar o componente. Ainda temos o benefício de, se um dia optarmos por substituir essa biblioteca por uma regex por exemplo, alteraremos apenas um componente.&lt;/p&gt;

&lt;p&gt;Podemos dizer que é nossa camada &lt;strong&gt;Utils&lt;/strong&gt; que é mais genérica irá conter coisas que podem ser utilizadas em qualquer lugar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F272m0hf9zyzktg1jc17g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F272m0hf9zyzktg1jc17g.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Surge, então, a necessidade de uma camada de negócio que diga o que precisamos fazer. Pois para realizar um cadastro, precisamos salvar os dados no banco de dados, mas antes disso, queremos criptografar a senha do usuário.&lt;br&gt;
Criamos então uma interface &lt;code&gt;AddAccount&lt;/code&gt; que nada mais é do que a representação de uma camada de negócio da aplicação, a camada &lt;strong&gt;Domain&lt;/strong&gt;. Essa camada não terá implementação, mas apenas protocolos que dizem o que nossa regra de negócio deve fazer.&lt;br&gt;
Com isso, o &lt;code&gt;SignUpController&lt;/code&gt; irá precisar de alguém que implemente essa interface para criar uma conta de usuário. Não importa se a implementação será com banco de dados, cache, ou dados "mockados", o que importa é que a implementação respeite a interface definida.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6d1dtvt2o3f0vwxxlrkf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6d1dtvt2o3f0vwxxlrkf.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Assumindo que queremos a implementação da regra de negócio voltada para armazenamento em banco de dados, criaremos a &lt;strong&gt;Data&lt;/strong&gt; layer que terá o componente &lt;code&gt;DbAddAcccount&lt;/code&gt;.&lt;br&gt;
Esse sim irá utilizar o BCrypt para fazer a criptografia da senha do usuário. Mas não queremos acoplá-los diretamente. Assim como antes, criaremos o &lt;code&gt;BCryptAdapter&lt;/code&gt; para isolar os nossos componentes do &lt;em&gt;BCrypt&lt;/em&gt; que uma biblioteca externa.&lt;br&gt;
Ele ficará dentro da &lt;strong&gt;Infra&lt;/strong&gt; layer, camada que terá implementações de interface voltadas para frameworks. E agora para realizar a inversão de dependência, criamos a interface &lt;code&gt;Encrypter&lt;/code&gt; ainda na Data layer já que o &lt;code&gt;DbAddAcccount&lt;/code&gt; precisa de alguém que saiba fazer criptografia e não ele mesmo saber como faz.&lt;br&gt;
Com isso a dependência inverteu novamente. O Infra layer que aponta para o Data layer e não o Data layer apontando para o Infra.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7gjgee2zaa57vma5iey0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7gjgee2zaa57vma5iey0.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para finalizar temos o a dependência com o MongoDb. Criaremos o componente &lt;code&gt;AddAccountMongoRepository&lt;/code&gt; que sabe usar o mongo e criaremos também a interface &lt;code&gt;AddUserRepo&lt;/code&gt; pois outros componentes podem precisar de "alguém" que saiba inserir no banco de dados, não importa qual.&lt;br&gt;
Inversão de dependência feita mais uma vez.&lt;/p&gt;

&lt;p&gt;Com isso as bibliotecas de  terceiros estão cada vez mais isoladas, cada vez mais na camada mais "fora" da nossa arquitetura. Se futuramente quisermos trocar MongoDB, vamos alterar apenas um componente.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuowklp9objucgzfvqwd3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuowklp9objucgzfvqwd3.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Realizamos até aqui transformações, com a ajuda do padrão de projeto &lt;em&gt;Adapter&lt;/em&gt;, que removem o acoplamento entre as camadas. Mas para conseguir ter uma solução completa e desacoplar nossas camadas precisamos acoplar uma delas, e esta será a &lt;strong&gt;Main&lt;/strong&gt; layer. &lt;/p&gt;

&lt;p&gt;Ela será responsável por criar instâncias de todos os objetos. Exemplo: Para criar a rota de signup precisamos do &lt;code&gt;SignUpController&lt;/code&gt;, que por sua vez precisa de alguém que implemente a interface &lt;code&gt;AddAccount&lt;/code&gt;. Mas que sua implementação não será instanciada no controller.&lt;br&gt;
"Alguém" irá criar essa instância e injetará no controller. O Main layer fará a composição desses objetos através de outro design pattern, o &lt;em&gt;Composite&lt;/em&gt;, e toda composição será feita em um lugar só.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh3h3h8ab5i2rkiawazez.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh3h3h8ab5i2rkiawazez.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Abaixo está o desenho final desse exemplo, destacando com cores para melhor visualização das camadas. Acredito que tenhamos chegado bem próximo de um desenho arquitetural bem estruturado com baixo acoplamento e alta coesão. Observa-se que as dependências externas estão sempre nas "pontas" e facilmente podemos troca-las sem afetar o resto do sistema. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo7tr0knvkz7mz837iux0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo7tr0knvkz7mz837iux0.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Considerações Finais
&lt;/h2&gt;

&lt;p&gt;As ideias propostas por Uncle Bob, padronizam o desenvolvimento de software moderno. &lt;br&gt;
Nota-se que os métodos sugeridos, se aplicados de maneira correta, organizam o código, facilita o trabalho em equipe, e entre outros benefícios. Isso não quer dizer que o Clean Architecture é uma "bala de prata" para desenvolver softwares. Ressalto aqui que sua aplicação deve ser avaliada de acordo com o tipo de projeto e suas particularidades.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;p&gt;Artigo do &lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" rel="noopener noreferrer"&gt;Uncle Bob&lt;/a&gt; sobre Clean Architecture.&lt;/p&gt;

&lt;p&gt;Curso NodeJs, Typescript, TDD, Clean Architecture e SOLID na &lt;a href="https://www.udemy.com/course/tdd-com-mango/" rel="noopener noreferrer"&gt;Udemy&lt;/a&gt; do Rodrigo Manguinho.&lt;/p&gt;

</description>
      <category>clean</category>
      <category>architecture</category>
      <category>development</category>
      <category>bestpractices</category>
    </item>
  </channel>
</rss>
