<?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: Pedro Mafra</title>
    <description>The latest articles on DEV Community by Pedro Mafra (@pmafra).</description>
    <link>https://dev.to/pmafra</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%2F1414474%2F868b0af4-8106-4fd9-a296-581bff226a76.jpg</url>
      <title>DEV Community: Pedro Mafra</title>
      <link>https://dev.to/pmafra</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pmafra"/>
    <language>en</language>
    <item>
      <title>Domain-Driven Design: como evitar o "Big Ball of Mud"</title>
      <dc:creator>Pedro Mafra</dc:creator>
      <pubDate>Thu, 27 Jun 2024 13:50:32 +0000</pubDate>
      <link>https://dev.to/pmafra/domain-driven-design-como-evitar-o-big-ball-of-mud-106i</link>
      <guid>https://dev.to/pmafra/domain-driven-design-como-evitar-o-big-ball-of-mud-106i</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Introdução&lt;/li&gt;
&lt;li&gt;Algumas considerações&lt;/li&gt;
&lt;li&gt;Como o DDD pode ajudar&lt;/li&gt;
&lt;li&gt;Domínios, sub-domínios e contextos&lt;/li&gt;
&lt;li&gt;Elementos transversais&lt;/li&gt;
&lt;li&gt;
Context Mapping

&lt;ul&gt;
&lt;li&gt;Partnership (parceria)&lt;/li&gt;
&lt;li&gt;Shared kernel&lt;/li&gt;
&lt;li&gt;Customer-Supplier development - upstream/downstream&lt;/li&gt;
&lt;li&gt;Conformist&lt;/li&gt;
&lt;li&gt;Anti-corruption layer&lt;/li&gt;
&lt;li&gt;Open Host Service&lt;/li&gt;
&lt;li&gt;Published language&lt;/li&gt;
&lt;li&gt;Separate ways&lt;/li&gt;
&lt;li&gt;Big Ball of Mud&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  Introdução
&lt;/h1&gt;

&lt;p&gt;O DDD acabou virando algo meio místico nos dias de hoje, em que muito se fala e nada se entende. Muitos acham que é apenas uma série de Design Patterns, ou até mesmo codar de forma estruturada em pastas. Este artigo buscará mostrar que o DDD vai muito além disso.&lt;/p&gt;

&lt;p&gt;De início, podemos entender a sua origem: o DDD foi um conceito abordado no livro de Eric Evans lançado em 2003 que, desde então, vem sendo amplamente utilizado principalmente ao se trabalhar com grandes projetos, objetivando uma clareza mais profunda do produto e possibilitando que o software sobreviva de forma saudável.&lt;/p&gt;

&lt;p&gt;Sendo assim, fica a pergunta: mas o que esse conceito apresenta de tão especial?&lt;br&gt;
Bom, para entender isso, vamos tentar dar defini-lo:&lt;/p&gt;




&lt;p&gt;“Domain Driven Design é modelar um software com base em seus diferentes domínios, buscando entender suas regras, processos e complexidades. É basicamente moldar problemas e trazer soluções a eles, separando as responsabilidades de cada um.”&lt;/p&gt;




&lt;p&gt;Podemos entender o DDD quase como uma filosofia, uma forma de pensar ao se trabalhar com software. Hoje em dia, em que se trabalhar com microsserviços tornou-se tão importante, essa filosofia aumenta ainda mais seu protagonismo → grande parte do desafio dos MS é exatamente conseguir modelar o software, separar suas complexidades e entender seus contextos para conseguirmos criá-los de forma mais independente.&lt;/p&gt;

&lt;p&gt;Além disso, em um âmbito mais prático, também apresenta princípios base e Patterns para que o dev consiga trabalhar em projetos com diferentes escopos de forma mais decente e organizada.&lt;/p&gt;

&lt;h1&gt;
  
  
  Algumas considerações
&lt;/h1&gt;

&lt;p&gt;Antes de seguir no assunto, vamos fazer e refletir com algumas considerações:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DDD é para projetos mais complexos;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O negócio e o domínio devem ter certo nível de complexidade para que consigamos modelá-lo. Não adianta querermos usar DDD p/ modelar um software super simples com 5 cruds - o DDD é utilizado quando temos problemas maiores e não temos clareza do todo,  como uma coisa se relaciona com a outra, e também quando temos muitas pessoas e de departamentos diferentes envolvidos;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Projetos complexos possuem muitas áreas, regras de negócio, pessoas com visões diferentes em variados contextos;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Considere o exemplo:&lt;/p&gt;

&lt;p&gt;Em uma certa empresa A, mais “old school”, o coração do negócio (que traz o resultado esperado) pode ser fazer vendas ligando para os clientes um a um, e chama este processo de “vender por live-call”. Já em outra empresa B, mais moderna e automatizada vendendo através de seu site, as ligações 1 a 1 servem apenas para suportar/complementar o negócio base (de vender online), e chamam esse processo de “vender no one-on-one”.&lt;/p&gt;

&lt;p&gt;Podemos ver que são duas coisas “iguais” em contextos diferentes, e portanto com significados e graus diferentes de importância. Cada empresa também terá sua forma específica de se expressar e seus jargões específicos. &lt;br&gt;
O software é vivo e movido a pessoas e contextos. Nós, devs, temos que entender isso e modelá-lo de acordo com estes princípios.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Não temos como tratar um software grande, complexo, em uma empresa com muitos processos e pessoas, sem utilizar técnicas avançadas;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Grande parte da complexidade do software não vem da tecnologia em si, mas sim da comunicação, separação de contextos, entendimento do negócio por diversos ângulos;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Muitas vezes quando um software começa a dar problema não é por conta da tecnologia escolhida, e sim por conta da complexidade de negócio. Quando vamos “transformar” o negócio para tecnologia, se não tivermos clareza do mesmo, é quase certo que o software terá problemas no futuro. E uma das principais formas de ter essa clareza é usando o DDD.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Em uma empresa temos devs, POs, gerentes, diretoria, etc., pessoas com várias opiniões distintas;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Não podemos ser inocentes de achar que o software tem uma visão única - temos que entendê-lo com base no contexto de cada um e ter técnicas adequadas para extrair a informação e entregar o que realmente precisamos.&lt;/p&gt;

&lt;h1&gt;
  
  
  Como o DDD pode ajudar
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Vai nos ajudar a entender com profundidade o domínio e subdomínios da aplicação;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;DDD diz para termos uma linguagem universal (linguagem ubíqua) entre todos os envolvidos:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Um das coisas que geram muitos problemas é que diferentes times, contextos, colaboradores tem linguagens/jargões específicos. Isso aqui é um ponto muito importante pois permeia todo o processo de desenvolvimento → todos tem que estar na mesma página.&lt;/p&gt;

&lt;p&gt;Exemplo: para um departamento de vendas, os ‘clientes’ vão ser uma coisa, para outro departamento, serão outra. Se ambos os departamentos começarem a falar juntos sobre ‘clientes’ pode haver confusão - vamos aprender a controlar isso no dia a dia com o DDD.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Vai ajudar a criar um design mais estratégico utilizando Bounded Contexts;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Vai ajudar a criar um design tático para conseguir mapear e agregar as entidades e objetos de valor da aplicação, bem como os eventos de domínio;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Com o design estratégico, conseguimos separar os contextos, com o tático, conseguimos mapear as entidades do negócio, para então começar a desenvolver o nosso programa.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clareza do que é complexidade de negócio e complexidade técnica;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Por fim, deixo uma definição do Vernon sobre DDD:&lt;/p&gt;




&lt;p&gt;“In short, DDD is primarily about modeling a Ubiquitous Language in an explicitly Bounded Context”&lt;/p&gt;




&lt;p&gt;Resumindo, é conseguir modelar de forma explícita uma linguagem universal dentro de um contexto limitado do nosso domínio. Quando a linguagem muda, é sinal que já estamos em um contexto diferente de nossa aplicação. &lt;/p&gt;

&lt;h1&gt;
  
  
  Domínios, sub-domínios e contextos
&lt;/h1&gt;

&lt;p&gt;Pense na seguinte situação: está num quarto escuro com uma lanterna. De cara, não é possível enxergar o quarto todo. Porém, se formos iluminando uma parte do quarto de cada vez, poderemos “juntar os pedaços” em nossa cabeça e ter uma noção de como o quarto é.&lt;/p&gt;

&lt;p&gt;O mesmo acontece com o problema (domínio) que o software irá resolver. De cara, não temos noção do seu todo. Porém, se separarmos esse problema em problemas menores (subdomínios), poderemos juntar os pedaços para ter uma visão mais completa e criar uma solução.&lt;/p&gt;

&lt;p&gt;Neste sentido temos as seguintes divisões: Core, Support e Generic, explicadas na imagem a seguir:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi6fp3ttn23sjgiaxldzp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi6fp3ttn23sjgiaxldzp.png" alt="Image description" width="637" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Um ponto importante é que os softwares auxiliares são substituíveis, enquanto o ‘core’ é o que dá sentido a nossa aplicação - sem ele nosso projeto não existe.&lt;/p&gt;

&lt;p&gt;Podemos entender essa separação em domínios e subdomínios como a definição de nosso Problema. Em sequência, o que faremos é o molde da Solução. Neste sentido, a partir dos subdomínios observados iremos delimitar contextos a eles → cada contexto provavelmente acabará por virar subprodutos a serem desenvolvidos por nós, devs.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhyqq1c03jqie9qg40o0h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhyqq1c03jqie9qg40o0h.png" alt="Image description" width="611" height="273"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Em resumo, vemos o problema (domínio), o quebramos em subproblemas (subdomínios), e então criamos fronteiras explícitas para esses problemas menores (contextos) que farão parte de nossa solução. Mas como faremos essa delimitação?&lt;br&gt;
Bom, vamos analisar outra citação do Vernon:&lt;/p&gt;




&lt;p&gt;“A Bounded Context is an explicit boundary within which a domain model exists. Inside the boundary all terms and phrases of the Ubiquitous Language have specific meaning, and the model reflects the Language with exactness.”&lt;/p&gt;




&lt;p&gt;Com isso, podemos entender que uma das formas de definir essa fronteira é o uso da linguagem universal. Tudo que é específico daquele negócio, como as pessoas se comunicam e como os problemas são resolvidos possui uma terminologia → nesse caso geralmente todos estão dentro do mesmo contexto. Quando o linguajar começa a mudar, é indício que estamos cruzando a fronteira e entrando em um outro contexto. De forma simples, podemos identificar contextos diferentes quando:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Temos palavras iguais significando coisas diferentes → um “ticket” no Contexto de “Venda de Ingresso” é diferente de um “ticket” no Contexto de “Suporte ao Cliente”;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Temos palavras diferentes mas que significam a mesma coisa → ”cliente”, “freguês”, “usuário”, “comprador”;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agora ficou ainda mais claro do porque não conseguimos utilizar o DDD em sistemas simplórios → o contexto é tão pequeno que todo mundo já “fala a mesma língua”, sendo assim não tem tanto sentido fazer uma modelagem de domínio.&lt;/p&gt;

&lt;h1&gt;
  
  
  Elementos transversais
&lt;/h1&gt;

&lt;p&gt;Entendendo a importância dos Bounded Contexts, que irão determinar qual área da empresa estamos trabalhando e o problema que estamos resolvendo, podemos também entender que contextos diferentes muitas vezes acabam “conversando” entre si → poderemos ter elementos transversais, que estão em contextos diferentes porém com perspectivas diferentes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyj1yg407rsn4sxmr3zwm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyj1yg407rsn4sxmr3zwm.png" alt="Image description" width="779" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Aqui, o cliente é o mesmo, mas estão em contextos diferentes. Logo, para cada contexto teremos preocupações diversas (que poderão ser as propriedades de uma entidade Cliente), e isso é uma das coisas que mais gera confusão para os devs.  O que mais acontece nos dias de hoje é modelar um Cliente tentando atender as preocupações de diversos contextos diferentes → nossa entidade/classe Cliente acaba ficando enorme e confusa.&lt;/p&gt;

&lt;p&gt;Se tenho contextos diferentes, mesmo que a entidade seja a mesma, tenho que modelar ela de acordo com o contexto. Sendo assim, se estou em um monolito, e tenho uma área de suporte e outra de ingresso, ainda sim terei que criar entidades diferentes para representar esse Cliente.&lt;/p&gt;

&lt;p&gt;Sem toda essa delimitação a aplicação vai ficando um monstro. Se quisermos depois quebrá-la em microsserviços, por exemplo, teríamos bastante esforço de reescrita.&lt;/p&gt;

&lt;h1&gt;
  
  
  Context Mapping
&lt;/h1&gt;

&lt;p&gt;Agora vamos pra um lado mais prático. Temos que ter estratégias para trabalhar e organizar as comunicações entre os contextos e também entre os times da empresa para iniciar o desenvolvimento - o Context Mapping descreve exatamente as possíveis perspectivas para termos uma visão holística sobre essas relações. Neste sentido, temos alguns padrões a se utilizar:&lt;/p&gt;

&lt;h2&gt;
  
  
  Partnership (parceria)
&lt;/h2&gt;

&lt;p&gt;Contextos podem compartilhar e consumir apis entre si. Exemplo: contexto de venda de ingressos online e contexto de vendas de ingressos a partir de parceiros.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shared kernel
&lt;/h2&gt;

&lt;p&gt;Estes sistemas parceiros muitas vezes também podem ter um shared kernel. Exemplo: criar um sdk para ambos utilizarem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Customer-Supplier development - upstream/downstream
&lt;/h2&gt;

&lt;p&gt;Um contexto vai fornecer um serviço para o outro consumir e poder realizar seu negócio, ditando as regras dele. Exemplo: a venda de ingressos online (downstream) que consome um serviço do contexto de pagamentos (upstream).&lt;/p&gt;

&lt;h2&gt;
  
  
  Conformist
&lt;/h2&gt;

&lt;p&gt;Considerando que o contexto de pagamentos consuma uma gateway externa de cartão de crédito, ele terá que se conformar com as regras do serviço disponibilizado (a não ser que o cliente corresponda a uma grande parte dos lucros do fornecedor, nesse caso poderá ter algum poder de decisão).&lt;/p&gt;

&lt;h2&gt;
  
  
  Anti-corruption layer
&lt;/h2&gt;

&lt;p&gt;Quanto mais conformista a relação, mais vou acoplando os sistemas e ficando difícil de substituir. Logo, para evitar isso, podemos criar uma ACL - camada de interface que servirá como um adaptador entre nosso contexto e a gateway utilizada - irá minimizar o problema de conformidade.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open Host Service
&lt;/h2&gt;

&lt;p&gt;Um serviço (upstream) fornece um protocolo compartilhado que dá acesso aos seus subsistemas, como API Rest ou gRPC.&lt;/p&gt;

&lt;h2&gt;
  
  
  Published language
&lt;/h2&gt;

&lt;p&gt;A tradução entre os modelos de dois contextos delimitados precisa ter uma linguagem comum, bem documentada para expressar as informações de domínio necessárias. A “linguagem publicada” é frequentemente combinada com um serviço de host aberto (open host service).&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate ways
&lt;/h2&gt;

&lt;p&gt;Quando contextos não tem relações de comunicação, desenvolvedores podem encontrar soluções simples e especializadas dentro de cada escopo específico.&lt;/p&gt;

&lt;h2&gt;
  
  
  Big Ball of Mud
&lt;/h2&gt;

&lt;p&gt;Quando um sistema tem modelos misturados e limites inconsistentes - não podemos permitir que essa “bagunça” se propague para outros contextos delimitados. É uma demarcação da baixa qualidade de um modelo/sistema.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://github.com/ddd-crew/context-mapping?tab=readme-ov-file#context-mapping" rel="noopener noreferrer"&gt;https://github.com/ddd-crew/context-mapping?tab=readme-ov-file#context-mapping&lt;/a&gt;&lt;/p&gt;

</description>
      <category>learning</category>
      <category>ddd</category>
      <category>architecture</category>
      <category>contextmapping</category>
    </item>
    <item>
      <title>Arquitetura Hexagonal Explicada: como Transformar seu Desenvolvimento de Software</title>
      <dc:creator>Pedro Mafra</dc:creator>
      <pubDate>Sun, 16 Jun 2024 22:51:51 +0000</pubDate>
      <link>https://dev.to/pmafra/arquitetura-hexagonal-explicada-como-transformar-seu-desenvolvimento-de-software-43d9</link>
      <guid>https://dev.to/pmafra/arquitetura-hexagonal-explicada-como-transformar-seu-desenvolvimento-de-software-43d9</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Introdução&lt;/li&gt;
&lt;li&gt;Ciclo de um projeto&lt;/li&gt;
&lt;li&gt;Arquitetura vs Design de Software&lt;/li&gt;
&lt;li&gt;Arquitetura Hexagonal&lt;/li&gt;
&lt;li&gt;Hexagonal vs Clean vs Onion&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Introdução
&lt;/h1&gt;

&lt;p&gt;De forma geral, entende-se que a função de todo desenvolvedor é “resolver problemas utilizando o software como ferramenta”. Esta frase, apesar de simples, pode ser entendida a partir de duas vertentes: complexidade de negócio, envolvendo as regras para se resolver o problema; e a complexidade técnica, que é a tecnologia integrada ao negócio para fazê-lo funcionar.&lt;/p&gt;

&lt;p&gt;Muitas vezes, porém, o que observamos são aplicações tão intrinsecamente integradas de forma que não é mais possível destacar o que é complexidade de negócio e o que é a complexidade técnica.&lt;/p&gt;

&lt;p&gt;Considere o seguinte cenário: a Empresa X deseja rastrear eventos de usuários em seu aplicativo, como 'account_created', 'home_viewed', e 'payment_finished', e enviá-los para uma plataforma de CRM, Empresa Y, para construir perfis detalhados e aprimorar estratégias de marketing. Para isso, utilizam o SDK da Empresa Y com o método 'send_event', implementado em cada ponto do sistema onde ocorre um evento. Dois meses depois, com o aumento dos custos pelo uso do sistema da Empresa Y, a Empresa X opta por migrar para a Empresa Z. A substituição do SDK de Y pelo de Z seria um processo simples nesse caso?&lt;/p&gt;

&lt;p&gt;Podemos facilmente concluir que não. O código de Y ficou acoplado por todo o sistema, “sujando” a complexidade de negócio. Substituir a sua utilização seria um processo árduo e demorado.&lt;/p&gt;

&lt;p&gt;A arquitetura hexagonal, também chamada de “Ports and Adapters”, vem exatamente para impedir que isso aconteça. Nesta linha, podemos exemplificar alguns pontos importantes sobre uma arquitetura bem feita:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Crescimento sustentável: o software precisa ser escalável e possível de ser melhorado de forma simples, de forma que ao longo do tempo ele pague o seu próprio investimento;&lt;/li&gt;
&lt;li&gt;O Software deve ser desenhado por nós e não pelo framework - devemos mitigar o acoplamento entre complexidade técnica e de negócio;&lt;/li&gt;
&lt;li&gt;Possível de ser substituída sem muitos esforços&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Em outras palavras, podemos entender a arquitetura como o futuro de um software. &lt;/p&gt;

&lt;h1&gt;
  
  
  Ciclo de um projeto
&lt;/h1&gt;

&lt;p&gt;Ainda sim, muitas vezes, seja por falta de conhecimento sobre arquitetura, ou mudanças complexas de mercado, vemos um software crescer de uma maneira bem pouco sustentável. A seguir exemplifico o ciclo de vida de muitos projetos hoje em dia.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;Fase 1:&lt;/u&gt;&lt;/strong&gt;&lt;br&gt;
Nesta fase, o projeto é iniciado. Implementa-se o banco, cadastros, autenticação, servidor, views, controllers, etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;Fase 2:&lt;/u&gt;&lt;/strong&gt;&lt;br&gt;
Adiciona-se regras de negócio no cadastro, implementa-se uma ACL para autorização, adicionam-se logs, criação e consumo de APIs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;Fase 3:&lt;/u&gt;&lt;/strong&gt;&lt;br&gt;
Os acessos aumentam muito, escala-se horizontalmente a aplicação (upgrade de hardware), começamos a trabalhar com cache, consumir apis de terceiros e implementar regras de negócio de parceiros.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;Fase 4:&lt;/u&gt;&lt;/strong&gt;&lt;br&gt;
Mais acessos, mais upgrades, mais consultas ao banco que começam a gerar gargalos, implementa-se uma v2 da API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;Fase 5:&lt;/u&gt;&lt;/strong&gt;&lt;br&gt;
O software é escalado verticalmente, fazer uploads em multiplas máquinas (começamos a trabalhar com S3), muita refatoração para executar a escala vertical, criação de autoscaling, pipeline de CI/CD.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;Fase 6:&lt;/u&gt;&lt;/strong&gt;&lt;br&gt;
Começamos a utilizar graphQL para algumas APIs, começam a aparecer bugs em função da mudança nos formatos, problemas com logs em múltiplas máquinas - começa-se a pensar em algum sistema para centralização, cria-se integração com plataforma de CRM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;Fase 7:&lt;/u&gt;&lt;/strong&gt;&lt;br&gt;
Começamos a ter inconsistência dos dados de CRM, a pensar em conteinerizar nossa aplicação - precisa-se repensar o CI/CD, memória, logs, nos livrar de código legado.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;Fase 8:&lt;/u&gt;&lt;/strong&gt;&lt;br&gt;
Começamos a trabalhar com microsserviços, inicia-se compartilhando bancos, começamos a ter problemas de tracing, lentidão no sistema, custo fica elevado.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;Fase 9:&lt;/u&gt;&lt;/strong&gt;&lt;br&gt;
Não conseguimos mais trabalhar com containers e vamos para Kubernetes, temos que refazer o CI/CD novamente, começa-se a ter problemas de resiliência, começamos a trabalhar com mensageria sem ter muita experiência e começamos a perder mensagens, começa-se a contratar consultoras de software para auxiliar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;Fase 10:&lt;/u&gt;&lt;/strong&gt;&lt;br&gt;
Use a imaginação!&lt;/p&gt;




&lt;p&gt;A partir da análise dessas fases, podemos ver que um software não se perde do dia pra noite, mas sim um dia de cada vez. O sistema começa a ficar com cara de legado, com débitos técnicos que ninguém quer colocar a mão.&lt;br&gt;
A seguir listo algumas reflexões desse ciclo de vida apresentado:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faltou visão de futuro: não podemos ter a inocência de achar que um software sempre será simples/pequeno. Uma hora ele cresce;&lt;/li&gt;
&lt;li&gt;Má definição de limites: não houve uma separação clara entre o que é negócio e o que é framework, gerando um acoplamento e dificultando a troca e adição de componentes;&lt;/li&gt;
&lt;li&gt;Falta de preparação para escalamento: no início tudo está no mesmo servidor - cash, logs, upload. Porém, quando começamos escalar horizontalmente, e depois verticalmente, temos que refazer muita coisa. Logo, temos que pensar e nos preparar para escala desde o dia 1.&lt;/li&gt;
&lt;li&gt;Falta de limites para otimizações frequentes: a todo momento o software vai precisar de novas features com prazos apertados e, se não definirmos um limite aceitável, começaremos a criar e manter cada vez mais débitos técnicos;&lt;/li&gt;
&lt;li&gt;Incapaz de lidar com mudanças bruscas: ex.: empresa trocou a gateway de pagamento, ou de plataforma de CRM → conseguimos alterar facilmente a implementação?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Podemos ver que, se tivermos visão de futuro desde o dia 1, conseguimos criar camadas anti-corrupção para que as mudanças não afetem o negócio e não dificultem o nosso trabalho.&lt;/p&gt;

&lt;h1&gt;
  
  
  Arquitetura vs Design de Software
&lt;/h1&gt;

&lt;p&gt;É importante também salientar a diferença entre esses dois conceitos, muitas vezes considerados como a mesma coisa. A seguir segue uma definição que considero bem sucinta e completa, resumida do seguinte artigo: &lt;a href="https://eximia.co/quais-sao-as-diferencas-entre-arquitetura-e-design-de-software/" rel="noopener noreferrer"&gt;https://eximia.co/quais-sao-as-diferencas-entre-arquitetura-e-design-de-software/&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;“Atividades relacionadas a arquitetura de software são sempre de design. Entretanto, nem todas as atividades de design são sobre arquitetura. O objetivo primário da arquitetura de software é garantir que os atributos de qualidades, restrições de alto nível e os objetivos do negócio, sejam atendidos pelo sistema. Qualquer decisão de design que não tenha relação com este objetivo não é arquitetural. Todas as decisões de design para um componente que não sejam “visíveis” fora dele, geralmente, também não são.”&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Em outras palavras, podemos entender a arquitetura como aquilo faz entregarmos o software com qualidade, eficiência, e garantir que o negócio vai funcionar, algo mais abstrato. O Design seria como vamos fazer isso funcionar, algo mais concreto.&lt;/p&gt;

&lt;p&gt;Muitas decisões de design não têm a ver com a arquitetura, porém também podem impactar nas decisões arquiteturais. Segue um exemplo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Todos os sistemas terão que gerar logs e ficarem armazenados em um local” - &lt;strong&gt;visão arquitetural&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;“Para que isso seja possível, vamos fazer o log não ser gravado em arquivo e sim sair pelo terminal” - &lt;strong&gt;visão de design&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&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%2Fktrnq77voix6v6vxsxxd.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%2Fktrnq77voix6v6vxsxxd.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Arquitetura Hexagonal
&lt;/h1&gt;

&lt;p&gt;De acordo com Alistair Cockburn, podemos definir a Arquitetura Hexagonal da seguinte forma:&lt;/p&gt;




&lt;p&gt;&lt;em&gt;“Allow an application to equally be driven by users, programs, automated test or batch scripts, and to be developed and tested in isolation from its eventual run-time devices and databases.”&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Obs.:&lt;/strong&gt; fica a dica do artigo: &lt;a href="https://alistair.cockburn.us/hexagonal-architecture/" rel="noopener noreferrer"&gt;https://alistair.cockburn.us/hexagonal-architecture/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De forma sucinta, é basicamente criar software isolando a forma que pessoas e sistemas o acessam, e como ele acessa outros sistemas. Podemos entender melhor esse conceito a partir da seguinte imagem:&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%2F62i0w88qlwlmms0afg3p.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%2F62i0w88qlwlmms0afg3p.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Observando a imagem, temos o coração de nossa aplicação, o negócio, no centro do hexágono. Para haver a comunicação com objetos externos (tanto cliente quanto servidor abstraídos por seus respectivos adaptadores) criamos interfaces (ports), de forma a impedir que minha aplicação (negócio) fique diretamente interligada ao adaptador e vice-versa.&lt;/p&gt;

&lt;p&gt;É importante notar aqui que a forma de hexágono é apenas uma estrutura arbitrária para representar - poderia ser qualquer outro formato. A questão é que não queremos misturar o que é complexidade de negócio com a complexidade técnica. &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%2Fcvwl2b8ecmcxefvk4jyu.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%2Fcvwl2b8ecmcxefvk4jyu.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nesta linha, conseguimos componentizar a integração com os diversos objetos externos: logs, cache, banco, filas de mensagens, cliente (REST, gRPC, GraphQL), facilitando sua adição e substituição por meio dos “Ports” e “Adapters”.&lt;/p&gt;

&lt;p&gt;De forma mais prática, precisamos utilizar de um dos conceitos de SOLID - &lt;strong&gt;Princípio da Inversão de Dependência&lt;/strong&gt; - para atingir essa clareza:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Módulos de alto nível (negócio) não dependem de módulos de baixo nível (objetos externos), e sim ambos devem depender de abstrações.&lt;/li&gt;
&lt;li&gt;Abstrações não devem depender de detalhes e vice-versa.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O que fazemos aqui é uma inversão de controle. Por exemplo, se eu instanciar uma classe B dentro de outra classe A diretamente, estarei gerando um acoplamento. O que farei ao invés disso é recebê-la dentro do construtor. Porém, para evitar esse acoplamento entre as duas classes, devo receber uma interface no construtor de A, que representará B indiretamente.&lt;/p&gt;

&lt;p&gt;Todos esses conceitos mudam completamente a forma como desenvolvemos software de qualidade.&lt;/p&gt;

&lt;h1&gt;
  
  
  Hexagonal vs Clean vs Onion
&lt;/h1&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%2Fa1zbc5pcxjamho2ropva.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%2Fa1zbc5pcxjamho2ropva.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Por fim, podemos diferenciar esses conceitos muitas vezes confundidos. Na arquitetura hexagonal não há um padrão estabelecido de como o código deve ser organizado, quais camadas ou estruturas de pastas utilizar, diferentemente da Clean e Onion Architecture. Ela apenas define o princípio da separação entre o coração da aplicação e os objetos externos.&lt;/p&gt;

&lt;p&gt;Neste meio, não precisamos necessariamente implementar uma estrutura conhecida (Clean/Onion) contanto que sigamos alguma regra de organização seguindo a essência dos conceitos que falamos neste artigo. Mas é claro, implementar estruturas já estudadas e conhecidas com certeza facilita bastante o processo.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>systemdesign</category>
      <category>beginners</category>
      <category>learning</category>
    </item>
    <item>
      <title>Arquitetura de Microsserviços: um Guia para construir Sistemas Resilientes</title>
      <dc:creator>Pedro Mafra</dc:creator>
      <pubDate>Fri, 24 May 2024 03:43:57 +0000</pubDate>
      <link>https://dev.to/pmafra/arquitetura-de-microsservicos-2an</link>
      <guid>https://dev.to/pmafra/arquitetura-de-microsservicos-2an</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Introdução&lt;/li&gt;
&lt;li&gt;
Características por Martin Fowler

&lt;ul&gt;
&lt;li&gt;Componentização via serviços&lt;/li&gt;
&lt;li&gt;Organização através de áreas de negócio&lt;/li&gt;
&lt;li&gt;Produtos e não Projetos&lt;/li&gt;
&lt;li&gt;Smart endpoints e Dump Pipes&lt;/li&gt;
&lt;li&gt;Governança descentralizada&lt;/li&gt;
&lt;li&gt;Gerenciamento descentralizado de dados&lt;/li&gt;
&lt;li&gt;Automação de infraestrutura&lt;/li&gt;
&lt;li&gt;Desenhado para falhar&lt;/li&gt;
&lt;li&gt;Design Evolutivo&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Resiliência&lt;/li&gt;

&lt;li&gt;Coreografia vs Orquestração&lt;/li&gt;

&lt;li&gt;

Patterns

&lt;ul&gt;
&lt;li&gt;API-Composition&lt;/li&gt;
&lt;li&gt;Decompose By Business Capability&lt;/li&gt;
&lt;li&gt;Strangler Application&lt;/li&gt;
&lt;li&gt;ACL - Anti-Corruption Layer&lt;/li&gt;
&lt;li&gt;API-Gateway&lt;/li&gt;
&lt;li&gt;BFF - Backend For Frontend&lt;/li&gt;
&lt;li&gt;Relatórios e Consolidação de Informações&lt;/li&gt;
&lt;li&gt;Transactional Outbox&lt;/li&gt;
&lt;li&gt;Secret Manager / Vault&lt;/li&gt;
&lt;li&gt;Padronização de Logs&lt;/li&gt;
&lt;li&gt;OTEL - Open Telemetry&lt;/li&gt;
&lt;li&gt;Service Template&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;



&lt;h1&gt;
  
  
  Introdução
&lt;/h1&gt;

&lt;p&gt;Talvez você já ouviu falar de microsserviços em algum lugar e ainda não sabe exatamente o que é, ou talvez queira apenas relembrar as principais características da arquitetura e implementação. Este artigo é para você!&lt;/p&gt;

&lt;p&gt;Primeiro de tudo, o que são? Como já diz o próprio nome, é um serviço ‘micro’, mas vai muito além disso. Um microsserviço (MS) é uma aplicação como outra qualquer, em qualquer linguagem, porém possui um escopo e responsabilidade delineada, fazendo parte de um ecossistema maior. Quando não faz parte, é possível que seja apenas um monolito pequeno.&lt;br&gt;
Mas e um monolito, o que é exatamente? 🤔&lt;/p&gt;

&lt;p&gt;Para tudo ficar mais claro, podemos diferenciar um monolito de um microsserviço de forma simples:&lt;/p&gt;

&lt;p&gt;&lt;u&gt;Monolito:&lt;/u&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Serviço que engloba todo um ecossistema, todos (ou quase todos) os domínios da aplicação&lt;/li&gt;
&lt;li&gt;Atualizações podem impactar diferentes domínios ao mesmo tempo&lt;/li&gt;
&lt;li&gt;Geralmente feito todo em uma mesma linguagem&lt;/li&gt;
&lt;li&gt;Mais difícil de escalar e separar times&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;u&gt;Microsserviço:&lt;/u&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Serviço que representa um domínio específico da aplicação, e que faz parte de um ecossistema maior&lt;/li&gt;
&lt;li&gt;São serviços independentes, logo possuem deploy independente, banco de dados independente, e apresentam menos riscos de impactar todo o sistema caso haja algum tipo de problema&lt;/li&gt;
&lt;li&gt;Podem ser realizados cada um em uma tecnologia diferente, para obtenção de performance por exemplo&lt;/li&gt;
&lt;li&gt;São mais facilmente divididos entre times&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Tudo bem, mas então porque vou querer utilizar monolitos? Bom, como em nossa área sabemos que não existe bala de prata, podemos entender algumas situações já conhecidas em que trabalhar com um ou outro traz maiores vantagens. Então se liga nesses 2 próximos parágrafos:&lt;/p&gt;




&lt;p&gt;Começando pelos &lt;strong&gt;&lt;u&gt;monolitos&lt;/u&gt;&lt;/strong&gt;, geralmente são muito vantajosos quando vamos iniciar uma nova ideia de um projeto. Nesses casos raramente temos de cara todo o conhecimento dos domínios e escopos, sem falar nas possíveis mudanças de mercado e de clientes, que impactam diretamente neste delineamento de responsabilidades. Por isso são também são muito vantajosos para POCs (provas de conceito).&lt;br&gt;
Outro ponto é quando queremos uma governança simplificada: é muito mais simples se trabalhar com apenas uma tecnologia, contratar novos profissionais e introduzi-los ao projeto, principalmente devs mais iniciantes, que não conhecem muitas linguagens, comunicação assíncrona, etc.&lt;br&gt;
Além disso, temos um shared kernel, ou seja, um compartilhamento claro de libs dentro do mesmo codebase. Usando MS geralmente vamos ter um repo separado para bibliotecas, porém manter a compatibilidade de versões será muito mais complicado.&lt;/p&gt;

&lt;p&gt;Já engatando para os &lt;strong&gt;&lt;u&gt;microsserviços&lt;/u&gt;&lt;/strong&gt;, começam a ser vantajosos quando temos contextos e áreas de negócio bem definidas em nossa aplicação. Se queremos escalar/separar melhor times, trabalhar com alguma tech específica para obter performance, e temos maturidade nos processos de entrega (time de plataformas, templates para criação de novos repos do zero, maturidade técnica dos times, etc.) são bons indícios para começarmos a trabalhar com MS.&lt;br&gt;
Além disso, se queremos escalar apenas uma parte de nosso sistema, nada impede que comecemos extraindo apenas esta parte que já está mais madura para funcionar como um serviço separado.&lt;/p&gt;




&lt;p&gt;Podemos concluir aqui que nem um nem outro é o certo, depende da situação, se ligou?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3h8hdgh8bc0fiwzkc20d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3h8hdgh8bc0fiwzkc20d.png" alt="Image description" width="680" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Porém, também é importante salientar que o processo de migração de monolito para arquitetura de microsserviços não é algo simples, e temos que nos atentar em diversos pontos deste processo. Alguns deles listei abaixo e você pode usar como um checkbox caso precise:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Separar bem os domínios/contextos da aplicação - Domain Driven Design&lt;/li&gt;
&lt;li&gt;Evitar excesso de granularidade - “nanosserviços”&lt;/li&gt;
&lt;li&gt;Verificar dependências - um MS não pode depender de outro, um “monolito distribuído” é o pior dos casos&lt;/li&gt;
&lt;li&gt;Planejar processo de migração de banco - para simplificar, podemos começar criando o MS utilizando um mesmo banco, e posteriormente migrar o banco - aqui não podemos ter medo extremo de duplicação de dados&lt;/li&gt;
&lt;li&gt;Começar a pensar em comunicação assíncrona - arquitetura baseada em eventos (Event Driven Design)&lt;/li&gt;
&lt;li&gt;Lembrar que com MS teremos consistência eventual dos dados&lt;/li&gt;
&lt;li&gt;Precisamos de maturidade para trabalhar com CI/CD, testes,rate limiting, autenticação, etc.&lt;/li&gt;
&lt;li&gt;Começar pelas beiradas é uma boa opção - “Strangler Pattern” - ir quebrando as partes periféricas do serviço principal em MS, até chegar nas partes principais&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ainda vamos expandir melhor alguns desses pontos nos próximos tópicos, então fica tranquilo. 😉&lt;/p&gt;

&lt;h1&gt;
  
  
  Características por Martin Fowler
&lt;/h1&gt;

&lt;p&gt;Agora vamos mapear bem resumidamente as principais características de um Microsserviço de acordo com o seguinte artigo &lt;a href="https://martinfowler.com/articles/microservices.html" rel="noopener noreferrer"&gt;https://martinfowler.com/articles/microservices.html&lt;/a&gt; escrito por Martin Fowler:&lt;/p&gt;

&lt;h3&gt;
  
  
  Componentização via serviços
&lt;/h3&gt;

&lt;p&gt;Microsserviços são serviços “out of process”, diferentemente de bibliotecas que são componentes “in memory”. Sendo assim, são separados do processo principal da aplicação que está rodando, e independentemente “deployaveis”.&lt;/p&gt;

&lt;h3&gt;
  
  
  Organização através de áreas de negócio
&lt;/h3&gt;

&lt;p&gt;Em microsserviços, estamos pensando menos em divisões de funções da empresa, e mais nas divisões de áreas de negócio da empresa.&lt;/p&gt;

&lt;h3&gt;
  
  
  Produtos e não Projetos
&lt;/h3&gt;

&lt;p&gt;Um projeto tem início, meio e fim. A ideia aqui é tratar o software como produto e ter um time “owner” que irá mantê-lo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Smart endpoints e Dump Pipes
&lt;/h3&gt;

&lt;p&gt;Os canais para comunicação com os MS não devem ter regras - devem sair de um jeito e chegar do mesmo jeito (o “pipe” deve ser “dumb”). Caso contrário, estaremos gerando um acoplamento de nossa aplicação.&lt;/p&gt;

&lt;h3&gt;
  
  
  Governança descentralizada
&lt;/h3&gt;

&lt;p&gt;Eventualmente precisaremos de soluções diferentes para resolver certos problemas - os MS resolvem este problema de padronização. Uma vez que poderemos ter tecnologias diferentes, temos que ter uma comunicação que funcione bem (“Consumer Driven Contract”), sempre com um contrato muito claro e pré-definido.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gerenciamento descentralizado de dados
&lt;/h3&gt;

&lt;p&gt;Em MS, teremos vários bancos separados e autônomos - não garantiremos a consistência das informações 100% do tempo, ou seja, teremos duplicações e delays nas sincronizações.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automação de infraestrutura
&lt;/h3&gt;

&lt;p&gt;Em monolitos, temos uma esteira de CI, testes, segurança, deploy, etc., mas em MS, precisamos de vários. Sendo assim, vem a tona a necessidade de uma automação de infra, time de plataformas, criação de templates, para facilitar este processo. Além disso, se não temos uma automação, a falta de padronização entre os MS tornará as manutenções mais complicadas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Desenhado para falhar
&lt;/h3&gt;

&lt;p&gt;Desde o dia zero, precisamos pensar em Resiliência, que será o próximo tópico deste artigo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Design Evolutivo
&lt;/h3&gt;

&lt;p&gt;Precisamos criar aplicações independentes e possíveis de substituição. Se precisamos de mais de um MS para substituir uma feature, é sinal que existe uma dependência entre eles e talvez possam ser agrupados em apenas um.&lt;/p&gt;




&lt;p&gt;Acho que de características estamos bem acertados né? Caso tenha alguma dúvida em relação a algum dos tópicos, fica a sugestão para fazer a leitura completa do artigo linkado acima.&lt;/p&gt;

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

&lt;h1&gt;
  
  
  Resiliência
&lt;/h1&gt;

&lt;p&gt;Continuando, uma das questões cruciais quando falamos de microsserviços é a Resiliência. Mas o que é isso?&lt;br&gt;
Bom, em nosso meio, pode ser entendida como um conjunto de estratégias adotadas intencionalmente para a adaptação de um sistema quando uma falha ocorre.&lt;/p&gt;

&lt;p&gt;Em algum momento todo sistema irá falhar, e precisamos estar preparados a isso. Nessa vertente, é muito melhor que as estratégias sejam mais “consistentes” do que “perfeitas”.&lt;br&gt;
Como exemplo, é melhor que respondamos a uma requisição em 500 ms sempre, não importando se recebemos 1 ou 1 milhão de requisições. Caso a resposta ultrapasse seu tempo, precisaríamos começar a barrar requisições. Em MS muitas vezes é pior um sistema lento que um fora do ar, pois essa lentidão inesperada pode causar um efeito dominó em todos os outros sistemas envolvidos.&lt;/p&gt;

&lt;p&gt;De forma geral, podemos listar alguns mecanismos de resiliência mais conhecidos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Health checks:&lt;/strong&gt; observar os sinais vitais do sistema como garantia de sua saúde. Podemos realizar de forma ativa, a partir do próprio serviço, ou passiva, com a verificação a partir de um consumer por exemplo;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate limiting:&lt;/strong&gt; limitar as requisições de um sistema para não afetar sua qualidade. Aqui, temos que nos basear no cliente estratégico que irá utilizar nosso sistema e em suas demandas;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Circuit Breaker:&lt;/strong&gt; ter uma forma de impedir novas requisições de forma simples pode se demonstrar crucial para proteger o sistema;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Comunicação assíncrona:&lt;/strong&gt; conseguimos evitar a perda de dados e falhas em cadeia caso algum sistema saia do ar, por exemplo implementando um padrão outbox com registros temporários. Exemplos de serviços de mensageria: Kafka, SQS, etc;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retry:&lt;/strong&gt; aqui podemos falar sobre backoff exponencial e com Jitter. Recomendo assistir o seguinte vídeo: &lt;a href="https://www.youtube.com/watch?v=1MkPpKPyBps" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=1MkPpKPyBps&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observabilidade:&lt;/strong&gt; APM, tracing, métricas personalizadas, OpenTelemetry;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Autenticação:&lt;/strong&gt; acho que é claro para todos a necessidade de autenticar as requisições de um sistema.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inclusive, mesmo trabalhando-se com comunicação assíncrona, ainda temos que pensar nas possibilidades de nosso sistema de mensageria não funcionar. E aí? Neste caso como podemos garantir alguma resiliência? &lt;br&gt;
Poderíamos pensar em trabalhar por exemplo com o Padrão Outbox, criando tabelas com registros temporários no banco. Mas, além disso, temos que nos preocupar também com garantias de entrega e recebimento, idempotência, políticas de fallback, e em documentar todos estes pontos de nosso sistema.&lt;/p&gt;

&lt;p&gt;Acho que até aqui ficou bem claro que depender de implementações do zero a todo momento em que vamos criar um novo microsserviço acaba se tornando inviável e muito trabalhoso. Por isso, hoje em dia são muito utilizadas ferramentas como API Gateway e Service Mesh para abstrair essas implementações de resiliência e facilitarmos o processo de comunicação e entrega.&lt;/p&gt;

&lt;p&gt;Porém, não é do dia para noite que conseguiremos cobrir todos esses pontos, é sempre um processo de amadurecimento - precisamos mapeá-los e ir atacando-os a um a partir de nossas prioridades.&lt;/p&gt;

&lt;h1&gt;
  
  
  Coreografia vs Orquestração
&lt;/h1&gt;

&lt;p&gt;Basicamente existem duas formas de comunicação entre MS - coreografia e orquestração.&lt;br&gt;
Em uma coreografia, as comunicações são mais descentralizadas, acontecendo de forma mais independente. Na orquestração, temos um “maestro”, um serviço que irá coordenar como a orquestra irá fluir.&lt;/p&gt;

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

&lt;p&gt;Então vamos diferenciá-los:&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Comunicação decentralizada, baseada em eventos;&lt;/li&gt;
&lt;li&gt;Serviços mais independentes entre si, mais facilmente substituíveis, tornando o sistema mais escalável.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Em contrapartida, apresentam maior complexidade de manutenção, monitoramento e solução de problemas.&lt;/p&gt;

&lt;p&gt;Podemos listar alguns casos em que se é bom trabalhar com Coreografia:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quando todo processo pode se basear no input inicial sem precisar de mais contexto (passos condicionais intermediários);&lt;/li&gt;
&lt;li&gt;Quando temos um fluxo com uma direção clara e única.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Comunicação mais centralizada, baseada em comandos;&lt;/li&gt;
&lt;li&gt;Orquestrador dita a sequência de comunicações que os MS devem seguir, também definindo políticas de fallback;&lt;/li&gt;
&lt;li&gt;Mais simples de monitorar e solucionar problemas, pois sabemos onde olhar quando algo da errado.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Em contrapartida, gera acoplamento entre os serviços, dificultando adicionar, remover ou substituí-los. A falha de um pode ser a falha de outros.&lt;/p&gt;

&lt;p&gt;Podemos listar alguns casos em que se é bom trabalhar com Orquestração:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quando temos passos condicionais que trigarão fluxos diferentes, como por exemplo confirmação de pagamento de cartão de crédito;&lt;/li&gt;
&lt;li&gt;Quando precisamos centralizar o monitoramento do fluxo.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;E novamente voltamos ao mesmo ditado: não existe bala de prata. Dependendo do caso, um ou outro pode ter seus benefícios, o importante aqui é implementar alguma estratégia de comunicação. Caso contrário, podemos gerar um Anti-Pattern conhecido, a "Estrela da Morte", quando as comunicações ficam tão descentralizadas e interdependentes que podemos perder o controle da comunicação da rede.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn2aq46w2ebvwo19mirah.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn2aq46w2ebvwo19mirah.png" alt="Image description" width="764" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Em outras palavras, se sua empresa está implementando MS sem parar, e mais importante, sem um componente de mediação na arquitetura, é apenas uma questão de tempo até a "Estrela da Morte" aparecer pra você.&lt;/p&gt;

&lt;p&gt;Sendo assim, já podemos pensar aqui em estratégias de mitigação - Resiliência - para evitar que isso aconteça. Por exemplo, a utilização de API Gateways como intermediários para comunicação entre os MS é uma maneira eficiente para conseguirmos manter um controle maior das chamadas, pois elas passarão a acontecer entre contextos, e MS de contextos diferentes não terão ideia de qual MS estará se comunicando do outro lado.&lt;br&gt;
Inclusive, assim como já dito anteriormente, poderemos mais facilmente definir rate limiting, circuit breakers, autenticação, e outros mecanismos de resiliência diretamente em nosso API Gateway.&lt;/p&gt;

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

&lt;p&gt;E, assim como em nossas aplicações, podemos seguir práticas de DDD e dividir nossos Gateways de acordo com os Bounded Contexts, aumentando ainda mais o controle sobre nosso sistema. Mas falaremos um pouco mais sobre isso já já.&lt;/p&gt;

&lt;h1&gt;
  
  
  Patterns
&lt;/h1&gt;

&lt;p&gt;Categorizações finalizadas, agora podemos focar um pouco em alguns padrões comumente usados nos dias de hoje numa arquitetura de microsserviços.&lt;/p&gt;

&lt;h3&gt;
  
  
  API-Composition
&lt;/h3&gt;

&lt;p&gt;Pense no caso: quero gerar um relatório, mas metade dos dados está em um microsserviço e metade em outro, o que fazer? Neste caso podemos utilizar criar um Service Composer para fazer chamadas a esses MS e realizar a composição e transformação dos dados de acordo com as regras de negócio.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmd0oc90bwgkwike194c6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmd0oc90bwgkwike194c6.png" alt="Image description" width="551" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Decompose By Business Capability
&lt;/h3&gt;

&lt;p&gt;Supondo que queremos decompor um monolito em n microsserviços por x razões, como começar este processo? Bom, uma ideia inicial é buscar decompor nosso sistema por áreas de negócio (Bounded Contexts). Utilizar o DDD para visualizar nossa aplicação e separá-la em domínios, subdomínios, subcontextos, etc. Porém, ainda sim não é uma tarefa simples - existem muitas áreas cinzentas de intersecção.&lt;br&gt;
Para facilitar o processo, podemos utilizar uma ferramenta do DDD: Context Mapping. Caso queria ler mais sobre, recomendo este link: &lt;a href="https://www.infoq.com/articles/ddd-contextmapping/" rel="noopener noreferrer"&gt;https://www.infoq.com/articles/ddd-contextmapping/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Strangler Application
&lt;/h3&gt;

&lt;p&gt;Ainda falando em decomposição, podemos nos utilizar do "Strangler Pattern" para começar a trabalhar com MS, basicamente seguindo duas regras:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Toda nova feature será transformada em um MS&lt;/li&gt;
&lt;li&gt;Pegar pequenos pedaços do monolito e transformar em MS&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Porém, esta quebra vai sendo feita aos poucos - o monolito continua existindo e vai reduzindo cada vez mais, até que se torne apenas mais um pedaço da aplicação. Além disso, temos que lembrar dos pontos de atenção mencionados no início deste artigo para realizar esta migração.&lt;/p&gt;

&lt;h3&gt;
  
  
  API-Gateway
&lt;/h3&gt;

&lt;p&gt;Como já dito anteriormente, o API Gateway irá redirecionar as requisições aos serviços, funcionando como uma porta de entrada única e fornecendo soluções para rate limiting, transformações nas mensagens, autenticação, health checks, etc. Também podemos trabalhar com API Gateways divididos por áreas de neǵocio, melhorando ainda mais o controle de nosso sistema.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  ACL - Anti-Corruption Layer
&lt;/h3&gt;

&lt;p&gt;Podemos inclusive criar um novo serviço para servir como um “proxy” - por exemplo, criar uma interface de pagamentos que irá abstrair qual gateway de pagamento será chamado, de forma a não impactar diretamente o MS consumidor em caso de mudanças. Além disso, mais que um proxy, este ACL pode também encapsular regras de negócio, como por exemplo, fazendo a escolha de um gateway de pagamento de cartão de crédito de acordo com a bandeira escolhida.&lt;br&gt;
O objetivo aqui é impedir a necessidade (ou intrusão) de um domínio conhecer os detalhes do outro.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  BFF - Backend For Frontend
&lt;/h3&gt;

&lt;p&gt;Temos que levar em consideração que, dependendo do cliente, precisaremos de retornos de API diferentes de acordo com cada demanda. Nessa linha, podemos implementar BFFs, que segregam nossos backends por tipo de cliente, retornando apenas as infos que aquele cliente em específico irá utilizar.&lt;/p&gt;

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

&lt;p&gt;Podemos, alternativamente, utilizar GraphQL como uma maneira de substituir o uso de BFFs, garantindo ao client o poder de escolha dos dados a serem retornados.&lt;/p&gt;

&lt;h3&gt;
  
  
  Relatórios e Consolidação de Informações
&lt;/h3&gt;

&lt;p&gt;Quando vamos trabalhar com microsserviços, muitas vezes queremos obter dados espalhados por diversos bancos para retornar em uma requisição, como por exemplo na geração de um relatório de extrato bancário. Nesta linha, é importante também falar sobre &lt;strong&gt;tabelas de projeção&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Exemplo: quero gerar o relatório X, obtendo nome, email e telefone contidos no MS 1, o saldo do MS 2, e empréstimos realizados do MS 3. Com isso, posso pensar na criação de uma tabela no banco de um outro MS 4 exatamente com esta estrutura:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4d7y39ci8o96vciho69h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4d7y39ci8o96vciho69h.png" alt="Image description" width="444" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora, posso fazer cada MS se comunicar e atualizar continuamente os registros dessa tabela quando sofrerem modificações:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cada vez que o dado de um MS mudar, ele mesmo atualiza no seu banco e na tabela do banco do MS 4;&lt;/li&gt;
&lt;li&gt;O próprio MS 4 escuta eventos de alteração gerados pelos outros MS em um message broker e então atualiza sua tabela.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Em ambos teremos consistência eventual, que como já dito é algo comum ao se trabalhar numa arquitetura de microsserviços.&lt;/p&gt;

&lt;h3&gt;
  
  
  Transactional Outbox
&lt;/h3&gt;

&lt;p&gt;Assim como brevemente comentado anteriormente, podemos ver o "transactional outbox" como um padrão de resiliência. Neste pattern, persistimos temporariamente nossos dados em uma tabela &lt;em&gt;outbox&lt;/em&gt; de forma a não perdê-los caso algum sistema saia do ar.&lt;/p&gt;

&lt;p&gt;&lt;u&gt;Exemplo:&lt;/u&gt; um MS 1 faz uma requisição http a um MS 2, ou mesmo posta eventos em um sistema de mensageria, como o RabbitMQ. Para evitarmos perder esses eventos caso haja algum problema em nosso MS 2 ou no message broker, guardamos os dados na tabela &lt;u&gt;outbox&lt;/u&gt;. Após o sucesso do envio, o MS 1 deleta os dados dessa tabela.&lt;br&gt;
Assim, de tempos em tempos o MS 1 ficará lendo a tabela e mandando as transações perdidas novamente para o seu destino. Além disso, é importante que estes dados não se misturem com a base principal e, para evitar isso, podemos por exemplo implementar um sdk interno que trabalhará com retries e guardará os dados na tabela em caso de falha.&lt;/p&gt;

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

&lt;p&gt;É claro, porém, que para casos que necessitam de uma resposta imediata, não poderemos aplicar este padrão.&lt;/p&gt;

&lt;h3&gt;
  
  
  Secret Manager / Vault
&lt;/h3&gt;

&lt;p&gt;Como fazemos para rotacionar diversas credenciais de diversos microsserviços e controlar tudo isso? Aqui podemos trabalhar com o Vault, que nada mais é do que uma solução da Hashicorp que armazena nossas credenciais e facilita este processo. Podemos por exemplo criar webhooks a serem chamados quando o Vault identifica as datas limites que setamos para nossas secrets.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqzlg7vfxrbzv6b5k8eki.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqzlg7vfxrbzv6b5k8eki.png" alt="Image description" width="710" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Padronização de Logs
&lt;/h3&gt;

&lt;p&gt;Em observabilidade, temos 3 vertentes básicas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Logs&lt;/li&gt;
&lt;li&gt;Métricas&lt;/li&gt;
&lt;li&gt;Tracing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O log é o resultado de um evento. Se um erro estoura para nosso cliente, podemos ir procurando o log por nossas VMs. Porém, muitas vezes a VM do log pode até já ter sido destruída por conta de mecanismos de autoscaling por exemplo. Para evitar problemas e facilitar a observabilidade, podemos centralizar os logs por exemplo no ElasticSearch.&lt;br&gt;
Além disso, temos que nos preocupar com a padronização: imagine diversos microsserviços, cada um com sua estrutura própria de logs, dificultaria muito fazer buscas né?. Nesse sentido, podemos criar um SDK que realizará uma padronização dos logs dos sistemas de nossa empresa por exemplo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99s9075klvg3marldic9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99s9075klvg3marldic9.png" alt="Image description" width="794" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  OTEL - Open Telemetry
&lt;/h3&gt;

&lt;p&gt;Se recebemos um erro 500 em alguma requisição, que por sua vez envolve a comunicação de 3 microsserviços diferentes, como saber onde aconteceu? Aqui entra o conceito de tracing distribuído, que nos dá exatamente essa visibilidade.&lt;br&gt;
Agora, vamos supor que fazemos o tracing utilizando o serviço do New Relic, mas depois queremos mudar para Datadog, depois para o Elastic - isso acaba gerando uma grande esforço "braçal". De forma a não ficarmos presos em nosso ‘vendor’, entra a ferramenta do &lt;strong&gt;OpenTelemetry&lt;/strong&gt;, que disponibiliza um ‘collector’ para nossos serviços enviarem os dados, e consegue fazer a distribuição para o serviço especificado.&lt;/p&gt;

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

&lt;p&gt;Com isso, temos maior segurança, descentralização e padronização dos dados de observabilidade que uma aplicação gera (logs, métricas e tracing).&lt;/p&gt;

&lt;h3&gt;
  
  
  Service Template
&lt;/h3&gt;

&lt;p&gt;Por fim, mas não menos importante, o Service Template, algo que é muito utilizado e continuará sendo. Basicamente, é um modelo definido por nossa empresa com padrões de implementação para logs, outbox, passwords, comunicação com sistemas de mensageria, observabilidade, CQRS, múltiplos bancos, auditoria, jobs, etc. - em outras palavras, um “kit de desenvolvimento”.&lt;br&gt;
Porém, para se ter algo assim, é muito imporante também um time de plataforma e sustenção para auxiliar na manutenção e aplicação destes padrões, ou seja, torna-se necessário uma certa maturação da empresa em si.&lt;/p&gt;

&lt;p&gt;Em uma arquitetura de microsserviços, caso não tenhamos um service template, os devs irão demorar muito mais para criar novos serviços, pois sempre terão que configurar tudo do zero.&lt;/p&gt;




&lt;p&gt;Bom, acredito que com todos estes tópicos em mente já consiga ter um bom ponto de partida para decidir os melhores padrões para seu sistema ou ao menos para ter uma visão geral do que estudar em seguida.&lt;/p&gt;

&lt;p&gt;Obrigado pela leitura!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7keaj5nims8ycofehenk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7keaj5nims8ycofehenk.png" alt="Image description" width="593" height="578"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>architecture</category>
      <category>learning</category>
      <category>backend</category>
    </item>
  </channel>
</rss>
