<?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: Humberto Barbosa</title>
    <description>The latest articles on DEV Community by Humberto Barbosa (@h1bertobarbosa).</description>
    <link>https://dev.to/h1bertobarbosa</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%2F468935%2F572d1e0f-6e19-4f3b-aaf8-a8707ce9b85b.png</url>
      <title>DEV Community: Humberto Barbosa</title>
      <link>https://dev.to/h1bertobarbosa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/h1bertobarbosa"/>
    <language>en</language>
    <item>
      <title>Promises em Nodejs Paralelo, Sequencial e Corrida – Qual usar?</title>
      <dc:creator>Humberto Barbosa</dc:creator>
      <pubDate>Sat, 19 Jul 2025 00:41:07 +0000</pubDate>
      <link>https://dev.to/h1bertobarbosa/promises-em-nodejs-paralelo-sequencial-e-corrida-qual-usar-1g3g</link>
      <guid>https://dev.to/h1bertobarbosa/promises-em-nodejs-paralelo-sequencial-e-corrida-qual-usar-1g3g</guid>
      <description>&lt;h1&gt;
  
  
  Promises em Node.js: Paralelo, Sequencial e Corrida – Como Escolher?
&lt;/h1&gt;

&lt;p&gt;Em JavaScript (e especialmente no Node.js), &lt;strong&gt;Promises&lt;/strong&gt; são uma das ferramentas mais poderosas para trabalhar com &lt;strong&gt;código assíncrono&lt;/strong&gt; — aquele que não bloqueia o fluxo principal enquanto espera por uma resposta, como uma chamada de API ou leitura de arquivo.&lt;/p&gt;

&lt;p&gt;Mas… quando você tem &lt;strong&gt;várias Promises ao mesmo tempo&lt;/strong&gt;, como decidir a melhor forma de executá-las?&lt;/p&gt;

&lt;p&gt;Neste artigo, vamos explorar os três padrões mais importantes para isso:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Execução Paralela&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Execução Sequencial&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Corrida (Race Condition)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;E sim, vou te mostrar com &lt;strong&gt;exemplos práticos e simples&lt;/strong&gt; como isso funciona.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Antes de tudo: o que é uma Promise?
&lt;/h2&gt;

&lt;p&gt;Uma &lt;em&gt;Promise&lt;/em&gt; é um objeto que representa a eventual conclusão (ou falha) de uma operação assíncrona. Em outras palavras, ela &lt;strong&gt;promete&lt;/strong&gt; que vai te dar um resultado.&lt;/p&gt;

&lt;p&gt;Você pode "esperar" por esse resultado com &lt;code&gt;await&lt;/code&gt;, ou então usar &lt;code&gt;.then()&lt;/code&gt; e &lt;code&gt;.catch()&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 Função base para nosso exercício
&lt;/h2&gt;

&lt;p&gt;Vamos criar uma função que simula uma tarefa assíncrona com um &lt;code&gt;setTimeout&lt;/code&gt;. Ela simplesmente "resolve" com um valor depois de um tempo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;promiseWithDelay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Valor: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, Delay: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;ms`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exemplo de uso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;promiseWithDelay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="c1"&gt;// → Valor: A, Delay: 3000ms (após 3 segundos)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🟩 Execução Paralela (Parallel)
&lt;/h2&gt;

&lt;p&gt;Quando queremos executar &lt;strong&gt;várias Promises ao mesmo tempo&lt;/strong&gt; e esperar todas terminarem juntas, usamos &lt;code&gt;Promise.all()&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Exemplo:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;executarParalelo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resultados&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nf"&gt;promiseWithDelay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;promiseWithDelay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;promiseWithDelay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;C&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Execução Paralela Finalizada:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resultados&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  O que acontece aqui?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;As três Promises são iniciadas &lt;strong&gt;ao mesmo tempo&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A função espera &lt;strong&gt;todas&lt;/strong&gt; terminarem&lt;/li&gt;
&lt;li&gt;O tempo total é do item &lt;strong&gt;mais lento&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Resultado:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;espera 5 segundos&lt;span class="o"&gt;)&lt;/span&gt;
Execução Paralela Finalizada: &lt;span class="o"&gt;[&lt;/span&gt;
  &lt;span class="s1"&gt;'Valor: A, Delay: 1000ms'&lt;/span&gt;,
  &lt;span class="s1"&gt;'Valor: B, Delay: 5000ms'&lt;/span&gt;,
  &lt;span class="s1"&gt;'Valor: C, Delay: 3000ms'&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Execução Sequencial (Sequential)
&lt;/h2&gt;

&lt;p&gt;Às vezes, você quer rodar Promises &lt;strong&gt;em ordem&lt;/strong&gt;, uma de cada vez. Isso é útil quando o segundo depende do resultado do primeiro.&lt;/p&gt;

&lt;h3&gt;
  
  
  Exemplo:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;executarSequencial&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resultado1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;promiseWithDelay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resultado2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;promiseWithDelay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resultado3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;promiseWithDelay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;C&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Execução Sequencial Finalizada:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;resultado1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;resultado2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;resultado3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  O que acontece?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Espera o primeiro terminar (&lt;code&gt;A&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Só então executa o segundo (&lt;code&gt;B&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Depois, o terceiro (&lt;code&gt;C&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;O tempo total = &lt;strong&gt;soma dos delays&lt;/strong&gt; (9 segundos neste caso)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Corrida (Race)
&lt;/h2&gt;

&lt;p&gt;E se você quiser &lt;strong&gt;só o primeiro resultado que chegar&lt;/strong&gt; e ignorar o resto? Use &lt;code&gt;Promise.race()&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Exemplo:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;executarCorrida&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resultado&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;race&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nf"&gt;promiseWithDelay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;promiseWithDelay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;promiseWithDelay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;C&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Corrida Finalizada. Vencedor:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resultado&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Resultado:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;espera 1 segundo&lt;span class="o"&gt;)&lt;/span&gt;
Corrida Finalizada. Vencedor: Valor: A, Delay: 1000ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quem chegar primeiro, ganha. Simples assim!&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Testando os três modos
&lt;/h2&gt;

&lt;p&gt;Vamos chamar os três juntos e ver o comportamento:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;testarTodos&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;executarCorrida&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;executarParalelo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;executarSequencial&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;testarTodos&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mesmo sendo chamados na mesma ordem, a &lt;strong&gt;corrida&lt;/strong&gt; terminará primeiro, seguida da &lt;strong&gt;execução paralela&lt;/strong&gt;, e por último a &lt;strong&gt;sequencial&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quando usar cada um?
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Caso real&lt;/th&gt;
&lt;th&gt;Qual usar?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Carregar 3 dados de API ao mesmo tempo&lt;/td&gt;
&lt;td&gt;Paralelo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Passo 1: Login → Passo 2: Pegar token → Passo 3: Dados&lt;/td&gt;
&lt;td&gt;Sequencial&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Testar 3 URLs e usar a primeira que responder&lt;/td&gt;
&lt;td&gt;Corrida (Race)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Quando falamos de Promises em Node.js, &lt;strong&gt;a forma como você organiza suas execuções faz toda a diferença&lt;/strong&gt; no desempenho e no comportamento do seu código.&lt;/p&gt;

&lt;p&gt;Lembre-se:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Promise.all()&lt;/code&gt; → tudo junto (paralelo)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;await&lt;/code&gt; em sequência → um por vez (sequencial)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Promise.race()&lt;/code&gt; → quem chegar primeiro vence (corrida)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use o tipo certo de execução para &lt;strong&gt;otimizar seus fluxos assíncronos&lt;/strong&gt;. E se quiser explorar mais, experimente mudar os tempos de delay e veja como isso impacta a execução. &lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Integração Correios para Rastreamento de Entregas: Arquitetura Escalável com NestJS e Kafka</title>
      <dc:creator>Humberto Barbosa</dc:creator>
      <pubDate>Thu, 15 May 2025 12:12:50 +0000</pubDate>
      <link>https://dev.to/h1bertobarbosa/integracao-correios-para-rastreamento-de-entregas-arquitetura-escalavel-com-nestjs-e-kafka-oj2</link>
      <guid>https://dev.to/h1bertobarbosa/integracao-correios-para-rastreamento-de-entregas-arquitetura-escalavel-com-nestjs-e-kafka-oj2</guid>
      <description>&lt;h3&gt;
  
  
  Introdução
&lt;/h3&gt;

&lt;p&gt;Nos sistemas de e-commerce e da logística, rastrear o status de entregas é essencial para garantir transparência e agilidade no atendimento ao cliente. Automatizar esse processo com integração direta aos Correios é um desafio que envolve lidar com APIs externas, mapeamento de status inconsistentes e atualização em tempo real.&lt;/p&gt;

&lt;p&gt;Neste artigo, vamos apresentar uma abordagem completa para orquestração de rastreamento de pedidos usando NestJS, aplicando os princípios de Clean Architecture, testes unitários robustos e integração com mensageria (Kafka).&lt;/p&gt;

&lt;h3&gt;
  
  
  Desenho da Solução
&lt;/h3&gt;

&lt;p&gt;A solução gira em torno do caso de uso &lt;code&gt;TrackingOrderStatusService&lt;/code&gt;, responsável por:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consultar configurações de contas com rastreamento ativo;&lt;/li&gt;
&lt;li&gt;Buscar os pedidos com status finalizados que devem ser atualizados;&lt;/li&gt;
&lt;li&gt;Integrar com a API dos Correios via &lt;code&gt;ProviderTrackingApiGateway&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Filtrar eventos novos não registrados;&lt;/li&gt;
&lt;li&gt;Mapear os eventos para um modelo interno de status;&lt;/li&gt;
&lt;li&gt;Persistir os novos eventos no repositório;&lt;/li&gt;
&lt;li&gt;Emitir mensagens Kafka sobre mudanças de status;&lt;/li&gt;
&lt;li&gt;Registrar novos status desconhecidos para posterior mapeamento.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pontos de Complexidade
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Identificação de Status&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A API dos Correios utiliza uma combinação de &lt;code&gt;codigo&lt;/code&gt; e &lt;code&gt;tipo&lt;/code&gt; para representar eventos. Essa combinação foi padronizada com o helper:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;buildPartnerStatusId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;codigo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tipo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;codigo&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;tipo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso garante que qualquer ponto do sistema que precise identificar unicamente um status tenha uma forma unificada, reduzindo erros e facilitando o mapeamento.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Detecção de Eventos Novos&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Para evitar a reprocessamento de eventos já persistidos, usamos o método &lt;code&gt;getNewHistories&lt;/code&gt;. Ele compara os eventos vindos dos Correios com os eventos já salvos no histórico:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;getNewHistories&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tracking&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TrackingData&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;eventos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CorreiosEventoDTO&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="nx"&gt;CorreiosEventoDTO&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;eventos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evento&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;historyExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evento&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tracking&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E o &lt;code&gt;historyExists&lt;/code&gt; compara tanto o código concatenado quanto a data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;historyExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evento&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CorreiosEventoDTO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tracking&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TrackingData&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;tracking&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hist&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;hist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;partner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nf"&gt;buildPartnerStatusId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evento&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;codigo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;evento&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tipo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
      &lt;span class="nf"&gt;compareDates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hist&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eventDate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;evento&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dtHrCriado&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Fallback para Status Não Mapeados&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Se um evento dos Correios não tem status mapeado, salvamos esse status para posterior análise e notificamos por Kafka:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;statusMapped&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newStatusPartner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StatusCodePartner&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;statusId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCodePartnerRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newStatusPartner&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messageProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;KAFKA_TOPIC_FREIGHT_STATUS_CODE_PARTNER_NOT_FOUND&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
      &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newStatusPartner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X-Tenant-Id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;accountId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X-Correlation-Id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;randomUUID&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Resiliência e Logging&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Todas as etapas do processo possuem logging contextualizado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TrackingOrderStatusService.trackingOrders&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`[&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tracking&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;accountId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;|&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tracking&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;internalOrderId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;] Evento processado com sucesso.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Além disso, exceções são capturadas e logadas para facilitar troubleshooting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TrackingOrderStatusService.execute&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Abstração via API Gateway
&lt;/h3&gt;

&lt;p&gt;Outro destaque importante da implementação é o uso do &lt;code&gt;ProviderTrackingApiGateway&lt;/code&gt;, uma interface que abstrai o consumo da API dos Correios. Ao invés de depender diretamente de chamadas HTTP acopladas no serviço, a integração é feita via uma porta definida por contrato:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface ProviderTrackingApiGateway {
  getTracking(etiqueta: string, cep: string): Promise&amp;lt;CorreiosApiResponseTrackingStatus&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa abordagem segue o princípio da Inversão de Dependência (DIP), permitindo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Substituir facilmente a implementação por mocks em testes unitários:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;correiosApiGateway = mock&amp;lt;ProviderTrackingApiGateway&amp;gt;();
correiosApiGateway.getTracking.mockResolvedValue(mockCorreiosTrackingResponse);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Trocar facilmente a origem do rastreamento (ex: transportadoras privadas)&lt;/strong&gt; sem alterar o caso de uso&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reduzir acoplamento e facilitar manutenção&lt;/strong&gt;, pois a lógica de orquestração não precisa conhecer detalhes de implementação HTTP, headers ou autenticação&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Essa separação clara entre camada de aplicação e infraestrutura melhora a testabilidade e prepara o código para cenários mais complexos.&lt;/p&gt;

&lt;h3&gt;
  
  
  Boas Práticas Adotadas
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Inversão de dependência via tokens de injeção;&lt;/li&gt;
&lt;li&gt;Separacão de responsabilidades (cada provider tem uma única função);&lt;/li&gt;
&lt;li&gt;Logging com identificadores contextuais (&lt;code&gt;[accountId|orderId]&lt;/code&gt;);&lt;/li&gt;
&lt;li&gt;Utilização de &lt;code&gt;Promise.all&lt;/code&gt; para operações paralelas (status + configuração);&lt;/li&gt;
&lt;li&gt;Mensagens Kafka emitidas apenas para eventos novos.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Testes Unitários
&lt;/h3&gt;

&lt;h4&gt;
  
  
  🧪 Exemplo de Teste com Gateway Mockado
&lt;/h4&gt;

&lt;p&gt;Abaixo está um exemplo real de como o &lt;code&gt;ProviderTrackingApiGateway&lt;/code&gt; pode ser simulado em testes unitários usando &lt;code&gt;jest-mock-extended&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;MockProxy&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jest-mock-extended&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ProviderTrackingApiGateway&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../correios/interfaces/provider-tracking-api-gateway&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CorreiosApiResponseTrackingStatus&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../correios/interfaces/provider-tracking-api-gateway&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;TrackingOrderStatusService – Integração com Correios API&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;correiosApiGateway&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MockProxy&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ProviderTrackingApiGateway&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;correiosApiGateway&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mock&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ProviderTrackingApiGateway&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;deve retornar eventos simulados dos Correios via gateway mockado&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;mockCorreiosResponse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CorreiosApiResponseTrackingStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;objetos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;codObjeto&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;XYZ123456BR&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;dtPrevista&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2025-04-25T18:00:00Z&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="na"&gt;modalidade&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;F&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;peso&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;formato&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pacote&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;eventos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="na"&gt;codigo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BDE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;tipo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;01&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="na"&gt;dtHrCriado&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2025-04-21T14:00:00Z&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
              &lt;span class="na"&gt;descricao&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Objeto entregue ao destinatário&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nx"&gt;correiosApiGateway&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getTracking&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mockResolvedValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mockCorreiosResponse&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;correiosApiGateway&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTracking&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;XYZ123456BR&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;12345&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;objetos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;codObjeto&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;XYZ123456BR&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;objetos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;eventos&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;codigo&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BDE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse mock garante que o &lt;code&gt;ApiGateway&lt;/code&gt; esteja isolado e testável sem fazer chamadas reais, permitindo simular qualquer tipo de retorno da API externa.&lt;/p&gt;

&lt;p&gt;Para garantir a qualidade e a confiabilidade da lógica, foram adicionados testes com &lt;code&gt;jest-mock-extended&lt;/code&gt; para:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;getAllStatusMapped&lt;/code&gt;: mapeamento correto e fallback para status desconhecidos;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;getNewHistories&lt;/code&gt;: detecção de eventos novos;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;historyExists&lt;/code&gt;: comparação exata por status e data;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;trackingOrders&lt;/code&gt; e &lt;code&gt;execute&lt;/code&gt;: cenários completos de sucesso e falha.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Lições Aprendidas
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Pequenos helpers como &lt;code&gt;buildPartnerStatusId&lt;/code&gt; e &lt;code&gt;compareDates&lt;/code&gt; reduzem bugs e aumentam reutilização;&lt;/li&gt;
&lt;li&gt;Separar persistência de envio em &lt;code&gt;sendMessageStatusNotFound&lt;/code&gt; tornou o código mais testável e legível;&lt;/li&gt;
&lt;li&gt;Centralizar a orquestração no caso de uso facilita extensão para outras transportadoras;&lt;/li&gt;
&lt;li&gt;Cobertura de testes auxilia na manutenção sem medo de regressão.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusão
&lt;/h3&gt;

&lt;p&gt;A solução apresentada mostra como é possível construir uma integração robusta com os Correios utilizando boas práticas de arquitetura, testes e logging. Além de resolver o problema imediato de rastreamento, essa abordagem serve como base para integração com outros parceiros logísticos.&lt;/p&gt;

&lt;p&gt;Essa implementação está pronta para produção, observável e fácil de evoluir.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>node</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Evitando Erros de Índice Único (E11000) ao Usar findOneAndUpdate com upsert no Mongoose</title>
      <dc:creator>Humberto Barbosa</dc:creator>
      <pubDate>Sat, 26 Apr 2025 23:29:00 +0000</pubDate>
      <link>https://dev.to/h1bertobarbosa/evitando-erros-de-indice-unico-e11000-ao-usar-findoneandupdate-com-upsert-no-mongoose-49df</link>
      <guid>https://dev.to/h1bertobarbosa/evitando-erros-de-indice-unico-e11000-ao-usar-findoneandupdate-com-upsert-no-mongoose-49df</guid>
      <description>&lt;p&gt;Como garantir unicidade de remessas em sistemas multi-tenant no MongoDB? Entenda por que erros E11000 acontecem, como alinhar filtros de upsert com índices únicos e evite armadilhas clássicas em modelagem de dados para operações críticas.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Cenário
&lt;/h2&gt;

&lt;p&gt;Imagine um sistema de gestão de entregas com múltiplos clientes (empresas) utilizando a mesma plataforma. Cada cliente (representado por um &lt;code&gt;tenantId&lt;/code&gt;) possui seus próprios &lt;strong&gt;pedidos internos&lt;/strong&gt; (&lt;code&gt;clientOrderId&lt;/code&gt;), que podem coincidir entre diferentes clientes, mas &lt;strong&gt;não dentro do mesmo cliente&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Cada pedido tem &lt;strong&gt;uma única remessa associada&lt;/strong&gt;, representada por um &lt;code&gt;shipment&lt;/code&gt; com informações como nota fiscal, status e dados logísticos.&lt;/p&gt;

&lt;p&gt;Você precisa garantir que &lt;strong&gt;haja apenas uma remessa por pedido e por cliente&lt;/strong&gt; — e que atualizações venham a sobrescrever remessas existentes se o pedido já existir.&lt;/p&gt;




&lt;h2&gt;
  
  
  💾 Estrutura simplificada dos dados
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Schema&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;shipments&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;timestamps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ShipmentEntity&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Document&lt;/span&gt; &lt;span class="p"&gt;{@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="nx"&gt;tenantId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="nx"&gt;clientOrderId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="nx"&gt;invoiceNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;@&lt;/span&gt;&lt;span class="nd"&gt;Prop&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="nx"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔐 Definindo o índice único
&lt;/h2&gt;

&lt;p&gt;Para garantir unicidade por cliente + pedido:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;ShipmentSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;tenantId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;clientOrderId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse índice impede que existam dois documentos com a mesma combinação &lt;code&gt;tenantId&lt;/code&gt; e &lt;code&gt;clientOrderId&lt;/code&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  📈 O Risco pro negocio
&lt;/h3&gt;

&lt;p&gt;Quando pensamos em unicidade de remessas, não é só uma questão de evitar erros técnicos como o E11000.&lt;br&gt;
&lt;strong&gt;É sobre proteger a integridade operacional do sistema.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Se um pedido tiver duas remessas associadas por erro, as consequências podem incluir:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Faturamento duplicado&lt;/strong&gt;: o cliente pode ser cobrado duas vezes pelo mesmo pedido.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Erro logístico&lt;/strong&gt;: o centro de distribuição pode despachar duas cargas separadas para o mesmo destino.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Problemas fiscais&lt;/strong&gt;: inconsistência nas notas fiscais emitidas pode gerar multas ou retrabalho junto à Receita.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Perda de confiança&lt;/strong&gt;: clientes empresariais esperam precisão; falhas assim corroem a relação de confiança.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ou seja:&lt;br&gt;
&lt;strong&gt;Definir corretamente a unicidade dos dados não é só uma questão técnica — é uma salvaguarda para a operação e para o relacionamento com o cliente.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  ❌ O erro clássico: E11000
&lt;/h2&gt;

&lt;p&gt;Se você tentar fazer um &lt;code&gt;findOneAndUpdate&lt;/code&gt; assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shipmentModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOneAndUpdate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;clientOrderId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;shipment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientOrderId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;invoiceNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;shipment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invoiceNumber&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$set&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;shipment&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;new&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;upsert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pode falhar com o erro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;E11000 duplicate key error collection: logistics.shipments index: tenantId_1_clientOrderId_1 dup key: &lt;span class="o"&gt;{&lt;/span&gt; tenantId: &lt;span class="s2"&gt;"tenantA"&lt;/span&gt;, clientOrderId: &lt;span class="s2"&gt;"12345"&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso ocorre porque o filtro ignora &lt;code&gt;tenantId&lt;/code&gt;, violando a restrição única definida pelo índice.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Solução: usar o filtro certo
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shipmentModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOneAndUpdate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;tenantId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;shipment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tenantId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="na"&gt;clientOrderId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;shipment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientOrderId&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$set&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;shipment&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;new&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;upsert&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora o &lt;code&gt;upsert&lt;/code&gt; respeita a chave única, atualizando corretamente se já houver uma remessa com o mesmo pedido para o mesmo cliente, ou criando um novo registro caso contrário.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Conclusão
&lt;/h2&gt;

&lt;p&gt;Quando trabalhamos com &lt;code&gt;upsert&lt;/code&gt; no MongoDB, é fundamental que o filtro usado esteja alinhado com o índice único que definimos. No caso que discutimos, isso significa sempre usar &lt;code&gt;tenantId&lt;/code&gt; e &lt;code&gt;clientOrderId&lt;/code&gt; juntos. Se você esquecer um deles ou misturar outros campos, como &lt;code&gt;invoiceNumber&lt;/code&gt;, pode acabar quebrando a unicidade e gerando erros difíceis de diagnosticar.&lt;/p&gt;

&lt;p&gt;É importante lembrar que buscar por qualquer campo no MongoDB é possível — mas isso não significa que qualquer campo serve para garantir unicidade em operações críticas. Se sua operação depende da certeza de que "não existe outro igual", então o campo (ou a combinação de campos) precisa estar refletido no índice único.&lt;/p&gt;

&lt;p&gt;Quando acontece um erro como o E11000, não é só um problema de código quebrado. É um sinal de que a modelagem dos dados, a estratégia de identificação e a operação do sistema podem estar desalinhadas. Esses erros são uma ótima oportunidade para revisar e fortalecer o desenho do seu banco.&lt;/p&gt;

&lt;p&gt;Por fim, sempre vale a pena pensar além da parte técnica: proteger a unicidade dos dados é proteger também a integridade do seu processo logístico, financeiro e de relacionamento com os clientes. No final das contas, um sistema que respeita essas premissas é mais robusto, confiável — e mais fácil de evoluir.&lt;/p&gt;

</description>
      <category>mongoose</category>
      <category>nestjs</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Como os pilares da Programação Orientada a Objetos (POO) se conectam ao SOLID</title>
      <dc:creator>Humberto Barbosa</dc:creator>
      <pubDate>Mon, 07 Apr 2025 14:26:15 +0000</pubDate>
      <link>https://dev.to/h1bertobarbosa/como-os-pilares-da-programacao-orientada-a-objetos-poo-se-conectam-ao-solid-3e3</link>
      <guid>https://dev.to/h1bertobarbosa/como-os-pilares-da-programacao-orientada-a-objetos-poo-se-conectam-ao-solid-3e3</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;1. Abstração&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Foca no comportamento essencial isolando as características essenciais de um objeto, ignorando os detalhes de implementação.&lt;/p&gt;

&lt;p&gt;A abstração é um dos pilares da Programação Orientada a Objetos (POO) que ajuda a reduzir a complexidade no desenvolvimento de software. Ela permite que os programadores representem entidades do mundo real de maneira simplificada, focando apenas nos aspectos essenciais para o sistema.&lt;/p&gt;

&lt;p&gt;Isso permite que seu código de negócio &lt;strong&gt;não conheça&lt;/strong&gt; como o pagamento será salvo: pode ser banco, arquivo, API.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Encapsulamento&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Protege o estado interno do objeto ermite ocultando os detalhes internos de implementação e definindo uma interface de uso externo segura.&lt;/p&gt;

&lt;p&gt;O encapsulamento é um princípio fundamental da Programação Orientada a Objetos que consiste em &lt;strong&gt;ocultar os detalhes internos de um objeto&lt;/strong&gt;, expondo apenas o que é necessário para sua interação. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Herança&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Permite reuso de comportamento e especialização por meio de classes derivadas.&lt;/p&gt;

&lt;p&gt;A herança é um dos pilares fundamentais da Programação Orientada a Objetos que permite &lt;strong&gt;estender funcionalidades&lt;/strong&gt; de uma classe já existente. Com ela, é possível criar novas classes (chamadas de &lt;strong&gt;subclasses&lt;/strong&gt; ou &lt;strong&gt;classes filhas&lt;/strong&gt;) que herdam características (atributos e métodos) de uma &lt;strong&gt;classe base&lt;/strong&gt; (superclasse ou classe pai).&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. Polimorfismo&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Permite que objetos de diferentes classes possam &lt;strong&gt;responder de maneira diferente a uma mesma chamada de método&lt;/strong&gt;, mantendo uma interface comum.&lt;/p&gt;

&lt;p&gt;O polimorfismo é um conceito essencial da POO que permite que &lt;strong&gt;um mesmo método se comporte de maneiras diferentes&lt;/strong&gt;, dependendo do objeto que o executa. Ele dá flexibilidade ao código, permitindo que classes distintas respondam à mesma ação de formas específicas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Os 5 Princípios SOLID
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Single Responsibility Principle (SRP) – Princípio da Responsabilidade Única&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Reúna as coisas que mudam pelos mesmos motivos. Separe as coisas que mudam por motivos diferentes.&lt;/p&gt;

&lt;p&gt;Evite misturar regras de negócio com a camada de interface gráfica. Também separamos comandos SQL de protocolos de comunicação. Fazemos isso porque queremos manter isolado o código que muda por motivos diferentes, evitando que alterações em uma parte afetem outras de forma indesejada. Assim, garantimos que módulos que evoluem por razões distintas não fiquem entrelaçados por dependências desnecessárias.&lt;/p&gt;

&lt;p&gt;Se uma classe faz muitas coisas diferentes, ela fica difícil de entender e modificar. Separando as responsabilidades, deixamos o código &lt;strong&gt;mais organizado e modular&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;2. Open/Closed Principle (OCP) – Princípio Aberto/Fechado&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;O código deve estar &lt;strong&gt;aberto para extensão, mas fechado para modificação&lt;/strong&gt;. Isso significa que devemos ser capazes de &lt;strong&gt;adicionar novas funcionalidades sem alterar o código existente&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Isso quer dizer que devemos usar interfaces ou classes abstratas para definir o comportamento, e usando polimorfismo esse comportamento pode variar em tempo de execução.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;3. Liskov Substitution Principle (LSP) – Princípio da Substituição de Liskov&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Subtipos devem ser substituíveis por seus tipos base&lt;/strong&gt; sem quebrar a aplicação.&lt;/p&gt;

&lt;p&gt;Se uma subclasse altera o comportamento esperado da classe pai, podemos ter problemas imprevisíveis no código.&lt;br&gt;
Existem 3 regras que devem ser seguidas pelas subclasses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pré-condições não devem ser fortalecidas na subclasse&lt;/strong&gt;: Pré-condições representam os requisitos necessários para que um método possa ser executado corretamente, os parâmetros esperados. Por exemplo, se um método aceita um número (positivo ou negativo), uma subclasse &lt;strong&gt;não deve restringir&lt;/strong&gt; esse comportamento para aceitar apenas números positivos. Fazer isso &lt;strong&gt;fortalece a pré-condição&lt;/strong&gt;, e pode quebrar a lógica do programa, especialmente em casos onde se espera que o método aceite números negativos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pós-condições não devem ser enfraquecidas na subclasse&lt;/strong&gt;: As pós-condições definem o que o método retorna após sua execução. Uma subclasse &lt;strong&gt;não deve retornar menos do que o esperado&lt;/strong&gt;. Por exemplo, se o contrato do método exige um valor booleano, a subclasse deve retornar um &lt;code&gt;true&lt;/code&gt; ou &lt;code&gt;false&lt;/code&gt;. Embora seja possível "fortalecer" o contrato (por exemplo, retornando sempre &lt;code&gt;true&lt;/code&gt;), retornar &lt;strong&gt;outros tipos como &lt;code&gt;string&lt;/code&gt;, &lt;code&gt;number&lt;/code&gt;, &lt;code&gt;null&lt;/code&gt;&lt;/strong&gt;, ou lançar exceções inesperadas, &lt;strong&gt;quebra a expectativa&lt;/strong&gt; da aplicação — especialmente em linguagens dinamicamente tipadas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A invariância deve ser preservada na subclasse&lt;/strong&gt;: Invariância se refere ao estado interno do objeto, que deve ser protegido e controlado por meio de encapsulamento. Subclasses &lt;strong&gt;não devem violar esse contrato&lt;/strong&gt;, modificando diretamente atributos da superclasse ou alterando sua lógica de maneira inconsistente. É essencial respeitar os &lt;strong&gt;modificadores de visibilidade&lt;/strong&gt; (como &lt;code&gt;private&lt;/code&gt; e &lt;code&gt;protected&lt;/code&gt;) e manter o &lt;strong&gt;comportamento coerente&lt;/strong&gt; em toda a hierarquia de classes.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;4. Interface Segregation Principle (ISP) – Princípio da Segregação de Interface&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Nenhuma classe deve ser forçada a depender de &lt;strong&gt;métodos que não usa&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;É melhor ter &lt;strong&gt;múltiplas interfaces específicas&lt;/strong&gt; do que uma interface gigante cheia de métodos inúteis.&lt;/p&gt;

&lt;h4&gt;
  
  
  Por que isso importa? (segundo Uncle bob)
&lt;/h4&gt;

&lt;p&gt;Mesmo hoje, trabalhando com linguagens compiladas, ainda somos afetados por problemas relacionados à &lt;strong&gt;recompilação&lt;/strong&gt; e &lt;strong&gt;reimplantação&lt;/strong&gt; desnecessária. Imagine o seguinte cenário:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O &lt;strong&gt;Módulo A&lt;/strong&gt; depende de uma interface do &lt;strong&gt;Módulo B&lt;/strong&gt; apenas para um subconjunto de seus métodos.&lt;/li&gt;
&lt;li&gt;Se outro método dessa interface for alterado, &lt;strong&gt;mesmo que o Módulo A não o utilize&lt;/strong&gt;, ele precisará ser recompilado e reimplantado.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esse acoplamento em tempo de compilação, mesmo sem dependência em tempo de execução, é um &lt;strong&gt;problema real&lt;/strong&gt; — especialmente em linguagens &lt;strong&gt;estaticamente tipadas&lt;/strong&gt; como &lt;strong&gt;Java, C#, C++, Go, Swift&lt;/strong&gt; etc.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;5. Dependency Inversion Principle (DIP) – Princípio da Inversão de Dependência&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Dependa de abstrações, não de implementações concretas, ou seja abstrações não devem depender de detalhes. Detalhes devem depender de abstrações.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Isso significa que implementando esse princípio voce vai &lt;strong&gt;quebrar a dependência direta entre regras de negócio (nível alto)&lt;/strong&gt; e &lt;strong&gt;detalhes de implementação (nível baixo)&lt;/strong&gt;. Ele propõe que as dependências devem sempre apontar para &lt;strong&gt;abstrações&lt;/strong&gt;, nunca diretamente para implementações concretas.&lt;br&gt;
A injeção de dependências resolve o vínculo entre os dois em tempo de execução.&lt;/p&gt;




&lt;h2&gt;
  
  
  RELAÇÃO: PILARES da POO → PRINCÍPIOS SOLID
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pilar da POO&lt;/th&gt;
&lt;th&gt;Conexões com Princípios SOLID&lt;/th&gt;
&lt;th&gt;Como se Conectam&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Abstração&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;OCP&lt;/strong&gt;, &lt;strong&gt;DIP&lt;/strong&gt;, &lt;strong&gt;ISP&lt;/strong&gt;, &lt;strong&gt;SRP&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Permite &lt;strong&gt;ocultar complexidade&lt;/strong&gt;, definindo &lt;strong&gt;interfaces&lt;/strong&gt; que isolam o “o quê” do “como”. Facilita o desacoplamento entre módulos. Base para &lt;strong&gt;Dependency Inversion&lt;/strong&gt; e &lt;strong&gt;Interface Segregation&lt;/strong&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Encapsulamento&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;SRP&lt;/strong&gt;, &lt;strong&gt;LSP&lt;/strong&gt;, &lt;strong&gt;OCP&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Protege o estado interno dos objetos, &lt;strong&gt;separando responsabilidades&lt;/strong&gt;. Ajuda a manter &lt;strong&gt;coesão&lt;/strong&gt; e &lt;strong&gt;evitar que alterações em um detalhe impactem em outros&lt;/strong&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Herança&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;OCP&lt;/strong&gt;, &lt;strong&gt;LSP&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Permite a extensão de comportamento sem modificação (essência do &lt;strong&gt;Open/Closed&lt;/strong&gt;). Deve ser usada com cautela para não violar substituição (&lt;strong&gt;Liskov&lt;/strong&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Polimorfismo&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;OCP&lt;/strong&gt;, &lt;strong&gt;DIP&lt;/strong&gt;, &lt;strong&gt;LSP&lt;/strong&gt;, &lt;strong&gt;ISP&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Permite que objetos de diferentes tipos sejam tratados de forma uniforme via interfaces. Viabiliza &lt;strong&gt;inversão de dependência&lt;/strong&gt;, &lt;strong&gt;extensão sem modificação&lt;/strong&gt; e &lt;strong&gt;substituição segura&lt;/strong&gt; de implementações.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Código tem que ser simples
&lt;/h2&gt;

&lt;p&gt;Simplicidade &lt;strong&gt;não é ausência de estrutura&lt;/strong&gt; ou codar com falta de boas praticas e principios&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Dizer apenas "Código tem que ser simples" sem oferecer princípios claros é como ser um surdo em bingo.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Com o entendimento básico dos fundamentos de POO fica mais facil entender os principios SOLID&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle&lt;/a&gt;&lt;br&gt;
&lt;a href="https://blog.cleancoder.com/uncle-bob/2020/10/18/Solid-Relevance.html" rel="noopener noreferrer"&gt;https://blog.cleancoder.com/uncle-bob/2020/10/18/Solid-Relevance.html&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.branas.io/blog/solid-lsp-liskov-substitution-principle.htmlpo" rel="noopener noreferrer"&gt;https://www.branas.io/blog/solid-lsp-liskov-substitution-principle.htmlpo&lt;/a&gt;&lt;br&gt;
&lt;a href="https://hub.asimov.academy/blog/programacao-orientada-a-objetos-conceito-e-pilares/" rel="noopener noreferrer"&gt;https://hub.asimov.academy/blog/programacao-orientada-a-objetos-conceito-e-pilares/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>solidprinciples</category>
      <category>poo</category>
    </item>
    <item>
      <title>Publicando eventos a partir do domínio - com NestJS</title>
      <dc:creator>Humberto Barbosa</dc:creator>
      <pubDate>Fri, 28 Mar 2025 20:56:41 +0000</pubDate>
      <link>https://dev.to/h1bertobarbosa/publicando-eventos-a-partir-do-dominio-com-nestjs-551m</link>
      <guid>https://dev.to/h1bertobarbosa/publicando-eventos-a-partir-do-dominio-com-nestjs-551m</guid>
      <description>&lt;h2&gt;
  
  
  📌 Eventos de Domínio: O que são e por que usar?
&lt;/h2&gt;

&lt;p&gt;Eventos de domínio registram fatos importantes dentro do sistema. Algo aconteceu – um usuário se cadastrou, uma compra foi feita, um status mudou. Ao capturar isso como um evento, mantemos um histórico claro, facilitando auditorias e análises. Além disso, deixamos o sistema preparado para reagir a mudanças sem bagunçar tudo.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Implementação na prática
&lt;/h2&gt;

&lt;p&gt;Eventos precisam ser &lt;strong&gt;imutáveis&lt;/strong&gt;. Criou? Não mexe mais. Isso garante integridade e rastreabilidade. Outra coisa: desacoplar ao máximo. Se um evento precisa notificar outra parte do sistema, nada de dependência direta. Deixa ele solto e deixa quem precisar ouvir.&lt;/p&gt;

&lt;p&gt;Benefícios?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Regras de negócio explícitas&lt;/strong&gt; – Dá pra entender fácil o que está acontecendo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Código modular e organizado&lt;/strong&gt; – Menos acoplamento, mais flexibilidade.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistência entre agregados&lt;/strong&gt; – Se algo muda, tudo que precisa ser atualizado é notificado automaticamente.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🎯 Quando usar eventos de domínio?
&lt;/h2&gt;

&lt;p&gt;Sempre que precisar notificar outros contextos sem acoplamento. Exemplo clássico:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Usuário se cadastra → Dispara evento → Outro serviço manda e-mail de boas-vindas.&lt;/li&gt;
&lt;li&gt;Pedido pago → Dispara evento → Estoque e faturamento são atualizados automaticamente.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bora pro código.&lt;/p&gt;

&lt;p&gt;Para fazer isso, vamos evitar expor o dominio a qualquer tipo de infraestrutura de mensagens, com isso evitamos acoplar nossa entidade explicitamente a um recurso externo.&lt;/p&gt;

&lt;h2&gt;
  
  
  📌 Cenário:
&lt;/h2&gt;

&lt;p&gt;Temos um &lt;strong&gt;Usuário&lt;/strong&gt; que se cadastra no sistema. Quando isso acontece, queremos:&lt;br&gt;
✅ Enviar um e-mail de boas-vindas&lt;/p&gt;
&lt;h3&gt;
  
  
  Criando o Evento de Domínio
&lt;/h3&gt;

&lt;p&gt;Usamos &lt;strong&gt;eventos de domínio&lt;/strong&gt; para desacoplar esses processos. &lt;br&gt;
Bora pro código! 🎯&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsuarioCadastradoEvent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;usuarioId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Um evento simples com id e email do novo usuario&lt;/p&gt;

&lt;h3&gt;
  
  
  Criando o Agregado Raiz
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Usuario&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;domainEvents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;nome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;adicionarEvento&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UsuarioCadastradoEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;adicionarEvento&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evento&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domainEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;evento&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;pullEvents&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;events&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domainEvents&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domainEvents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O que rolou aqui?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Criamos um &lt;strong&gt;Usuário&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Assim que ele nasce, ele já dispara &lt;code&gt;UsuarioCadastradoEvent&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pullEvents()&lt;/code&gt; pega os eventos pendentes e os limpa.
### Criando um Manipulador de Eventos (Event Handler)
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;EventsHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;IEventHandler&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/cqrs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;UsuarioCadastradoEvent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../events/usuario-cadastrado.event&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;EventsHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;UsuarioCadastradoEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EnviarEmailBoasVindasHandler&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;IEventHandler&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UsuarioCadastradoEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UsuarioCadastradoEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`📧 Enviando e-mail de boas-vindas para &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;...`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quando &lt;code&gt;UsuarioCadastradoEvent&lt;/code&gt; acontece, o &lt;strong&gt;handler&lt;/strong&gt; entra em ação. Aqui ele só printa no console, mas poderia enviar e-mail, publicar no Kafka, chamar outro serviço, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Criando o Serviço de Usuário
&lt;/h3&gt;

&lt;p&gt;O NestJS já fornece um &lt;strong&gt;Event Bus&lt;/strong&gt; pronto via &lt;code&gt;@nestjs/cqrs&lt;/code&gt;, então só precisamos usá-lo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;EventBus&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/cqrs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Usuario&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../models/usuario.model&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UsuarioService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;eventBus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EventBus&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;criarUsuario&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Usuario&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;usuario&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Usuario&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nx"&gt;nome&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;usuario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pullEvents&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eventBus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;usuario&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Criamos o usuário.&lt;/li&gt;
&lt;li&gt;Pegamos os eventos gerados.&lt;/li&gt;
&lt;li&gt;Publicamos no &lt;strong&gt;Event Bus do NestJS&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Agora qualquer serviço que ouvir esse evento pode agir sem precisar mudar código aqui.&lt;/p&gt;

&lt;p&gt;Lembre-se de registrar no modulo, algo assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;UsuarioService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;EnviarEmailBoasVindasHandler&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;e claro registrar o cqrs no modulo principal conforme a documentação.&lt;br&gt;
Agora, sempre que um usuário se cadastrar, os eventos certos serão disparados. 🚀&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ Recapitulando
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Eventos de Domínio&lt;/strong&gt; organizam melhor as regras de negócio.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Código desacoplado&lt;/strong&gt; → Adiciona novos handlers sem mexer no código principal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NestJS + CQRS&lt;/strong&gt; → Event Bus já pronto, sem precisar reinventar a roda.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Links
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://martinfowler.com/eaaDev/DomainEvent.html" rel="noopener noreferrer"&gt;martinfowler.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fullcycle.com.br/principais-conceitos-sobre-domain-events/" rel="noopener noreferrer"&gt;fullcycle.com.br&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/pt-br/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/domain-events-design-implementation" rel="noopener noreferrer"&gt;learn.microsoft.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.nestjs.com/recipes/cqrs#events" rel="noopener noreferrer"&gt;docs.nestjs.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>nestjs</category>
    </item>
    <item>
      <title>As três leis do TDD em 'The Clean Coder'</title>
      <dc:creator>Humberto Barbosa</dc:creator>
      <pubDate>Wed, 19 Mar 2025 10:47:05 +0000</pubDate>
      <link>https://dev.to/h1bertobarbosa/as-tres-leis-do-tdd-em-the-clean-coder-p88</link>
      <guid>https://dev.to/h1bertobarbosa/as-tres-leis-do-tdd-em-the-clean-coder-p88</guid>
      <description>&lt;p&gt;Robert C. Martin, o Uncle Bob, não brinca quando fala de Test Driven Development (TDD). Ele trata como disciplina essencial para quem quer ser um desenvolvedor de verdade. O cara define três leis que tornam o TDD um processo inegociável:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;"Não escreva código de produção sem antes escrever um teste que falhe."&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Sem exceções. Antes de codar qualquer funcionalidade, escreva um teste que prove que aquilo precisa existir. Como a funcionalidade ainda não foi implementada, o teste falha. Essa falha inicial mostra que o teste realmente verifica o comportamento esperado.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;"Não escreva mais de um teste do que o suficiente para falhar - e não compilar já conta como falha."&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Sem enrolação. Escreva apenas o necessário para ver o erro acontecer. Nada de sair codando funcionalidade antes da hora.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;"Não escreva mais código de produção do que o necessário para passar no teste que falhou."&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Código mínimo para o teste passar, nada de firulas. Isso força um ciclo enxuto de implementação e garante que cada linha de código tenha um propósito.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  O Ciclo Virtuoso do TDD
&lt;/h3&gt;

&lt;p&gt;Essas três leis criam um loop de desenvolvimento que dura, em média, 30 segundos. Escreve teste → vê falhar → escreve código → vê passar → refatora. Esse ciclo curto reduz o risco de surpresas desagradáveis no código.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefícios do TDD
&lt;/h3&gt;

&lt;p&gt;Uncle Bob defende que seguir essas regras traz uma série de vantagens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Certeza&lt;/strong&gt;: Testes constantes garantem que as funcionalidades funcionam como esperado.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Coragem&lt;/strong&gt;: Ter uma suíte de testes permite refatorar sem medo de quebrar tudo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Menos bugs&lt;/strong&gt;: Erros são encontrados antes de chegarem ao usuário.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentação viva&lt;/strong&gt;: Os testes servem como um manual de como o código deveria se comportar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design melhor&lt;/strong&gt;: TDD força modularidade e baixo acoplamento.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  O Maior Benefício: Certeza
&lt;/h3&gt;

&lt;p&gt;Segundo Uncle Bob, o grande diferencial do TDD é a confiança que ele proporciona. Escrevendo e rodando centenas de testes por semana, um desenvolvedor sabe exatamente o que está funcionando. No projeto FitNesse, com 64 mil linhas de código e mais de 2.200 testes unitários, Uncle Bob garante 90% de cobertura. Tudo roda em 90 segundos, e se passar, ele sabe que pode lançar uma nova versão sem pânico.&lt;/p&gt;

&lt;p&gt;Isso se traduz em:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Refatoração sem medo&lt;/strong&gt;: Melhorar o código sem receio de quebrar algo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Menos defeitos no código final&lt;/strong&gt;: Bugs são eliminados antes de virarem problema para o usuário.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Resumindo? Se você quer escrever código que realmente funcione, sem gambiarra e sem susto, TDD não é opcional. É disciplina. Seguir esse processo transforma código ruim em código sólido.&lt;/p&gt;

</description>
      <category>tdd</category>
      <category>programming</category>
    </item>
    <item>
      <title>State Pattern na prática - pare de sofrer com lógicas de estado bagunçadas</title>
      <dc:creator>Humberto Barbosa</dc:creator>
      <pubDate>Tue, 18 Mar 2025 21:33:58 +0000</pubDate>
      <link>https://dev.to/h1bertobarbosa/state-pattern-na-pratica-pare-de-sofrer-com-logicas-de-estado-baguncadas-3no9</link>
      <guid>https://dev.to/h1bertobarbosa/state-pattern-na-pratica-pare-de-sofrer-com-logicas-de-estado-baguncadas-3no9</guid>
      <description>&lt;p&gt;Descobrir o &lt;strong&gt;State Pattern&lt;/strong&gt; foi um ponto de virada. Esse padrão não é o mais falado, mas resolve um problema real: código inchado por condicionais monstruosas.&lt;/p&gt;

&lt;p&gt;Sabe aquelas máquinas de estado cheias de &lt;code&gt;if&lt;/code&gt; e &lt;code&gt;switch&lt;/code&gt;? O código cresce, novos estados surgem e, de repente, qualquer alteração vira uma dor de cabeça. Já viu algo assim?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pending&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Estado inicial&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;changeStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newStatus&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newStatus&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Já está ativo...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Usuário ativado com sucesso.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blocked&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blocked&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Usuário já está bloqueado.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blocked&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Usuário bloqueado com sucesso.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canceled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canceled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Usuário já está cancelado.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;canceled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Usuário cancelado com sucesso.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Status inválido.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;getStatus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Status atual: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No começo, parece tranquilo. Mas conforme o sistema evolui, o inferno começa: um mar de condicionais espalhadas pelo código. Manutenção? Um pesadelo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solução
&lt;/h2&gt;

&lt;p&gt;O &lt;strong&gt;State Pattern&lt;/strong&gt; resolve isso. Em vez de espalhar lógica de estado, cada estado vira uma classe separada. O objeto principal apenas mantém uma referência ao estado atual e delega as decisões para ele.&lt;/p&gt;

&lt;p&gt;Menos bagunça, mais organização. E quando precisar adicionar um novo estado? Só criar uma nova classe, sem tocar no código existente. Quer código flexível e fácil de manter? State Pattern é o caminho.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exemplo
&lt;/h2&gt;

&lt;p&gt;Aqui está um exemplo de implementação do &lt;strong&gt;State Pattern&lt;/strong&gt; em &lt;strong&gt;TypeScript&lt;/strong&gt; para modelar o status de uma conta (&lt;strong&gt;Account&lt;/strong&gt;), que pode estar em um dos seguintes estados:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Active&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WaitingActivation&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Blocked&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Cancelled&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cada estado implementará um comportamento diferente para a conta. Vamos definir as classes de estado e a classe de contexto (&lt;code&gt;Account&lt;/code&gt;), que gerencia o estado atual.&lt;/p&gt;

&lt;h3&gt;
  
  
  📌 &lt;strong&gt;Passo 1: Definir a Interface do Estado&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Cada estado da conta precisa implementar essa interface para garantir que todos os estados tenham os mesmos métodos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;AccountState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;activate&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;block&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;getStatus&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  📌 &lt;strong&gt;Passo 2: Criar as Implementações dos Estados&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Cada estado terá uma implementação específica, alterando o comportamento da conta de acordo com a regra de negócio.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ActiveState&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;AccountState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;activate&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A conta já está ativa.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;block&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bloqueando a conta...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BlockedState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cancelando a conta...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CancelledState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;getStatus&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Active&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WaitingActivationState&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;AccountState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;activate&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ativando a conta...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ActiveState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;block&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A conta ainda não está ativada e não pode ser bloqueada.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cancelando a conta antes da ativação...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CancelledState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;getStatus&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;WaitingActivation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BlockedState&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;AccountState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;activate&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Não é possível ativar uma conta bloqueada. Contate o suporte.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;block&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A conta já está bloqueada.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cancelando a conta bloqueada...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CancelledState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;getStatus&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Blocked&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CancelledState&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;AccountState&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;activate&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Uma conta cancelada não pode ser reativada.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;block&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Uma conta cancelada não pode ser bloqueada.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A conta já está cancelada.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;getStatus&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cancelled&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  📌 &lt;strong&gt;Passo 3: Criar a Classe &lt;code&gt;Account&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Essa classe é sua entidade e gerencia o estado atual da conta e delega chamadas para o estado correto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Account&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AccountState&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Estado inicial: aguardando ativação&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WaitingActivationState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AccountState&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;activate&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;activate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;block&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;block&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;getStatus&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getStatus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  📌 &lt;strong&gt;Passo 4: Testar a Implementação&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Agora, vamos criar uma conta e testar as transições de estado, a execução seria algo assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myAccount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Status inicial:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;myAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getStatus&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nx"&gt;myAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;activate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Deve ativar a conta&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Status atual:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;myAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getStatus&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nx"&gt;myAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;block&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Deve bloquear a conta&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Status atual:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;myAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getStatus&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nx"&gt;myAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Deve cancelar a conta&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Status atual:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;myAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getStatus&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nx"&gt;myAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;activate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Tentativa de ativar uma conta cancelada (deve falhar)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Status final:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;myAccount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getStatus&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  📌 &lt;strong&gt;Explicação&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Encapsulamento dos estados:&lt;/strong&gt; Cada estado implementa um comportamento específico e sabe para qual estado pode transitar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mudança dinâmica de comportamento:&lt;/strong&gt; A classe &lt;code&gt;Account&lt;/code&gt; delega a execução das ações ao estado atual.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Evita &lt;code&gt;if-else&lt;/code&gt; desnecessários:&lt;/strong&gt; O código fica mais organizado e escalável.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Isso garante uma implementação flexível e permite adicionar novos estados sem modificar a lógica central da &lt;code&gt;Account&lt;/code&gt;. 🚀&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusão
&lt;/h3&gt;

&lt;p&gt;No State Pattern que a gente montou, vários princípios entraram em jogo sem a gente nem precisar pensar muito. Olha só:&lt;/p&gt;

&lt;p&gt;Encapsulamento? Sim Cada estado tem sua própria lógica, sem espalhar código bagunçado por aí. O &lt;code&gt;Account&lt;/code&gt; nem precisa saber como cada estado funciona, só delega e segue o jogo.&lt;/p&gt;

&lt;p&gt;Responsabilidade Única? Sim Cada classe faz uma coisa só. O estado lida com as regras do status da conta, e o &lt;code&gt;Account&lt;/code&gt; só troca de estado quando precisa. Sem mistura de responsabilidades.&lt;/p&gt;

&lt;p&gt;Aberto/Fechado? Sim. Se amanhã precisar de um novo estado tipo &lt;code&gt;SuspendedState&lt;/code&gt;, só criar e encaixar. Não precisa mexer no código velho e correr risco de quebrar tudo.&lt;/p&gt;

&lt;p&gt;Substituição de Liskov? Sim. O &lt;code&gt;Account&lt;/code&gt; nem sabe qual estado tá rodando. Ele só chama os métodos da interface e confia que o estado resolve. Pode trocar um pelo outro sem dor de cabeça.&lt;/p&gt;

&lt;p&gt;Inversão de Dependência? Sim. O &lt;code&gt;Account&lt;/code&gt; depende da abstração (&lt;code&gt;AccountState&lt;/code&gt;), não de implementações específicas. Zero acoplamento, total flexibilidade.&lt;/p&gt;

&lt;p&gt;No fim, isso aqui é código escalável, fácil de manter e sem aquele monte de &lt;code&gt;if&lt;/code&gt; espalhado. Quer mudar um comportamento? Troca o estado e pronto. Isso é POO do jeito certo. 🚀&lt;/p&gt;

&lt;h3&gt;
  
  
  Links
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://refactoring.guru/pt-br/design-patterns/state" rel="noopener noreferrer"&gt;https://refactoring.guru/pt-br/design-patterns/state&lt;/a&gt;&lt;br&gt;
&lt;a href="https://elemarjr.com/clube-de-estudos/artigos/voce-precisa-conhecer-o-state-pattern/" rel="noopener noreferrer"&gt;https://elemarjr.com/clube-de-estudos/artigos/voce-precisa-conhecer-o-state-pattern/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>softwaredevelopment</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>Como testes mudaram minha forma de trabalhar</title>
      <dc:creator>Humberto Barbosa</dc:creator>
      <pubDate>Tue, 18 Mar 2025 00:30:10 +0000</pubDate>
      <link>https://dev.to/h1bertobarbosa/como-testes-mudaram-minha-forma-de-trabalhar-1g0e</link>
      <guid>https://dev.to/h1bertobarbosa/como-testes-mudaram-minha-forma-de-trabalhar-1g0e</guid>
      <description>&lt;p&gt;Antes, eu confiava no feeling. Escrevia código, rodava manualmente, dava aquela conferida na tela e, se parecia ok, bora pro deploy. Mas depois que comecei a testar do jeito certo, tudo mudou…&lt;/p&gt;

&lt;h2&gt;
  
  
  O que eu fazia antes
&lt;/h2&gt;

&lt;p&gt;Cada alteração era um risco. Ajustava uma coisa e, sem perceber, quebrava outra. Às vezes, gastava mais tempo testando manualmente do que escrevendo código. Já aconteceu de estar confiante, subir pra produção e… surpresa: bug.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que aprendi
&lt;/h2&gt;

&lt;p&gt;Testes não são sobre evitar bugs (porque eles vão acontecer), mas sobre &lt;strong&gt;ter controle&lt;/strong&gt;. Saber que, se algo quebrar, você vai descobrir &lt;strong&gt;antes do cliente&lt;/strong&gt;. Testes te colocam num ciclo rápido de feedback: você muda algo e, em segundos, já sabe se quebrou alguma coisa.&lt;/p&gt;

&lt;h2&gt;
  
  
  O impacto
&lt;/h2&gt;

&lt;p&gt;Menos medo de refatorar. Mais confiança pra evoluir o código. Tempo economizado que antes era gasto preenchendo formulário pra testar fluxo manualmente. A mentalidade mudou: agora penso primeiro em &lt;strong&gt;como testar&lt;/strong&gt;, antes de sair escrevendo código.&lt;/p&gt;

&lt;h2&gt;
  
  
  Se você ainda não aplica isso, está perdendo tempo
&lt;/h2&gt;

&lt;p&gt;Dá trabalho no começo, mas depois que entra no fluxo, &lt;strong&gt;vira hábito&lt;/strong&gt;. E um hábito que salva tempo, evita dor de cabeça e deixa seu código mais seguro.&lt;/p&gt;

&lt;p&gt;📌 &lt;strong&gt;E você, qual foi a maior mudança na sua forma de trabalhar nos últimos anos?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>test</category>
      <category>beginners</category>
    </item>
    <item>
      <title>O que acontece quando não tem testes?</title>
      <dc:creator>Humberto Barbosa</dc:creator>
      <pubDate>Tue, 18 Mar 2025 00:28:36 +0000</pubDate>
      <link>https://dev.to/h1bertobarbosa/o-que-acontece-quando-nao-tem-testes-9i8</link>
      <guid>https://dev.to/h1bertobarbosa/o-que-acontece-quando-nao-tem-testes-9i8</guid>
      <description>&lt;p&gt;Cada deploy é uma torcida. Você muda uma linha e fica esperando pra ver se algo quebrou. Feedback lento, retrabalho.&lt;/p&gt;

&lt;p&gt;Já passou um tempão preenchendo um formulário só pra testar um fluxo? Já quebrou algo numa parte do sistema que &lt;em&gt;aparentemente&lt;/em&gt; não tinha nada a ver? (eu já, várias vezes).&lt;/p&gt;

&lt;p&gt;Isso gera medo de mexer no código. E medo de mexer no código significa evolução mais lenta. Agora, quando você tem testes rodando pra vários cenários, qual o motivo pra temer?&lt;/p&gt;

&lt;p&gt;Testes não garantem que nunca vai ter um bug. Mas garantem que você tem mais controle sobre o código quando precisar mexer.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que realmente é um teste automatizado?
&lt;/h2&gt;

&lt;p&gt;É basicamente definir entradas e verificar se a saída tá batendo com a expectativa.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Given:&lt;/strong&gt; preparo do cenário&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When:&lt;/strong&gt; execução do comportamento&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Then:&lt;/strong&gt; validação do resultado&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;E se os testes forem lentos e dependentes entre si? Aí já começou errado. Eles devem rodar rápido e de forma independente.&lt;/p&gt;

&lt;p&gt;E o famoso &lt;em&gt;"não tenho tempo pra testar"&lt;/em&gt;? Mas tem tempo pra corrigir bug em produção, responder cliente puto, testar na mão, lidar com código legado que ninguém quer mexer, treinar dev novo… Pois é.&lt;/p&gt;

</description>
      <category>test</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Como Desacoplar um Serviço Externo do Seu Código (Sem Sofrer no Futuro)</title>
      <dc:creator>Humberto Barbosa</dc:creator>
      <pubDate>Sat, 15 Mar 2025 00:00:50 +0000</pubDate>
      <link>https://dev.to/h1bertobarbosa/como-desacoplar-um-servico-externo-do-seu-codigo-sem-sofrer-no-futuro-2boc</link>
      <guid>https://dev.to/h1bertobarbosa/como-desacoplar-um-servico-externo-do-seu-codigo-sem-sofrer-no-futuro-2boc</guid>
      <description>&lt;p&gt;Manter um sistema desacoplado de serviços externos não é frescura, &lt;strong&gt;é necessidade&lt;/strong&gt;. Se você quer um código mais flexível, testável e resiliente, precisa seguir algumas boas práticas. Vamos direto ao ponto:&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;1. Use um Gateway para Intermediar o Acesso&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Um &lt;strong&gt;Gateway&lt;/strong&gt; é basicamente um intermediário entre o seu código e o serviço externo. Ou seja, em vez de chamar diretamente a API do serviço, seu código conversa com um &lt;strong&gt;Gateway&lt;/strong&gt;, que gerencia essa comunicação.&lt;/p&gt;

&lt;p&gt;🔹 O que isso resolve?&lt;br&gt;
✅ Você pode &lt;strong&gt;trocar o serviço externo sem quebrar seu código&lt;/strong&gt;.&lt;br&gt;
✅ Facilita a implementação de &lt;strong&gt;cache, logs e validações&lt;/strong&gt;.&lt;br&gt;
✅ Reduz a dependência direta da aplicação no serviço externo.&lt;/p&gt;

&lt;p&gt;No livro &lt;em&gt;Patterns of Enterprise Application Architecture&lt;/em&gt; reforça que eles são essenciais para encapsular o acesso a sistemas externos.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;2. Aplique o Princípio da Inversão de Dependência (DIP)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;O DIP, um dos princípios SOLID, diz que &lt;strong&gt;o código deve depender de abstrações, não de implementações concretas&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;🔹 Como aplicar?&lt;br&gt;
✅ Crie &lt;strong&gt;interfaces&lt;/strong&gt; para os serviços externos e injete implementações via dependência.&lt;br&gt;
✅ Evite acoplar sua aplicação diretamente a APIs externas.&lt;br&gt;
✅ Facilita testes unitários, já que você pode &lt;strong&gt;mockar a interface em vez de bater na API real&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Exemplo prático: imagine que sua aplicação depende de uma api externa para fazer pagamentos. Em vez de chamar uma classe especifica que encapsula a lib do serviço de pagamento por exemplo: pagarmeService.pay()&lt;code&gt;, você pode criar uma interface&lt;/code&gt;PaymentService&lt;code&gt;e injetar diferentes implementações (&lt;/code&gt;PaymentServicePagarme&lt;code&gt;,&lt;/code&gt;PaymentServicePagseguro`, etc.).&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;3. Arquitetura Hexagonal (Ports and Adapters) ou clean arch&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A arquitetura &lt;strong&gt;Ports and Adapters&lt;/strong&gt; resolve um problema clássico: &lt;strong&gt;separar a lógica de negócio da infraestrutura&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;🔹 Como funciona?&lt;br&gt;
✅ &lt;strong&gt;Portas&lt;/strong&gt; (Ports) → Interfaces que sua aplicação expõe ou consome.&lt;br&gt;
✅ &lt;strong&gt;Adaptadores&lt;/strong&gt; (Adapters) → Traduções entre sua aplicação e serviços externos.&lt;/p&gt;

&lt;p&gt;Exemplo prático:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sua aplicação precisa enviar um email? Você define uma interface &lt;code&gt;EmailService&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Depois, pode implementar um &lt;code&gt;SendGridEmailService&lt;/code&gt;, desacoplando sua aplicação do serviço especifico.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Isso significa que, no futuro, &lt;strong&gt;se precisar trocar o sendgrid pelo SES, por exemplo, o impacto no código será mínimo&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;4. Utilize Eventos de Domínio (E faça as coisas de forma assíncrona)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Se você ainda acha que precisa chamar serviços externos &lt;strong&gt;de forma síncrona o tempo todo&lt;/strong&gt;, está perdendo uma grande oportunidade de melhorar a escalabilidade e resiliência do seu sistema.&lt;/p&gt;

&lt;p&gt;🔹 O que fazer?&lt;br&gt;
✅ &lt;strong&gt;Publicar eventos em vez de chamar APIs diretamente.&lt;/strong&gt;&lt;br&gt;
✅ Deixe outro serviço consumir o evento e interagir com a API externa.&lt;br&gt;
✅ Se o serviço externo estiver fora do ar, o evento pode ser processado depois.&lt;/p&gt;

&lt;p&gt;Isso reduz o &lt;strong&gt;acoplamento temporal&lt;/strong&gt;, ou seja, &lt;strong&gt;sua aplicação não precisa esperar uma resposta imediata do serviço externo para continuar funcionando&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;5. Mantenha o Domínio Isolado&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;🔹 O que isso significa na prática?&lt;br&gt;
✅ Seu &lt;strong&gt;modelo de domínio&lt;/strong&gt; não deve ter &lt;strong&gt;nada&lt;/strong&gt; relacionado a serviços externos.&lt;br&gt;
✅ Qualquer integração deve estar nas &lt;strong&gt;camadas externas da arquitetura&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Se seu domínio está cheio de chamadas para APIs de terceiros, &lt;strong&gt;você está cometendo um erro grave de design&lt;/strong&gt;. Uma boa prática é garantir que &lt;strong&gt;a camada de domínio não tenha imports de outras camadas&lt;/strong&gt;, mantendo-a &lt;strong&gt;pura e independente&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Anti-Corruption Layer (ACL): Blindando Seu Domínio Contra "Poluição Externa"&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Quando dois sistemas se comunicam, existe um risco de que &lt;strong&gt;um modelo de dados acabe "contaminando" o outro&lt;/strong&gt;. Para evitar isso, usamos a &lt;strong&gt;Anti-Corruption Layer (ACL)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;🔹 O que a ACL faz?&lt;br&gt;
✅ &lt;strong&gt;Traduz e adapta os dados&lt;/strong&gt; entre sistemas diferentes.&lt;br&gt;
✅ Evita que regras de negócio de um serviço externo afetem seu domínio.&lt;br&gt;
✅ Permite agregar dados de múltiplas fontes sem bagunçar sua aplicação.&lt;/p&gt;

&lt;p&gt;Alistair Cockburn até critica o nome "Anti-Corruption Layer" (acha que parece negativo), mas defende a ideia: &lt;strong&gt;é uma camada intermediária que traduz a comunicação entre seu sistema e um serviço externo para evitar que as regras externas "corrompam" seu domínio.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplo prático:&lt;/strong&gt;&lt;br&gt;
Se sua aplicação precisa se integrar a um ERP antigo, você não deve fazer chamadas diretas a ele. Em vez disso, cria-se uma &lt;strong&gt;ACL&lt;/strong&gt; que traduz os dados do ERP para um formato que sua aplicação entende, na pratica você vai usar o pattern adapter.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Contextos Delimitados: Entenda Onde Cada Conceito Faz Sentido&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;No &lt;strong&gt;Domain-Driven Design (DDD)&lt;/strong&gt;, um &lt;strong&gt;Contexto Delimitado&lt;/strong&gt; define &lt;strong&gt;onde um conceito faz sentido dentro do seu sistema&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;🔹 O que isso resolve?&lt;br&gt;
✅ Evita que um termo tenha significados diferentes dentro do mesmo sistema.&lt;br&gt;
✅ Ajuda na organização modular do código.&lt;br&gt;
✅ Facilita a modelagem de serviços independentes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplo prático:&lt;/strong&gt;&lt;br&gt;
O que significa "cliente"? No setor financeiro de um hospital, pode significar um paciente pagante. Já no setor de internação, "cliente" pode ser &lt;strong&gt;qualquer paciente&lt;/strong&gt;. &lt;strong&gt;O contexto muda completamente!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cada &lt;strong&gt;contexto delimitado&lt;/strong&gt; pode ter seu próprio modelo de dados, regras e até sua própria equipe de desenvolvimento.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dica:&lt;/strong&gt;&lt;br&gt;
Contextos bem definidos &lt;strong&gt;não significam automaticamente microserviços&lt;/strong&gt;, mas podem ajudar na &lt;strong&gt;modularização e escalabilidade&lt;/strong&gt; do sistema.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;As 4 Perguntas que Todo Arquiteto de Software Deve Fazer&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Ao avaliar uma proposta de design, um arquiteto de software precisa responder 4 perguntas essenciais:&lt;/p&gt;

&lt;p&gt;1️⃣ &lt;strong&gt;Essa solução atende aos objetivos do negócio?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Se não atende, não faz sentido implementá-la.
2️⃣ &lt;strong&gt;A solução respeita as restrições do projeto?&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Não adianta propor algo que não cabe dentro das limitações do sistema.
3️⃣ &lt;strong&gt;Ela cumpre os atributos de qualidade?&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Performance, escalabilidade, segurança, etc.
4️⃣ &lt;strong&gt;Existe uma alternativa mais barata ou menos arriscada?&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Se existir, &lt;strong&gt;volte para a prancheta&lt;/strong&gt; e refaça o planejamento.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;💡 Se a resposta para a quarta pergunta for "sim", é melhor reconsiderar a solução. Um bom arquiteto não busca apenas a "melhor" solução, mas sim a &lt;strong&gt;solução mais eficiente dentro do contexto do negócio&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusão&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Se você quer um sistema desacoplado de verdade, precisa aplicar boas práticas de arquitetura.&lt;/p&gt;

&lt;p&gt;🔹 &lt;strong&gt;Use Gateways&lt;/strong&gt; para encapsular integrações externas.&lt;br&gt;
🔹 &lt;strong&gt;Aplique DIP&lt;/strong&gt; para evitar dependências diretas.&lt;br&gt;
🔹 &lt;strong&gt;Adote Ports and Adapters&lt;/strong&gt; para separar seu domínio da infraestrutura.&lt;br&gt;
🔹 &lt;strong&gt;Use eventos assíncronos&lt;/strong&gt; para melhorar escalabilidade e resiliência.&lt;br&gt;
🔹 &lt;strong&gt;Proteja seu domínio com ACL&lt;/strong&gt; e &lt;strong&gt;defina contextos delimitados no DDD&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;O objetivo final é simples: &lt;strong&gt;um código flexível, fácil de manter e preparado para mudanças&lt;/strong&gt;. Se seu sistema ainda está acoplado diretamente a serviços externos, &lt;strong&gt;você está deixando um problema enorme para o futuro&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Agora, bora refatorar esse código! 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=AOIWUPjal60&amp;amp;list=TLGGMaacBIriC9UxNDAzMjAyNQ" rel="noopener noreferrer"&gt;Hexagonal Architecture (Ports and Adapters) with Alistair Cockburn // Live #98&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?list=TLGGm5-xFN3ig2wxNDAzMjAyNQ&amp;amp;v=9JBU-Fh3bz4" rel="noopener noreferrer"&gt;SOLID DIP Dependency Inversion Principle + Design Patterns Adapter&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?list=TLGGcj37oEUQjXkxNDAzMjAyNQ&amp;amp;v=tetVY6jmlnM" rel="noopener noreferrer"&gt;Como criar e desacoplar camadas usando SOLID&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?list=TLGG9YslJm1WW2UxNDAzMjAyNQ&amp;amp;v=6jHgd1LY6IE" rel="noopener noreferrer"&gt;10 perguntas sobre Domain-Driven Design&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?list=TLGGr7bjDWPIC1MxNDAzMjAyNQ&amp;amp;v=cz6EU7Z_BhE" rel="noopener noreferrer"&gt;Domain Driven Design do Jeito Certo&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?list=TLGGpFdV-xSBKOExNDAzMjAyNQ&amp;amp;v=NsQnmmIykoE" rel="noopener noreferrer"&gt;DDD, Domain-Driven Design com Elemar Jr. // Live #52&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?list=TLGG5KI3m6k5uYoxNDAzMjAyNQ&amp;amp;v=2LQkKU3dPGo" rel="noopener noreferrer"&gt;Event-Driven Architecture, Microservices e CQRS: A combinação perfeita&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>O que é Clean Architecture?</title>
      <dc:creator>Humberto Barbosa</dc:creator>
      <pubDate>Tue, 17 Jan 2023 01:38:54 +0000</pubDate>
      <link>https://dev.to/h1bertobarbosa/clean-architecture-53lj</link>
      <guid>https://dev.to/h1bertobarbosa/clean-architecture-53lj</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;O que é arquitetura de software?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Que raio é isso? O que isso faz? Vamos começar com algumas definições de caras que sabem o que estão falando.&lt;/p&gt;

&lt;p&gt;Robert Martin (Uncle Bob) diz o seguinte:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The goal of software architecture is to minimize the human resources required to build and maintain the required system.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ou seja, o objetivo da arquitetura de software é &lt;strong&gt;minimizar os recursos humanos necessários para construir e manter um sistema&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Já Martin Fowler define assim:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Software architecture is those decisions which are both important and hard to change.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ou seja, a arquitetura de software são as &lt;strong&gt;decisões importantes e difíceis de mudar&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Agora, bora descomplicar: arquitetura de software tem a ver com &lt;strong&gt;organização, estrutura, design, relacionamento e comportamento&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Se você já escreveu um software do zero ou participou da reescrita de um sistema legado, sabe do que estou falando. O chefe deu carta branca, escolheu-se tecnologia, servidores, frameworks… &lt;strong&gt;tudo isso são decisões arquiteturais.&lt;/strong&gt; E, adivinha? Elas vão te acompanhar enquanto o sistema estiver no ar.&lt;/p&gt;

&lt;p&gt;Essas decisões são afetadas por fatores como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O escopo do produto&lt;/li&gt;
&lt;li&gt;O orçamento da empresa (quanto tem para equipe, servidores, etc.)&lt;/li&gt;
&lt;li&gt;O volume de requisições&lt;/li&gt;
&lt;li&gt;O nível técnico da equipe (sênior, pleno, júnior, estagiários…)&lt;/li&gt;
&lt;li&gt;O prazo de entrega&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agora, pense comigo: se a empresa tem meia dúzia de clientes, faz sentido criar um sistema distribuído com Kafka, Kubernetes e banco replicado? Ou será que seria um gasto desnecessário?&lt;/p&gt;

&lt;p&gt;Cada tipo de software exige uma arquitetura diferente. Um &lt;strong&gt;ERP não é um jogo de RPG online&lt;/strong&gt;, uma &lt;strong&gt;plataforma de streaming não é um simples CLI&lt;/strong&gt;. Existem várias arquiteturas: &lt;strong&gt;monolítica, distribuída, cliente-servidor, orientada a eventos, serverless...&lt;/strong&gt; e cada uma resolve um problema específico.&lt;/p&gt;

&lt;p&gt;E só porque você usou &lt;strong&gt;Clean Architecture&lt;/strong&gt; em um projeto, &lt;strong&gt;não significa que precisa replicar isso em todos os outros&lt;/strong&gt;. Se você tem um sistema que só cadastra um e-mail numa newsletter, faz sentido implementar Clean Architecture, Hexagonal Architecture ou MVC? Não.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;O que é Clean Architecture?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Frz1gvbh6b1z4o7kuisxe.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Frz1gvbh6b1z4o7kuisxe.jpg" alt="Image description" width="772" height="567"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clean Architecture é um modelo arquitetural focado &lt;strong&gt;em desacoplar as regras de negócio dos recursos externos&lt;/strong&gt; (como banco de dados, frameworks, etc.).&lt;/p&gt;

&lt;p&gt;Exemplo: seu ORM deve ficar isolado na camada dele, fazendo apenas &lt;strong&gt;operações de banco&lt;/strong&gt; (salvar, atualizar, deletar). Enquanto isso, a entidade do ORM (que representa uma tabela) &lt;strong&gt;não deve ser a mesma entidade que contém as regras de negócio&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Como surgiu a Clean Architecture?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;O próprio Uncle Bob criou esse conceito enquanto desenvolvia um software junto com o filho dele. Era um sistema onde os usuários criavam testes baseados em uma wiki.&lt;/p&gt;

&lt;p&gt;Durante o projeto, ele percebeu que &lt;strong&gt;quando olhava para a estrutura de pastas, só via Rails&lt;/strong&gt;. Ele não queria ver Rails, queria enxergar o propósito da aplicação. O problema? &lt;strong&gt;O sistema estava totalmente dependente do framework&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Então, ele começou a &lt;strong&gt;separar as regras de negócio das dependências externas&lt;/strong&gt;, focando no core da aplicação e nos testes.&lt;/p&gt;

&lt;p&gt;Foi daí que surgiu a ideia: &lt;strong&gt;o centro da aplicação não é o banco de dados e nem o framework. O centro da aplicação são os casos de uso&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Use Cases: O Coração da Aplicação&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Uncle Bob definiu assim:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The center of your application is not the database, nor is it one or more of the frameworks you may be using. The center of your application is the use cases of your application.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ou seja, &lt;strong&gt;o centro da sua aplicação são os casos de uso&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Se liga: quando você projeta um sistema, qual a primeira coisa que a maioria das empresas pensa? No banco de dados. "Qual vai ser a tabela?", "Quais colunas precisa ter?"&lt;/p&gt;

&lt;p&gt;Esse pensamento está &lt;strong&gt;invertido&lt;/strong&gt;. O certo seria &lt;strong&gt;definir os casos de uso primeiro&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Casos de uso são as &lt;strong&gt;intenções do usuário dentro do sistema&lt;/strong&gt;. Exemplo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fazer check-in&lt;/li&gt;
&lt;li&gt;Adicionar itens ao carrinho&lt;/li&gt;
&lt;li&gt;Processar um pagamento&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esses casos de uso &lt;strong&gt;contêm as regras de negócio&lt;/strong&gt; e chamam as entidades para resolver as operações.&lt;/p&gt;

&lt;p&gt;E se, ao escrever um caso de uso, você percebe que ele depende de uma regra contida em outro caso de uso? A resposta é &lt;strong&gt;não reutilizar casos de uso diretamente&lt;/strong&gt;. Se isso aconteceu, significa que &lt;strong&gt;você identificou uma regra de negócio independente&lt;/strong&gt; e que ela deve estar na camada de entidades.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Entities: O Núcleo das Regras de Negócio&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Aqui entram as &lt;strong&gt;regras de negócio puras&lt;/strong&gt;, que podem ser aplicadas em diferentes contextos.&lt;/p&gt;

&lt;p&gt;E aqui está um erro comum: &lt;strong&gt;confundir entidade de regra de negócio com entidade de ORM&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A entidade do ORM &lt;strong&gt;mapeia o banco de dados&lt;/strong&gt; (ex: mapeamento de colunas para atributos). Já a entidade da Clean Architecture &lt;strong&gt;representa um conceito de negócio&lt;/strong&gt;, independente do banco.&lt;/p&gt;

&lt;p&gt;O que acontece se você misturar as duas coisas?&lt;/p&gt;

&lt;p&gt;Se adicionar decorators, annotations ou outras dependências do ORM dentro da sua entidade de regra de negócio, você cria &lt;strong&gt;alto acoplamento&lt;/strong&gt;. Resultado? Uma simples mudança na tabela do banco pode quebrar as regras de negócio.&lt;/p&gt;

&lt;p&gt;Entidades precisam ser &lt;strong&gt;independentes&lt;/strong&gt;. Elas podem ser classes ou simplesmente um conjunto de funções puras. &lt;strong&gt;A forma depende do seu estilo de código e do time&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Interface Adapters: A Ponte Entre Mundo Externo e Casos de Uso&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Essa camada &lt;strong&gt;traduz os dados&lt;/strong&gt; entre o mundo externo e a lógica de negócio.&lt;/p&gt;

&lt;p&gt;Aqui entra toda a arquitetura &lt;strong&gt;MVC&lt;/strong&gt;: controllers, middlewares, presenters...&lt;/p&gt;

&lt;p&gt;O fluxo é assim:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;O usuário faz uma requisição.&lt;/li&gt;
&lt;li&gt;O dado chega na camada de &lt;strong&gt;Interface Adapters&lt;/strong&gt;, que adapta e joga dentro de um DTO.&lt;/li&gt;
&lt;li&gt;O DTO vai para o caso de uso, que processa tudo e retorna um resultado.&lt;/li&gt;
&lt;li&gt;A resposta é adaptada novamente e enviada para o usuário.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Essa camada não deve conhecer detalhes como banco de dados, mensageria, etc.&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Frameworks and Drivers: O Mundo Externo&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Essa é a camada mais externa. Aqui entram:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Banco de dados&lt;/li&gt;
&lt;li&gt;Redis&lt;/li&gt;
&lt;li&gt;Nginx&lt;/li&gt;
&lt;li&gt;Kafka&lt;/li&gt;
&lt;li&gt;Qualquer outra dependência externa&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A ideia é &lt;strong&gt;manter esses componentes isolados&lt;/strong&gt;, evitando que impactem a lógica de negócio.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusão&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Não confunda &lt;strong&gt;camadas lógicas&lt;/strong&gt; com &lt;strong&gt;pastas no projeto&lt;/strong&gt;. Você pode jogar todos os arquivos na raiz e ainda assim manter as camadas organizadas. O que define as camadas &lt;strong&gt;é a dependência&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;O que está fora pode depender do que está dentro&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;O que está dentro nunca pode depender do que está fora&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Vantagens da Clean Architecture&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;✔ &lt;strong&gt;Isolamento das regras de negócio&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;Definição clara de camadas e responsabilidades&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;Fluxo de dependência ordenado e direcional&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;Facilidade para testar&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;Independência de frameworks e banco de dados&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
✔ &lt;strong&gt;Facilidade para evolução tecnológica&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Links Úteis&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html" rel="noopener noreferrer"&gt;Uncle Bob - The Clean Architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://engsoftmoderna.info/artigos/arquitetura-limpa.html" rel="noopener noreferrer"&gt;Engenharia de Software Moderna - Arquitetura Limpa&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=NYoW-ycqbYk" rel="noopener noreferrer"&gt;Vídeo Explicativo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>softwareengineering</category>
      <category>softwaredevelopment</category>
      <category>dotnet</category>
      <category>aspnet</category>
    </item>
    <item>
      <title>O que é runtime javascript ?</title>
      <dc:creator>Humberto Barbosa</dc:creator>
      <pubDate>Mon, 02 Jan 2023 12:18:06 +0000</pubDate>
      <link>https://dev.to/h1bertobarbosa/o-que-e-runtime-javascript--55bd</link>
      <guid>https://dev.to/h1bertobarbosa/o-que-e-runtime-javascript--55bd</guid>
      <description>&lt;h2&gt;
  
  
  O que é o ambiente de execução(runtime environment) ?
&lt;/h2&gt;

&lt;p&gt;No contexto do browser esse ambiente de execução é composto por:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Javascript Engine&lt;/li&gt;
&lt;li&gt;Web API&lt;/li&gt;
&lt;li&gt;Fila de callbacks(The callback queue)&lt;/li&gt;
&lt;li&gt;Loop de eventos(Event Loop)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ftm6rtjjni7ma2p5u6i8a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ftm6rtjjni7ma2p5u6i8a.png" alt="Image description" width="800" height="487"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Javascript Engine
&lt;/h2&gt;

&lt;p&gt;Javascript Engine é um programa que executa código JavaScript. É o que torna possível a execução de código JavaScript em um navegador web ou em um ambiente de servidor, como o Node.js e agora mais recentemente o Deno.&lt;/p&gt;

&lt;p&gt;Cada navegador web tem sua própria implementação de uma engine JavaScript, como o JavaScript V8 da Google, que é usado no Chrome e no Chromium, ou o Spider Monkey da Mozilla, que é usado no Firefox.&lt;/p&gt;

&lt;p&gt;As engines JavaScript são otimizadas para interpretar e executar o código JavaScript de maneira rápida e eficiente. Elas fazem isso através de diversas técnicas, como pré-compilação de código e otimização de memória. As engines também implementam APIs JavaScript, como a API do Document Object Model (DOM), que permite que o código JavaScript acesse e manipule elementos HTML na página da web.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Call Stack&lt;/strong&gt;: Dentro dessa engine nos temos a call stack e memory heap, toda vez que agente executa um código javascript as funções vão para a call stack que é o local onde as funções são empilhadas para serem executadas, essa estrutura é formada ultimo a entrar é primeiro a sair e só passa para a próxima execução quando concluir a atual.&lt;br&gt;
Caso existe uma função da web api na call stack essa função é enviada para lá, apos o termino da execução o callback é enviado para a fila de callback(callback queue) para retornar pra call stack pra concluir a execução do código&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory Heap&lt;/strong&gt;: é um "pedaço" da memória do computador que é usada para alocar novos objetos. Quando um novo objeto é criado no código JavaScript, ele é alocado na memory heap.&lt;/p&gt;

&lt;p&gt;A memory heap é dividida em duas partes: new space e old space. O new space é usada para alocar novos objetos e é otimizada para alocação rápida. O old space é usado para objetos que são mantidos por mais tempo e é otimizada para acesso rápido.&lt;/p&gt;

&lt;p&gt;Quando new space está cheia, o V8 realiza uma operação chamada garbage collection, durante a qual ele examina os objetos no new space e remove aqueles que não são mais usados ​​pelo código. Os objetos que ainda são usados ​​são movidos para o old space. Isso libera espaço no new space para novos objetos.&lt;/p&gt;

&lt;p&gt;O V8 também faz o garbage collection no old space, mas elas são menos frequentes e mais lentas do que as coletas no new space, pois envolvem a verificação de todos os objetos no old space.&lt;/p&gt;

&lt;p&gt;Espero que isso tenha esclarecido um pouco sobre como a memory heap funciona no JavaScript V8.&lt;/p&gt;

&lt;h2&gt;
  
  
  Web API
&lt;/h2&gt;

&lt;p&gt;JavaScript Web APIs são conjuntos de interfaces de programação de aplicativos (APIs) que fornecem acesso a recursos do navegador e do sistema operacional. Eles permitem a criação de aplicativos web que possam fazer coisas como acessar a câmera e o microfone do usuário, enviar solicitações HTTP, manipular o DOM e muito mais. Alguns exemplos de JavaScript Web APIs incluem:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Geolocation API&lt;/strong&gt;: permite que os aplicativos web acessem as informações de localização do usuário.&lt;br&gt;
&lt;strong&gt;Web Audio API&lt;/strong&gt;: permite que os aplicativos web reproduzam áudio e criem efeitos de áudio complexos.&lt;br&gt;
&lt;strong&gt;Web Storage API&lt;/strong&gt;: permite que os aplicativos web armazenem dados no navegador do usuário, como informações de login ou preferências de usuário.&lt;br&gt;
Essas são apenas algumas das muitas APIs disponíveis para os desenvolvedores de aplicativos web. Elas fornecem uma ampla gama de recursos que podem ser usados ​​para criar aplicativos web poderosos e interativos.&lt;br&gt;
O famoso setTimeout, ajax(xmlhttprequest) fazem parte da web api&lt;/p&gt;

&lt;h2&gt;
  
  
  Callback queue e Event Loop
&lt;/h2&gt;

&lt;p&gt;A fila de callbacks, também conhecida como a "fila de eventos", é uma fila de funções que são chamadas quando um evento específico ocorre. No JavaScript, esses eventos podem incluir coisas como o carregamento de uma página web, o clique em um botão ou o recebimento de uma resposta de uma solicitação HTTP.&lt;/p&gt;

&lt;p&gt;Quando um evento ocorre, a função de callback associada a ele é adicionada à fila de callbacks. O JavaScript possui um loop de eventos que executa continuamente e verifica a fila de callbacks para ver se há funções para serem chamadas. Quando uma função está disponível na fila, ela é removida da fila e chamada. Isso permite que o código JavaScript responda a eventos de maneira assíncrona.&lt;/p&gt;

&lt;p&gt;Por exemplo, quando um usuário clica em um botão em uma página web, é adicionada uma função de callback à fila de callbacks. Quando o loop de eventos verifica a fila, essa função é chamada e o código associado ao clique no botão é executado. Isso permite que o código continue a ser executado enquanto o navegador está ocupado processando o clique do botão, sem bloquear a interface do usuário.&lt;/p&gt;

&lt;h2&gt;
  
  
  Node.js
&lt;/h2&gt;

&lt;p&gt;O node.js é uma runtime para executar o javascript no backend a diferença do browser é que em vez de ter a Web Api ele tem a libuv que é onde ocorre a execuçaõ de funções assincronas.&lt;/p&gt;

&lt;p&gt;Se você quer visualizar essas coisas acontecendo tem esse site &lt;a href="http://latentflip.com/loupe" rel="noopener noreferrer"&gt;http://latentflip.com/loupe&lt;/a&gt; onde é possivel ver o código passando pelos mecanismos da runtime, ao entrar no site já existe um código de exemplo mas você pode colocar esse abaixo ou inventar algum:&lt;/p&gt;

&lt;p&gt;`&lt;br&gt;
console.log("Hi!");&lt;/p&gt;

&lt;p&gt;setTimeout(function timeout() {&lt;br&gt;
    console.log("5 segundos depois");&lt;br&gt;
}, 5000);&lt;/p&gt;

&lt;p&gt;console.log("executei antes do setTimeout");&lt;br&gt;
`&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Links pesquisados:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://medium.com/@gemma.croad/understanding-the-javascript-runtime-environment-4dd8f52f6fca" rel="noopener noreferrer"&gt;https://medium.com/@gemma.croad/understanding-the-javascript-runtime-environment-4dd8f52f6fca&lt;/a&gt;&lt;br&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Introduction" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Introduction&lt;/a&gt;&lt;br&gt;
&lt;a href="https://nodejs.org/en/docs/guides/diagnostics/memory/using-gc-traces/" rel="noopener noreferrer"&gt;https://nodejs.org/en/docs/guides/diagnostics/memory/using-gc-traces/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
