<?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>Forem: Clinton Rocha</title>
    <description>The latest articles on Forem by Clinton Rocha (@clintonrocha98).</description>
    <link>https://forem.com/clintonrocha98</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%2F988211%2Ff8ebabd6-a886-468e-ad5f-79c5adf2d3a5.jpeg</url>
      <title>Forem: Clinton Rocha</title>
      <link>https://forem.com/clintonrocha98</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/clintonrocha98"/>
    <language>en</language>
    <item>
      <title>Criei uma pipeline de planejamento no OpenCode e olha no que deu</title>
      <dc:creator>Clinton Rocha</dc:creator>
      <pubDate>Mon, 09 Mar 2026 04:37:00 +0000</pubDate>
      <link>https://forem.com/he4rt/sistema-de-planejamento-estruturado-no-opencode-16pb</link>
      <guid>https://forem.com/he4rt/sistema-de-planejamento-estruturado-no-opencode-16pb</guid>
      <description>&lt;p&gt;Você é como eu e vem buscando formas de otimizar o uso de ferramentas como o &lt;a href="https://opencode.ai/docs/pt-br" rel="noopener noreferrer"&gt;OpenCode&lt;/a&gt;? Talvez este conteúdo te ajude a ter novas ideias e até mesmo entender alguns fluxos dessa e de outras ferramentas.&lt;/p&gt;

&lt;p&gt;Enquanto eu estudava a documentação do OpenCode, encontrei a aba de &lt;a href="https://pt.wikipedia.org/wiki/Plug-in" rel="noopener noreferrer"&gt;plugins&lt;/a&gt; feitos pela comunidade. Ali, encontrei três plugins que, na minha visão, se complementam bem. Na verdade, um deles eu já utilizava: o &lt;a href="https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin" rel="noopener noreferrer"&gt;&lt;strong&gt;Plannotator&lt;/strong&gt;&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;A partir disso, comecei a estudar como funcionava os comandos, agentes e como eu poderia fazer um fluxo que fizesse sentido e principalmente que funcionasse, calma que já te explico oq cada um dos plugins fazem e qual a ideia final da integração.&lt;/p&gt;

&lt;h1&gt;
  
  
  Índice
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Como eu estava usando o OpenCode&lt;/li&gt;
&lt;li&gt;Objetivo da integração&lt;/li&gt;
&lt;li&gt;Plannotator: Revisão Visual&lt;/li&gt;
&lt;li&gt;Octto: Coleta estruturada de contexto&lt;/li&gt;
&lt;li&gt;Subtask2: Orquestração de Pipeline&lt;/li&gt;
&lt;li&gt;Comandos&lt;/li&gt;
&lt;li&gt;Considerações&lt;/li&gt;
&lt;li&gt;Referências&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Como eu estava usando o OpenCode
&lt;/h1&gt;

&lt;p&gt;Após começar a utilizar o OpenCode, notei o quão importante é o uso do módulo de planejamento e, principalmente, não apenas o planejamento em si, mas também as perguntas que são feitas durante esse processo. O resultado dessas duas novas abordagens (planejamento e perguntas) melhora bastante não só o código produzido, mas também a minha compreensão sobre a regra de negócio, além de comportamentos e fluxos do sistema.&lt;/p&gt;

&lt;p&gt;Mesmo com todas essas descobertas que trouxeram otimizações para o processo, eu ainda sentia que dava para melhorar mais.&lt;/p&gt;

&lt;p&gt;O fluxo de uso do OpenCode era basicamente o seguinte: eu enviava o prompt, a ferramenta vasculhava o código para obter contexto, depois vinham algumas perguntas e, em seguida, ela ia para a parte de &lt;em&gt;build&lt;/em&gt;, ou seja, para colocar em prática o que tinha sido planejado.&lt;/p&gt;

&lt;h1&gt;
  
  
  Objetivo da integração
&lt;/h1&gt;

&lt;p&gt;A ideia vai ser conseguir extrair o máximo de contexto com o &lt;code&gt;Octto&lt;/code&gt;, usar o &lt;code&gt;subtask2&lt;/code&gt; para orquestrar os comandos e visualizar o plano final com &lt;code&gt;Plannotator&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+---------------------------------------------------------------+
|                                                               |
|  IDEIA -&amp;gt; CONTEXTO -&amp;gt; PLANO -&amp;gt; REFINAMENTO -&amp;gt; REVISAO -&amp;gt; OK   |
|                                                               |
+---------------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O resultado é um &lt;strong&gt;único comando&lt;/strong&gt; que orquestra todo o processo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/generate-plan &lt;span class="s2"&gt;"descrição do objetivo"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Plannotator: Revisão visual
&lt;/h1&gt;

&lt;p&gt;O primeiro plugin chegou até mim por recomendação de uma amiga da comunidade (&lt;a href="https://github.com/he4rt/" rel="noopener noreferrer"&gt;He4rtDevs&lt;/a&gt;), a &lt;a href="https://dev.to/cherryramatis"&gt;Cherry&lt;/a&gt;, e o plugin era o &lt;a href="https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin" rel="noopener noreferrer"&gt;Plannotator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Esse plugin basicamente faz com que, ao final de um planejamento, seja aberta uma página no navegador contendo todo o plano gerado. Isso facilita muito a visualização em comparação com o terminal. Na interface do navegador, você consegue selecionar trechos do planejamento e dar feedback, que retorna para o processo de planejamento. Também é possível aprovar o plano e seguir diretamente para a etapa de &lt;em&gt;build&lt;/em&gt;, ou seja, aplicar o que foi planejado.&lt;/p&gt;

&lt;h1&gt;
  
  
  Octto: Coleta estruturada de contexto
&lt;/h1&gt;

&lt;p&gt;O &lt;a href="https://github.com/vtemian/octto" rel="noopener noreferrer"&gt;Octto&lt;/a&gt; quando você envia o primeiro prompt, ele abre uma página no navegador com perguntas relacionadas ao que você pediu inicialmente. Essa página funciona como uma interface interativa de brainstorming. Conforme você responde às perguntas, o sistema utiliza essas respostas para gerar novas perguntas dentro da mesma sessão, aprofundando o entendimento do problema e ajudando a estruturar melhor o contexto antes de seguir para as próximas etapas, ao final ele gera um arquivo &lt;code&gt;.md&lt;/code&gt; no diretório &lt;code&gt;/docs/plans&lt;/code&gt; dentro do projeto.&lt;/p&gt;

&lt;p&gt;A unica configuração que adicionei a ele, foi uma que faz com que a primeira pergunta seja um campo de texto livre onde o usuário consiga descrever o contexto com maior liberdade (colocar uma task completa, por exemplo).&lt;/p&gt;

&lt;h2&gt;
  
  
  Fluxo de Funcionamento
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+----------------------+
|       ask_text       |  &amp;lt;-- Primeira ação obrigatória
+----------+-----------+
           |
           | Campo de texto no browser:
           | "Descreva com detalhes o que
           | você quer planejar..."
           v
+----------------------+
|   create_brainstorm  |  &amp;lt;-- Agente inicia sessão
+----------+-----------+      com contexto coletado
           |
           | Define branches de exploração
           v
+--------------------------------------------------------------+
|                    BRANCHES DE EXPLORAÇÃO                    |
|                                                              |
|  +----------------+  +-------------------+  +---------------+|
|  | Motivação &amp;amp;    |  | Requisitos &amp;amp;      |  | Riscos &amp;amp;      ||
|  | Objetivos      |  | Restrições        |  | Dependências  ||
|  +--------+-------+  +---------+---------+  +-------+-------+|
|           |                    |                    |        |
+-----------+--------------------+--------------------+--------+
            |
            v
+----------------------+
|      BROWSER UI      |
|                      |
|  [ Pergunta 1 ]      |
|  [ Pergunta 2 ]      |
|  [ Pergunta N ]      |
|                      |
|      [Responder]     |
+----------+-----------+
           |
           | Usuário responde
           v
+----------------------+
| await_brainstorm_    |
| complete             |  &amp;lt;-- Agente aguarda respostas
+----------+-----------+
           |
           | Sintetiza respostas
           v
+----------------------+
|      docs/plans/     |
| 2026-03-08-objetivo  |  &amp;lt;-- Arquivo gerado
|        .md           |
+----------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configuração via Fragments
&lt;/h2&gt;

&lt;p&gt;O comportamento do Octto é customizado através de &lt;strong&gt;fragments&lt;/strong&gt;, instruções adicionadas ao prompt dos agentes internos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"fragments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"octto"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"Sempre pergunte a motivação e o 'porquê' das mudanças"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"Gere nomes de arquivo no formato: YYYY-MM-DD-slug.md"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"Salve os planos em docs/plans/"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"probe"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"Priorize perguntas sobre motivações e restrições"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"Inclua perguntas sobre requisitos não-funcionais"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"bootstrapper"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"Crie branches focados em: requisitos, arquitetura, riscos"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Função de cada agente interno:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;bootstrapper&lt;/strong&gt;: cria a estrutura inicial de branches&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;probe&lt;/strong&gt; : gera perguntas de aprofundamento&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;octto&lt;/strong&gt;: define o comportamento geral da coleta de contexto&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Subtask2: Orquestração de pipeline
&lt;/h1&gt;

&lt;p&gt;O &lt;a href="https://github.com/spoons-and-mirrors/subtask2" rel="noopener noreferrer"&gt;Subtask2&lt;/a&gt; permite &lt;strong&gt;encadear comandos&lt;/strong&gt; de forma sequencial. Quando um comando termina, o próximo da cadeia é executado automaticamente. &lt;/p&gt;

&lt;p&gt;Nesse meu contexto só vou usar a funcionalidade de &lt;code&gt;return&lt;/code&gt;, mas esse plugin tem muitas outras funcionalidades interessantes como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;loop&lt;/code&gt; de subtarefas até que a condição do usuário seja atendida&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;paralela&lt;/code&gt; de subtarefas simultaneamente - PR pendente.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$TURN[n]&lt;/code&gt; passa turnos da sessão (mensagens do usuário/assistente).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;{as:name}&lt;/code&gt; + &lt;code&gt;$RESULT[name]&lt;/code&gt; captura e referência as saídas das subtarefas.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Sintaxe de Return Chain
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;subtask&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;return&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/comando-1&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/comando-2&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/comando-3&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Comandos
&lt;/h1&gt;

&lt;p&gt;Com o &lt;code&gt;subtask2&lt;/code&gt;, consigo adicionar comandos ao fluxo, e isso abre muitas possibilidades. Mas, por enquanto, estou com os pés no chão e vou fazer um fluxo simples com alguns novos comandos.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Eu criei esses comandos com o único intuito de usar na pipeline.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Comando Principal
&lt;/h2&gt;

&lt;p&gt;O comando que vai dar inicio a todo o fluxo, vai ser o &lt;code&gt;/generate-plan&lt;/code&gt; ao executar, ele da inicio a pipeline de planejamento.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Você é livre para escolher qualquer nome para o comando, para escolher o nome desse aqui eu só segui as vozes da minha cabeça.&lt;/p&gt;

&lt;p&gt;Caso queira saber mais sobre como criar e configurar &lt;a href="https://opencode.ai/docs/pt-br/commands/" rel="noopener noreferrer"&gt;comandos no opencode&lt;/a&gt;, a doc é legalzinha.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/generate-plan refatorar sistema de autenticação
/generate-plan &lt;span class="s2"&gt;"adicionar suporte a múltiplos gateways de pagamento"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As aspas são opcionais: tudo após o comando é passado como &lt;code&gt;$ARGUMENTS&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pipeline completo de planejamento&lt;/span&gt; 
&lt;span class="na"&gt;agent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;octto&lt;/span&gt;
&lt;span class="na"&gt;subtask&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;return&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/refine-plan&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/review-plan&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

prompt aqui, e lembre de usar o $ARGUMENTS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Caso você queira ver como deixei o meu &lt;a href="https://gist.github.com/Clintonrocha98/f9f5cb146a799a3a2a340ef12a0bf9bf#file-prompt-generate-plan-md" rel="noopener noreferrer"&gt;prompt usado no comando generate-plan&lt;/a&gt; é só ir no gist.&lt;/p&gt;

&lt;p&gt;Todos os comandos podem ser usados individualmente/isolado no OpenCode, a unica diferença ao usar um comando com o &lt;code&gt;subtask&lt;/code&gt; é que ele vai ser executado em um contexto diferente.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Refinamento Técnico
&lt;/h2&gt;

&lt;p&gt;O &lt;code&gt;/refine-plan&lt;/code&gt; tem como objetivo expandir um plano existente com detalhes arquiteturais.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/refine-plan &lt;span class="c"&gt;# usa plano mais recente&lt;/span&gt;
/refine-plan docs/plans/meu-plano.md &lt;span class="c"&gt;# plano específico&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;refine-plan&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Expande e refina tecnicamente um plano existente com arquitetura e diagramas&lt;/span&gt;
&lt;span class="na"&gt;subtask&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

Mesma coisa que o anterior, aqui você consegue adicionar a instrução que você quiser.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;No meu caso, o prompt que estou sando tá no &lt;a href="https://gist.github.com/Clintonrocha98/f9f5cb146a799a3a2a340ef12a0bf9bf#file-refine-plan-md" rel="noopener noreferrer"&gt;gist 'refine-plan.md'&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Revisão Visual
&lt;/h2&gt;

&lt;p&gt;Por último vem o comando &lt;code&gt;/review-plan&lt;/code&gt; com o objetivo de mandar o plano para revisão interativa via Plannotator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/review-plan &lt;span class="c"&gt;# usa plano mais recente&lt;/span&gt;
/review-plan docs/plans/meu-plano.md &lt;span class="c"&gt;# plano específico&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Importante:&lt;/strong&gt; Este comando &lt;strong&gt;não usa &lt;code&gt;subtask: true&lt;/code&gt;&lt;/strong&gt;. Ele roda na sessão primária para que a ferramenta &lt;code&gt;submit_plan&lt;/code&gt; possa abrir a interface do Plannotator no browser corretamente. Comandos rodando como subtarefa não conseguem inicializar a UI do browser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fluxo Completo de Execução:&lt;/strong&gt;&lt;/p&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%2Fc22oiuapqumis0k3m5ns.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%2Fc22oiuapqumis0k3m5ns.png" alt="diagrama contendo todo o fluxo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Considerações
&lt;/h1&gt;

&lt;p&gt;O mais importante de tudo: funcionou? Sim. É uma bazuca? Sim, hahahaha. Esse projeto acabou saindo porque entrei em hiperfoco ao me fazer a pergunta “será que funciona?”. No fim, tive minha resposta.&lt;/p&gt;

&lt;p&gt;Olhando para a usabilidade no dia a dia, acredito que os melhores momentos para utilizar algo assim são em novas &lt;em&gt;features&lt;/em&gt;, refatoração de projeto e até mesmo para estruturar estudos, quem sabe. Só não use para algo como “quero trocar a cor de um botão”, aí você acaba complicando.&lt;/p&gt;

&lt;p&gt;O ponto que mais curti foi o &lt;code&gt;Octto&lt;/code&gt;, com as perguntas geradas de forma dinâmica. Aquilo ali, ao meu ver, auxilia na contextualização de uma baita maneira. Fora que é possível dar instruções para as &lt;em&gt;branches&lt;/em&gt; dele, especificar qual tipo de input você quer ou não quer, entre outras coisas (vale ler a documentação).&lt;/p&gt;

&lt;p&gt;Já o &lt;code&gt;subtask2&lt;/code&gt; abre portas para muita coisa. Como eu tinha dito antes, acabei indo pelo simples, mas alguém com a mente mais aberta provavelmente vai conseguir extrair o melhor da ferramenta.&lt;/p&gt;

&lt;p&gt;Eu pretendo criar novos comandos, refinar mais os &lt;em&gt;prompts&lt;/em&gt; e ver o que acontece. É isso, obrigado por ler até aqui e tente brincar com isso ai.&lt;/p&gt;

&lt;p&gt;Como meu &lt;em&gt;Tech Lead&lt;/em&gt; fala: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;Faça codigo inútil e quebre alguma coisa.&lt;/code&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://opencode.ai/docs/commands/" rel="noopener noreferrer"&gt;OpenCode - Comandos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://opencode.ai/docs/agents/" rel="noopener noreferrer"&gt;OpenCode - Agentes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/spoons-and-mirrors/subtask2" rel="noopener noreferrer"&gt;Subtask2 - GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/backnotprop/plannotator/tree/main/apps/opencode-plugin" rel="noopener noreferrer"&gt;Plannotator - Plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/vtemian/octto" rel="noopener noreferrer"&gt;Octto - GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/%40summer12126/what-does-adhoc-mean-in-sw-development-2196f09826d6" rel="noopener noreferrer"&gt;what does ad-hoc&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>braziliandevs</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Laravel Modular [anotações]</title>
      <dc:creator>Clinton Rocha</dc:creator>
      <pubDate>Tue, 12 Aug 2025 13:13:41 +0000</pubDate>
      <link>https://forem.com/clintonrocha98/laravel-modular-anotacoes-56ai</link>
      <guid>https://forem.com/clintonrocha98/laravel-modular-anotacoes-56ai</guid>
      <description>&lt;p&gt;Salve, tudo bem com você?&lt;br&gt;&lt;br&gt;
Então, este conteúdo é basicamente composto pelas minhas anotações feitas enquanto eu estudava sobre arquitetura modular no Laravel. Meu objetivo durante o estudo era entender quais configurações necessárias no Laravel que me permitiriam utilizar esse tipo de estratégia na arquitetura. Acabou que encontrei informações sobre essas configurações, mas, além disso, também descobri ferramentas que agilizam esse processo.&lt;/p&gt;

&lt;p&gt;Além do conteúdo sobre modularização, aqui você vai encontrar informações sobre padrões de &lt;em&gt;design&lt;/em&gt; e um pouco de boas práticas. Como isso aqui é um subproduto dos meus estudos, tem muita coisa sobre o Laravel que acabei aprendendo durante o processo. Pode parecer óbvio para você, mas não para o “eu” do passado.&lt;/p&gt;

&lt;p&gt;Já adianto: meu objetivo aqui é trazer pontos que considerei relevantes durante os estudos. Para você, talvez pareçam “informações jogadas”, mas eu geralmente estudo a partir de palavras-chave ou tópicos, usando-os como ponto de partida para outras pesquisas (Google, YouTube e artigos). Então, não tenho a pretensão de ensinar algo neste conteúdo.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Foi utilizada IA para organizar as minhas anotações em tópicos e gerar o &lt;em&gt;table of contents&lt;/em&gt;. Você provavelmente não entenderia a sopa de letrinhas e inúmeros &lt;em&gt;bullet points&lt;/em&gt; que produzi durante meus estudos, então utilizei essa famosa ferramenta para auxiliar na organização de tudo por aqui.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h1&gt;
  
  
  Table of contents
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;1. Configuração de Módulos  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1.1. Autoloading (PSR-4)
&lt;/li&gt;
&lt;li&gt;1.2. Service Providers
&lt;/li&gt;
&lt;li&gt;1.3. Testes Modulares
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;2. Modelos, Factories e DTOs  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2.1. Conectando Factories a Models
&lt;/li&gt;
&lt;li&gt;2.2. Actions
&lt;/li&gt;
&lt;li&gt;2.3. Definindo Status de Modelos
&lt;/li&gt;
&lt;li&gt;2.4. Data Transfer Objects (DTOs)
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;3. IDE Helper    &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3.1. Instalação e Uso
&lt;/li&gt;
&lt;li&gt;3.2. Scripts para Composer
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;4. Views Modulares  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;4.1. Vistas Normais
&lt;/li&gt;
&lt;li&gt;4.2. Componentes Anônimos
&lt;/li&gt;
&lt;li&gt;4.3. Componentes de Classe
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;5. Ferramentas e Plugins  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;5.1. Laravel IDEA
&lt;/li&gt;
&lt;li&gt;5.2. Pacote Laravel Modules
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;6. Organização de Código: Abordagens  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;6.1. Vertical Slice
&lt;/li&gt;
&lt;li&gt;6.2. Agrupamento por Tipo (Grouping by Type)
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;7. Padrões de Design e Boas Práticas  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;7.1. Acoplamento Temporal vs. Eventos
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;8. Outros Tópicos  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;8.1. Sequences em Factories
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  1. Configuração de Módulos
&lt;/h1&gt;
&lt;h3&gt;
  
  
  1.1. Autoloading (PSR-4)
&lt;/h3&gt;

&lt;p&gt;Para usar o Laravel de forma modular, é necessário informar o novo módulo no arquivo &lt;code&gt;composer.json&lt;/code&gt;. Isso permite que o &lt;strong&gt;autoload&lt;/strong&gt; funcione, garantindo que as classes do seu módulo sejam encontradas.&lt;/p&gt;

&lt;p&gt;Se quiser saber mais: &lt;a href="https://www.php-fig.org/psr/psr-4/" rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  1.2. Service Providers
&lt;/h3&gt;

&lt;p&gt;O &lt;code&gt;Service Provider&lt;/code&gt; é o coração de um módulo. Cada provider herda de uma classe base chamada &lt;code&gt;ServiceProvider&lt;/code&gt; e possui dois métodos principais:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;register()&lt;/code&gt;: Chamado primeiro, para registrar serviços e bindings.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;boot()&lt;/code&gt;: Chamado após todos os métodos &lt;code&gt;register()&lt;/code&gt; dos providers, para inicializar serviços e configurar funcionalidades (como rotas e views).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para registrar um novo provider, ele deve ser informado no arquivo &lt;code&gt;config/app.php&lt;/code&gt; (ou configurado para ser descoberto automaticamente).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://laravel.com/docs/12.x/providers" rel="noopener noreferrer"&gt;A doc do Laravel é uma mãe, se quiser mais informação sobre o tópico, recomendo!&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  1.3. Testes Modulares
&lt;/h3&gt;

&lt;p&gt;Para usar testes de forma modular, é necessário registrar o módulo no arquivo &lt;code&gt;phpunit.xml&lt;/code&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  2. Modelos, Factories e DTOs
&lt;/h1&gt;
&lt;h3&gt;
  
  
  2.1. Conectando Factories a Models
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Por padrão, as factories procuram pelas models no namespace &lt;code&gt;App\Models&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Para conectar uma factory a uma model, defina a model no atributo &lt;code&gt;$model&lt;/code&gt; da factory.&lt;/li&gt;
&lt;li&gt;Quando o caminho padrão da factory é alterado, é preciso informar ao Laravel onde ela está. Use o método estático &lt;code&gt;newFactory()&lt;/code&gt; na model:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Modules\Product\Database\Factories\ProductFactory&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;Product&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;newFactory&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="nc"&gt;ProductFactory&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;new&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;Saiba mais em:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://laravel.com/docs/12.x/eloquent" rel="noopener noreferrer"&gt;Eloquent: Getting Started&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://laravel.com/docs/12.x/eloquent-factories" rel="noopener noreferrer"&gt;Eloquent: Factories&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  2.2. Actions
&lt;/h3&gt;

&lt;p&gt;No Laravel, é uma convenção usar a pasta &lt;code&gt;Actions&lt;/code&gt; para agrupar comportamentos e ações, similar aos conceitos de &lt;code&gt;usecase&lt;/code&gt; ou &lt;code&gt;service&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  2.3. Definindo Status de Modelos
&lt;/h3&gt;

&lt;p&gt;É possível definir um status em uma instância de model sem persistir no banco de dados. Exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="no"&gt;STATUS_PENDING&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'pending'&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;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;startForUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$userId&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;self&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;self&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="s1"&gt;'user_id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s1"&gt;'status'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;STATUS_PENDING&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;
  
  
  2.4. Data Transfer Objects (DTOs)
&lt;/h3&gt;

&lt;p&gt;Os DTOs são úteis para &lt;strong&gt;reduzir o acoplamento&lt;/strong&gt; e &lt;strong&gt;melhorar a clareza&lt;/strong&gt;. Eles podem ser usados para:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Comunicação entre diferentes camadas do código.&lt;/li&gt;
&lt;li&gt;Reduzir o número de parâmetros em métodos.&lt;/li&gt;
&lt;li&gt;Representar coleções de dados (Collections).&lt;/li&gt;
&lt;li&gt;Usar métodos estáticos (&lt;code&gt;fromEloquentModel&lt;/code&gt; ou &lt;code&gt;fromEloquentCollection&lt;/code&gt;) para instanciar DTOs a partir de models ou collections do Eloquent.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProductDTO&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;function&lt;/span&gt; &lt;span class="n"&gt;__construct&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="kt"&gt;int&lt;/span&gt; &lt;span class="nv"&gt;$id&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="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$name&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="kt"&gt;string&lt;/span&gt; &lt;span class="nv"&gt;$sku&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="kt"&gt;float&lt;/span&gt; &lt;span class="nv"&gt;$price&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="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;fromEloquentModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Product&lt;/span&gt; &lt;span class="nv"&gt;$product&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;self&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;self&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$product&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$product&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;sku&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$product&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;sku&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;$product&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;price&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="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;fromEloquentCollection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Collection&lt;/span&gt; &lt;span class="nv"&gt;$products&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;Collection&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$products&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Product&lt;/span&gt; &lt;span class="nv"&gt;$product&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;self&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;fromEloquentModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$product&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;Saiba mais em:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/@mohammad.roshandelpoor/dto-data-transfer-objects-in-laravel-6b391e1c2c29" rel="noopener noreferrer"&gt;DTO (Data Transfer Objects) in PHP (Laravel)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://qirolab.com/posts/how-to-use-dtos-for-cleaner-code-in-laravel" rel="noopener noreferrer"&gt;How to Use DTOs for Cleaner Code in Laravel, Best Practices and Implementation Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. IDE Helper
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3.1. Instalação e Uso
&lt;/h3&gt;

&lt;p&gt;O &lt;a href="https://github.com/barryvdh/laravel-ide-helper" rel="noopener noreferrer"&gt;&lt;em&gt;IDE Helper Generator for Laravel&lt;/em&gt;&lt;/a&gt; gera PHPDocs que ajudam a IDE a entender as models.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Instalação:&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;composer require &lt;span class="nt"&gt;--dev&lt;/span&gt; barryvdh/laravel-ide-helper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Gerando PHPDocs:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Para o caminho padrão das models:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan ide-helper:models
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Para um caminho personalizado (ex: na pasta &lt;code&gt;modules&lt;/code&gt;):
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan ide-helper:models &lt;span class="nt"&gt;--dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;modules
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3.2. Scripts para Composer
&lt;/h3&gt;

&lt;p&gt;É possível encurtar o comando adicionando um script no &lt;code&gt;composer.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ide"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"php artisan ide-helper:models --dir=modules"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Uso na CLI:&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;composer run ide
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Views Modulares
&lt;/h2&gt;

&lt;p&gt;Para trabalhar com views modulares fora de &lt;code&gt;resources/views&lt;/code&gt;, use o método &lt;code&gt;boot()&lt;/code&gt; do &lt;code&gt;Service Provider&lt;/code&gt; para registrar os novos caminhos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderServiceProvider&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ServiceProvider&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;function&lt;/span&gt; &lt;span class="n"&gt;boot&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;loadViewsFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;__DIR__&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/../../Ui/Views'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'order'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;Blade&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;anonymousComponentPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;__DIR__&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'/../../Ui/Views/components'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'order'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;Blade&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;componentNamespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Modules\\Order\\Ui\\ViewComponents'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'order'&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;
  
  
  4.1. Views Normais
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;loadViewsFrom()&lt;/code&gt; para registrar pastas de views com um namespace, evitando conflitos entre módulos.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Exemplo:&lt;/strong&gt; &lt;code&gt;view('order::checkout')&lt;/code&gt; buscará a view em &lt;code&gt;Modules/Order/Ui/Views/checkout.blade.php&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4.2. Componentes Anônimos
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;Blade::anonymousComponentPath()&lt;/code&gt; para registrar uma pasta de componentes Blade anônimos.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Eles não têm classe PHP associada, apenas arquivos &lt;code&gt;.blade.php&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exemplo:&lt;/strong&gt; &lt;code&gt;&amp;lt;x-order::alert /&amp;gt;&lt;/code&gt; renderiza &lt;code&gt;Modules/Order/Ui/Views/components/alert.blade.php&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4.3. Componentes de Classe
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;Blade::componentNamespace()&lt;/code&gt; para registrar um namespace PHP de componentes de classe.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;São componentes criados com &lt;code&gt;php artisan make:component&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exemplo:&lt;/strong&gt; &lt;code&gt;&amp;lt;x-order::checkout-summary /&amp;gt;&lt;/code&gt; renderiza o componente de classe &lt;code&gt;CheckoutSummary&lt;/code&gt; no namespace &lt;code&gt;Modules\Order\Ui\ViewComponents&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O básico sobre views no Laravel:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://laravel.com/docs/12.x/views#main-content" rel="noopener noreferrer"&gt;Views&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Ferramentas e Plugins
&lt;/h2&gt;

&lt;h3&gt;
  
  
  5.1. Laravel IDEA
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;É um plugin do PHPStorm que oferece suporte ao Laravel.&lt;/li&gt;
&lt;li&gt;Na seção &lt;strong&gt;Module System&lt;/strong&gt;, permite definir a estrutura modular do projeto (ex.: diretório &lt;code&gt;modules&lt;/code&gt; com namespace &lt;code&gt;Modules&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Funciona bem quando a estrutura interna de cada módulo segue o padrão do Laravel.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Se não me engano o &lt;a href="https://laravel-idea.com/" rel="noopener noreferrer"&gt;Laravel IDEA&lt;/a&gt; agora tá de graça no PHPStorm, é uma ótima ferramenta, recomendo&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  5.2. Pacote Laravel Modules
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;O pacote &lt;a href="https://github.com/nWidart/laravel-modules" rel="noopener noreferrer"&gt;&lt;strong&gt;Laravel Modules&lt;/strong&gt;&lt;/a&gt; é uma ferramenta popular para modularizar projetos.&lt;/li&gt;
&lt;li&gt;Fornece uma estrutura organizada para criar e gerenciar módulos.&lt;/li&gt;
&lt;li&gt;O &lt;strong&gt;Laravel IDEA&lt;/strong&gt; possui suporte nativo para este pacote.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Organização de Código: Abordagens
&lt;/h2&gt;

&lt;h3&gt;
  
  
  6.1. Vertical Slice
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Organiza o código agrupando por &lt;strong&gt;funcionalidade&lt;/strong&gt; (ex.: &lt;code&gt;Order &amp;gt; Checkout&lt;/code&gt;), e não por tipo de arquivo.&lt;/li&gt;
&lt;li&gt;Todos os arquivos relacionados a uma funcionalidade ficam juntos.&lt;/li&gt;
&lt;li&gt;Facilita a visualização e manutenção de cada funcionalidade como uma unidade coesa.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mais sobre esse tópico em:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/@andrew.macconnell/exploring-software-architecture-vertical-slice-789fa0a09be6" rel="noopener noreferrer"&gt;Exploring Software Architecture: Vertical Slice&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.jimmybogard.com/vertical-slice-architecture/" rel="noopener noreferrer"&gt;Vertical Slice Architecture&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6.2. Agrupamento por Tipo (Grouping by Type)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Organiza o código por &lt;strong&gt;tipo de arquivo&lt;/strong&gt; (ex.: &lt;em&gt;models&lt;/em&gt;, &lt;em&gt;controllers&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;É possível combinar esta abordagem com a modularização criando uma pasta &lt;code&gt;src&lt;/code&gt; dentro do módulo para agrupar arquivos como &lt;em&gt;Models&lt;/em&gt;, &lt;em&gt;Events&lt;/em&gt;, etc., seguindo o padrão padrão do Laravel.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  7. Padrões de Design e Boas Práticas
&lt;/h2&gt;

&lt;h3&gt;
  
  
  7.1. Acoplamento Temporal vs. Eventos
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Problema: Acoplamento Temporal&lt;/strong&gt;: Ocorre quando uma ação depende estritamente de outra para ser executada, criando uma ordem rígida e dificultando a manutenção.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solução: Usar Eventos&lt;/strong&gt;: Em vez de executar tudo em um único método, separe as responsabilidades. O fluxo principal dispara um &lt;strong&gt;evento&lt;/strong&gt; e outras partes do sistema podem "escutar" e reagir de forma independente (ex.: enviar um e-mail de confirmação ou atualizar o estoque).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  8. Outros Tópicos
&lt;/h2&gt;

&lt;h3&gt;
  
  
  8.1. Sequences em Factories
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;O &lt;code&gt;Sequences&lt;/code&gt; do Laravel permite variar valores de atributos ao criar várias instâncias de uma factory.&lt;/li&gt;
&lt;li&gt;É útil para criar dados de teste com pequenas variações.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Database\Eloquent\Factories\Sequence&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;state&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;Sequence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Alice'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Bob'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Carol'&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="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Referencia: &lt;a href="https://laravel.com/docs/12.x/eloquent-factories#sequences" rel="noopener noreferrer"&gt;Laravel: sequences&lt;/a&gt;&lt;/p&gt;

</description>
      <category>braziliandevs</category>
      <category>laravel</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Clinton Rocha</dc:creator>
      <pubDate>Fri, 27 Dec 2024 15:39:09 +0000</pubDate>
      <link>https://forem.com/clintonrocha98/-5dan</link>
      <guid>https://forem.com/clintonrocha98/-5dan</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/jessilyneh" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&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%2Fuser%2Fprofile_image%2F170161%2F5ae6a245-e22d-455f-b79c-c79c42e6e977.jpg" alt="jessilyneh"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/jessilyneh/ser-ou-estar-senior-1l2h" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;"Ser" ou "estar" Senior?&lt;/h2&gt;
      &lt;h3&gt;Jessilyneh ・ Dec 27 '24&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#career&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#productivity&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#braziliandevs&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>career</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Um júnior e um teste técnico: The battle.</title>
      <dc:creator>Clinton Rocha</dc:creator>
      <pubDate>Sun, 03 Mar 2024 18:35:04 +0000</pubDate>
      <link>https://forem.com/clintonrocha98/um-junior-e-um-teste-tecnico-the-battle-4c5b</link>
      <guid>https://forem.com/clintonrocha98/um-junior-e-um-teste-tecnico-the-battle-4c5b</guid>
      <description>&lt;p&gt;Alguns dias atrás me deparei com um teste técnico e decidi fazer mesmo após já ter finalizado o período de entrega, não sei bem para que nível foi passado o teste, mas acredito que foi usado em diferentes níveis, o que vai definir a complexidade do projeto é a solução do candidato, ao ver isso, decidi fazer aplicando o que venho aprendendo.&lt;/p&gt;

&lt;p&gt;Eu nunca fiz teste técnico, muito menos uma entrevista técnica, então neste artigo pretendo explicar minha solução, motivações, reflexões e opiniões.&lt;/p&gt;

&lt;h1&gt;
  
  
  Table of contents
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Objetivo proposto&lt;/li&gt;
&lt;li&gt;Ferramentas escolhidas&lt;/li&gt;
&lt;li&gt;Primeiros passos&lt;/li&gt;
&lt;li&gt;Arquitetura e padrão de projeto&lt;/li&gt;
&lt;li&gt;Tratamento de erros&lt;/li&gt;
&lt;li&gt;Testes&lt;/li&gt;
&lt;li&gt;Duvida&lt;/li&gt;
&lt;li&gt;Questionamentos&lt;/li&gt;
&lt;li&gt;Conclusão&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Objetivo proposto
&lt;/h1&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%2Fmedia3.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExdGJnc2dzMDF6eWo2ZWtpdDA3aDU4c3F2dndteDNzOGRoNHE4dmlhNCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2F3oKIPnAiaMCws8nOsE%2Fgiphy.gif" class="article-body-image-wrapper"&gt;&lt;img alt="gatinho em cima de um notebook" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia3.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExdGJnc2dzMDF6eWo2ZWtpdDA3aDU4c3F2dndteDNzOGRoNHE4dmlhNCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2F3oKIPnAiaMCws8nOsE%2Fgiphy.gif" width="360" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Em resumo, o desafio é fazer uma API, um sistema de banco simplificado, nessa API existe dois tipos de usuário, o comum e o lojista, o comum pode transferir dinheiro para o lojista ou outro usuário comum, já o lojista não pode fazer transferência, ele apenas receber, veja mais alguns requisitos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validar se o usuário tem saldo antes da transferência.&lt;/li&gt;
&lt;li&gt;Antes de finalizar a transferência, deve-se consultar um serviço autorizador externo, e para isso eles disponibilizaram um &lt;code&gt;mock&lt;/code&gt; para simular esse serviço.&lt;/li&gt;
&lt;li&gt;A operação de transferência deve ser uma transação (ou seja, revertida em qualquer caso de inconsistência) e o dinheiro deve voltar para a carteira do usuário que envia.&lt;/li&gt;
&lt;li&gt;No recebimento de pagamento, o usuário ou lojista precisa receber notificação (envio de email, sms) enviada por um serviço de terceiro e eventualmente esse serviço pode estar indisponível/instável. Para isso também foi disponibilizado um &lt;code&gt;mock&lt;/code&gt; para simular o envio.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Mock&lt;/code&gt;: É um objeto simulado que imita o comportamento de um componente real. É usado principalmente em testes de software para isolar o código em teste de suas dependências externas, garantindo testes mais rápidos e previsíveis.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;O teste técnico não avalia:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fluxo de cadastro de usuários e lojistas&lt;/li&gt;
&lt;li&gt;Autenticação&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mas em desencargo de consciência vou explicar o que poderia ser usado, na autenticação poderia ser usado um JWT e para validar os campos da requisição existem diversas estratégias, geralmente eu uso &lt;code&gt;express-validator&lt;/code&gt; como middleware ou o &lt;code&gt;class-validator&lt;/code&gt; como seus &lt;code&gt;decorators&lt;/code&gt;, e podendo ser validado na camada de controller ou também como middleware.&lt;/p&gt;

&lt;h1&gt;
  
  
  Ferramentas escolhidas
&lt;/h1&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%2Fmedia1.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExZ25ocDB6OTE4azJmemh1cndzNGZuYzh4N2RwaGpuYmhuYmgyN203ZiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2F11JTxkrmq4bGE0%2Fgiphy.gif" 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%2Fmedia1.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExZ25ocDB6OTE4azJmemh1cndzNGZuYzh4N2RwaGpuYmhuYmgyN203ZiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2F11JTxkrmq4bGE0%2Fgiphy.gif" width="399" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para começar com chave de ouro nesse teste técnico, nada mais, nada menos do que o amigo da galera, sim, ele mesmo, nosso tão amado &lt;code&gt;Javascript&lt;/code&gt;, na verdade, vou usar o &lt;code&gt;Typescript&lt;/code&gt; junto ao &lt;code&gt;Express&lt;/code&gt;. Como é a linguagem que tenho uma boa base, a sintaxe não seria mais um problema nesse projeto, me permitindo focar em arquitetura e estrutura do código. As ferramentas que usei foram:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://expressjs.com" rel="noopener noreferrer"&gt;Express JS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org" rel="noopener noreferrer"&gt;Typescript&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.postgresql.org" rel="noopener noreferrer"&gt;PostgreSQL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.docker.com" rel="noopener noreferrer"&gt;Docker | Compose&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vitest.dev" rel="noopener noreferrer"&gt;Vitest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/supertest" rel="noopener noreferrer"&gt;Supertest&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Primeiros passos
&lt;/h1&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%2Fmedia1.giphy.com%2Fmedia%2Fil2pe9NcggoRa%2F200.webp%3Fcid%3D790b76117z920hfqfhw798aj4rabpqu605ntpt3jguyyfzms%26ep%3Dv1_gifs_search%26rid%3D200.webp%26ct%3Dg" 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%2Fmedia1.giphy.com%2Fmedia%2Fil2pe9NcggoRa%2F200.webp%3Fcid%3D790b76117z920hfqfhw798aj4rabpqu605ntpt3jguyyfzms%26ep%3Dv1_gifs_search%26rid%3D200.webp%26ct%3Dg" width="266" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Acredito que não exista uma ordem perfeita para se começar um projeto, já me deparei com pessoas começando pelas rotas, criando estrutura de pastas primeiro que tudo, outras criando os testes para depois implementar as funcionalidades, sendo essa ultima talvez a mais famosa e mais indicada que vejo pela internet, entre outras abordagens, enfim, não sei qual é melhor, após instalar as ferramentas escolhidas e tripagem comecei a desenvolver a tabela do banco.&lt;/p&gt;

&lt;p&gt;Confesso que modelagem ainda não é meu forte, e por isso deixei essas duas tabelas o mais simples possível.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BEGIN;
      CREATE TABLE IF NOT EXISTS users (
        id SERIAL PRIMARY KEY,
        firstName VARCHAR(255) NOT NULL,
        lastName VARCHAR(255) NOT NULL,
        document VARCHAR(14) UNIQUE NOT NULL,
        email VARCHAR(255) UNIQUE NOT NULL,
        password VARCHAR(255) NOT NULL,
        balance INT,
        userType VARCHAR(7) NOT NULL
    );

      CREATE TABLE IF NOT EXISTS transactions (
        id SERIAL PRIMARY KEY,
        payer INT NOT NULL,
        payee INT NOT NULL,
        amount INT NOT NULL,
        date_transaction TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        FOREIGN KEY (payer) REFERENCES users(id),
        FOREIGN KEY (payee) REFERENCES users(id)
      );
COMMIT;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tabelas prontas, agora eu posso criar os &lt;code&gt;types&lt;/code&gt; que vão existir dentro da minha aplicação.&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;type&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &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;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="na"&gt;firstName&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="err"&gt; &lt;/span&gt; &lt;span class="na"&gt;lastName&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="err"&gt; &lt;/span&gt; &lt;span class="na"&gt;document&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="err"&gt; &lt;/span&gt; &lt;span class="na"&gt;password&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="err"&gt; &lt;/span&gt; &lt;span class="na"&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="err"&gt; &lt;/span&gt; &lt;span class="na"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="na"&gt;usertype&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;comum&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lojista&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Transaction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &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;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="na"&gt;payer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="na"&gt;payee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;date_transaction&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;p&gt;Após perguntas para alguns amigos e pesquisar como geralmente é feito uma modelagem desse tipo, levantei essas duas possíveis melhorias: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Fazer mais uma tabela para guardar os cargos, imagine um cenário onde poderiam existir outros cargos do usuário, em vez de ter direto na tabela &lt;code&gt;user&lt;/code&gt;, poderia salvar esses cargos em outra tabela e relaciona ao usuário, resultado em uma normalização dos dados. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ter outra tabela onde eu salvaria o saldo da conta do cliente, assim eu não precisaria ficar atualizando a tabela do usuário toda vez que for feita uma transferência.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Arquitetura e padrão de projeto
&lt;/h1&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%2Fuwy0olqw1n4cfowtej5q.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%2Fuwy0olqw1n4cfowtej5q.png" alt="arquitetura em camadas escolhida para o projeto" width="800" height="180"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Acabei optando por utilizar uma arquitetura em camadas. Pelo que venho estudando, essa estratégia é bastante interessante por alguns motivos: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Desacoplamento de código. &lt;/li&gt;
&lt;li&gt;Separação de responsabilidade. &lt;/li&gt;
&lt;li&gt;Modularidade e reutilização de código. &lt;/li&gt;
&lt;li&gt;Facilidade na hora de criar testes. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Não posso deixar de citar os pontos negativos: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complexidade adicional. &lt;/li&gt;
&lt;li&gt;Dificuldade de implementação no início do projeto. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Além disso, foi usado alguns princípios da orientação a objetos, sim, o famoso SOLID. No meu código você pode encontrar princípios como: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Responsabilidade única&lt;/code&gt;, onde exemplo é o seguinte método que se comunica com a camada de repositório e procura um usuário pelo id:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;userById&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="kr"&gt;number&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;user&lt;/span&gt; &lt;span class="o"&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;userRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;userById&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="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;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;InvalidUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Usuario invalido&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;return&lt;/span&gt; &lt;span class="nx"&gt;user&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;ul&gt;
&lt;li&gt;
&lt;code&gt;Inversão da dependência&lt;/code&gt; e &lt;code&gt;aberto-fechado&lt;/code&gt;: usando a interface como uma abstração do banco de dados, o &lt;code&gt;UserService&lt;/code&gt; não vai mais precisar saber qual o banco minha aplicação está usando:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;//abstração&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;IUserRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;newUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;userById&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="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;emailExist&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;documentExist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&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;userRepository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IUserRepository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;newUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;EmailExist&lt;/span&gt; &lt;span class="o"&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;userRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emailExist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&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="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; 
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&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;EmailExist&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;InvalidEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email invalido&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; 
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DocumentExist&lt;/span&gt; &lt;span class="o"&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;userRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;documentExist&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&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;DocumentExist&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;InvalidDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Document invalid&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newUser&lt;/span&gt; &lt;span class="o"&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;userRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; 
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;newUser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A meu ver, o código fica muito mais limpo, só se deve ter cuidado com a quantidade de abstração, o uso excessivo pode acarreta um emaranhado de código. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Em outro artigo/post explico melhor sobre SOLID, nele eu trago alguns exemplos em código e imagens que podem te ajudar a entender melhor sobre esses princípios: &lt;a href="https://dev.to/clintonrocha98/era-solid-o-que-me-faltava-bhp"&gt;Era SOLID o que me faltava&lt;/a&gt;. Agora entrando na parte de organização de projeto, vou explicar um pouco das funções de cada camada, o projeto tem três camadas, são elas: &lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Repository&lt;/code&gt;: camada responsável por interagir com o banco de dados. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Service&lt;/code&gt;: camada onde a lógica de negócio acontece, interações com outros serviços e manipulação dos dados enviados/recebidos do&lt;code&gt;repository&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Controller&lt;/code&gt;: camada onde recebemos o corpo da requisição do cliente, podendo ser feito validações, verificações nas informações recebidas e enviadas, também podendo chamar diferentes serviços.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Tratamento de erros
&lt;/h1&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%2Fmedia3.giphy.com%2Fmedia%2FkELWH7yHTEWlrOrgli%2Fgiphy.webp%3Fcid%3D790b76117z920hfqfhw798aj4rabpqu605ntpt3jguyyfzms%26ep%3Dv1_gifs_search%26rid%3Dgiphy.webp%26ct%3Dg" 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%2Fmedia3.giphy.com%2Fmedia%2FkELWH7yHTEWlrOrgli%2Fgiphy.webp%3Fcid%3D790b76117z920hfqfhw798aj4rabpqu605ntpt3jguyyfzms%26ep%3Dv1_gifs_search%26rid%3Dgiphy.webp%26ct%3Dg" width="300" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No &lt;code&gt;Javascript&lt;/code&gt; o &lt;a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Statements/try...catch" rel="noopener noreferrer"&gt;&lt;code&gt;try catch&lt;/code&gt;&lt;/a&gt; é uma estrutura usada para lidar com exceções durante a execução de código, mas isso gera uma repetição de estrutura tremenda no código, fora que faz com que uma funcionalidade possa ter diferentes tipos de retorno, acaba deixando o código desorganizado e muito difícil de se entender. &lt;/p&gt;

&lt;p&gt;Tendo esse detalhe da linguagem em mente, optei pelo uso de middleware de erros e uma pequena biblioteca &lt;code&gt;express-async-errors&lt;/code&gt; fazendo com que minhas exceções não saiam de controle.&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;const&lt;/span&gt; &lt;span class="nx"&gt;errorMiddleware&lt;/span&gt; &lt;span class="o"&gt;=&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="nb"&gt;Error&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ApiError&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;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextFunction&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="nx"&gt;statusCode&lt;/span&gt; &lt;span class="o"&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;statusCode&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;500&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;message&lt;/span&gt; &lt;span class="o"&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;statusCode&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Internal Server Error&lt;/span&gt;&lt;span class="dl"&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;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&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;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;statusCode&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;Com o uso desse middleware eu posso lançar exceções e não quebrar a aplicação e nem mostrar erros tenebrosos para o usuário, mas não para por aqui, para deixar os erros ainda mais fáceis de se ler, eu fiz uma pequena personalização.&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;ApiError&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Error&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;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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;message&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;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&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="k"&gt;this&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="nx"&gt;statusCode&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="c1"&gt;// Um dos erros que usei na aplicação &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;UnauthorizedTransaction&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ApiError&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&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;message&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="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;super&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="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;//Caso de uso.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isAuthorized&lt;/span&gt; &lt;span class="o"&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;authorizationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authorizeTransaction&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isAuthorized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UnauthorizedTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Transação não autorizada&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Em outro artigo/post que fiz falo mais sobre esse assunto do &lt;code&gt;try-catch&lt;/code&gt; e middleware de erros: &lt;a href="https://dev.to/clintonrocha98/lidando-com-excecoes-como-fazer-erros-praticos-e-elegantes-no-express-js-4k5b"&gt;Lidando com exceções&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Testes
&lt;/h1&gt;

&lt;p&gt;Esse projeto me fez melhor muito na maneira que desenvolvo os meus testes e a estrutura escolhida para esse projeto auxiliou muito para isso, mais alguns benefícios que a estrutura do projeto proporcionou:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Me permite criar mocks em camadas especificas&lt;/li&gt;
&lt;li&gt;&lt;a href="https://martinfowler.com/bliki/InMemoryTestDatabase.html" rel="noopener noreferrer"&gt;In Memory Test Database&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Os &lt;code&gt;mocks&lt;/code&gt; são interessantes de se usar, eu pensava que poderia sair colocando &lt;code&gt;mock&lt;/code&gt; em tudo, mas não é bem assim que funciona, como qualquer coisa na tecnologia, toda ferramenta tem seu lugar na atuação, onde eu acredito que ele brilhe é em pontos específicos do teste, por exemplo:&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="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;authorizeTransaction should return false when authorization is not successful&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="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nb"&gt;global&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;vi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fn&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="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="na"&gt;json&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="nb"&gt;Promise&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="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Not authorized&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; 
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&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;authService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authorizeTransaction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&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="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&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 é um exemplo onde o &lt;code&gt;mock&lt;/code&gt; me permitiu testa o retorno de algo que não tenho controle, no caso seria uma API de autorização de transação.&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="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;It should not be possible to create a user with an email that already exists&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="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fakeUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;makeSut&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fakeUser&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;await&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;userService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;newUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fakeUser&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;rejects&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toThrow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email invalido&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&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 &lt;code&gt;In Memory Database&lt;/code&gt; é uma abordagem que aprendi faz pouco tempo, no link que disponibilizei fala mais sobre os benefícios do uso dessa estratégia, mas no caso dessa minha aplicação, o ponto de destaque foi os testes onde eu esperava retornos de falha, sem o uso de banco de dados eu consigo testa de maneiras simples e rápida pontos de falhas. &lt;/p&gt;

&lt;p&gt;Nos testes E2E foram usados o &lt;code&gt;supertest&lt;/code&gt; em conjunto de um container Docker rodando um banco de dados postgreSQL, para que não tivesse problema entre esses testes E2E foi usado um pequeno script para limpar o banco.&lt;/p&gt;

&lt;h1&gt;
  
  
  Duvida
&lt;/h1&gt;

&lt;p&gt;A maioria das vezes as soluções que pensei nesse desafio e também em outros projetos que já fiz, são consideradas como &lt;code&gt;overengineering&lt;/code&gt;, e pelo que vejo pela internet, provavelmente quase todo júnior na hora do desenvolvimento de alguma aplicação já passou por isso. Tendo isso em mente, eu me questionei, como que esse &lt;code&gt;overengineering&lt;/code&gt; seria visto pelo entrevistador? Eu estaria mostrando conhecimento ou iria parecer esta copiando ''modelo'' de solução? Provavelmente o que responderia essas perguntas seria minha entrevista.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Overengineering&lt;/code&gt;: É quando você cria uma solução mais complexa ou robusta do que realmente precisa. É como usar um canhão para matar uma mosca. Isso pode resultar em desperdício de tempo, recursos e dificuldade de manutenção. Em resumo, é quando você torna algo mais complicado do que é necessário para resolver o problema em questão.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Questionamentos
&lt;/h1&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%2Fmedia.giphy.com%2Fmedia%2F5AGvUbf5yBaUcRDkkc%2Fgiphy.gif%3Fcid%3D790b7611hatnpcd973kgaqpfbtoaj8k0qqp4w5slec6lidom%26ep%3Dv1_gifs_search%26rid%3Dgiphy.gif%26ct%3Dg" class="article-body-image-wrapper"&gt;&lt;img alt="gatinho digitando no notebook e falando que esta finalizando algo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia.giphy.com%2Fmedia%2F5AGvUbf5yBaUcRDkkc%2Fgiphy.gif%3Fcid%3D790b7611hatnpcd973kgaqpfbtoaj8k0qqp4w5slec6lidom%26ep%3Dv1_gifs_search%26rid%3Dgiphy.gif%26ct%3Dg" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Após finalizar boa parte desse artigo, mostrei o rascunho para a galera da comunidade &lt;a href="https://twitter.com/He4rtDevs" rel="noopener noreferrer"&gt;He4rt Developers&lt;/a&gt; resultando em um bate-papo bem legal, nele eu fui levado a questionar ainda mais as escolhas em relação às tecnologias usadas no processo de desenvolvimento. Eu vou esta fugindo um pouco do tema principal desse artigo, mas esses questionamentos são necessários para todo desenvolvedor e acredito que vão fazer você evoluir de alguma maneira.&lt;/p&gt;

&lt;p&gt;Usar ou não usar um framework? Convenhamos que usar determinado framework iria facilitar e muito o processo de desenvolvimento, mas temos que entender uma coisa, um framework é ferramenta que se encaixa em situações especificas e resolvem problemas específicos, e não para por aí, o desenvolvedor tem que entender o contexto do problema que ele vai solucionar, existem limitações e requisitos referente a estrutura, tem toda uma análise antes de se escolher uma tecnologia. O mesmo questionamento vale para linguagens.&lt;/p&gt;

&lt;p&gt;Após levantar esses pontos, quero mostrar questionamentos que normalmente se deve ter antes de escolher uma tecnologia:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Qual a quantidade de usuários que vai utilizar? &lt;/li&gt;
&lt;li&gt;O que está disponível para a utilização na infraestrutura da empresa?&lt;/li&gt;
&lt;li&gt;Terá novas implementações dentro desta lógica? &lt;/li&gt;
&lt;li&gt;Qual a criticidade do processo? &lt;/li&gt;
&lt;li&gt;Qual o tempo ideal de resposta para cada rota? &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Você já tinha se perguntado isso alguma vez antes? Pelo que vejo de outros desenvolvedores mais experientes, esses questionamentos fazem total diferença.&lt;/p&gt;

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

&lt;p&gt;Como foi dito no início, eu nunca tinha feito um teste técnico antes, acredito que após de ter feito essa solução e ao fazer esse artigo, me fez pensar em muita coisa em relação a tudo isso, provavelmente eu não teria a mesma postura que tive nesse projeto, mas de qualquer forma eu saí aprendendo algo.&lt;/p&gt;

&lt;p&gt;E você leitor, aprendeu algo com esse artigo? Tem algum feedback? Se tiver alguma explicação errada nesse artigo, eu ficaria grato com sua correção. Será que eu iria passar nesse teste? Fica essa dúvida no ar. &lt;/p&gt;

&lt;p&gt;Quase que esqueço, caso você queira ver minha solução por completo, ela está no meu &lt;a href="https://github.com/Clintonrocha98/picpay-desafio-backend" rel="noopener noreferrer"&gt;Github&lt;/a&gt; e também o repositório do &lt;a href="https://github.com/PicPay/picpay-desafio-backend/tree/master?tab=readme-ov-file#objetivo-picpay-simplificado" rel="noopener noreferrer"&gt;desafio original&lt;/a&gt;. Você pode me encontrar no &lt;a href="https://twitter.com/ClintonRocha_" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; ou no Discord da &lt;a href="https://twitter.com/He4rtDevs" rel="noopener noreferrer"&gt;He4rt Developers&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Gostaria de agradecer ao &lt;a class="mentioned-user" href="https://dev.to/carloseduardodb"&gt;@carloseduardodb&lt;/a&gt; e a &lt;a class="mentioned-user" href="https://dev.to/cherryramatis"&gt;@cherryramatis&lt;/a&gt; pela revisão desse conteúdo, feedbacks e dicas. Os questionamentos foram levantados pelo Carlos e eu achei de grande ajuda, para esse artigo e ainda mais para mim. &lt;/p&gt;

&lt;p&gt;"Eu tentaria fazer uma solução mais próxima da realidade do pessoal de lá para ganhar uns pontinhos. Às vezes, nem é utilizar a mesma linguagem que eles, mas entender os problemas que eles têm e como eles solucionam hoje."&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/carloseduardodb"&gt;@carloseduardodb&lt;/a&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Fica aí mais uma dica.&lt;/p&gt;

&lt;p&gt;Obrigado por ler até aqui.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>braziliandevs</category>
      <category>programming</category>
    </item>
    <item>
      <title>Primeiros passos no Docker</title>
      <dc:creator>Clinton Rocha</dc:creator>
      <pubDate>Wed, 07 Feb 2024 12:22:42 +0000</pubDate>
      <link>https://forem.com/clintonrocha98/primeiros-passos-no-docker-m0k</link>
      <guid>https://forem.com/clintonrocha98/primeiros-passos-no-docker-m0k</guid>
      <description>&lt;p&gt;Desenvolvendo de forma simples e direta, é hoje que você vai começar a usar o &lt;strong&gt;&lt;a href="https://www.docker.com" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;&lt;/strong&gt;. Nada de termos complicados, apenas uma abordagem fácil para que você possa usar containers sem stress. Você provavelmente já deve ter ouvido falar de &lt;strong&gt;Docker&lt;/strong&gt; em requisitos de vagas ou em projetos de algum outro desenvolvedor e com isso tentou usá-lo e não conseguiu ou então não entendeu como usar. Nesse artigo vou te mostrar de maneira simples como é o processo de &lt;a href="https://www.redhat.com/pt-br/topics/cloud-native-apps/what-is-containerization" rel="noopener noreferrer"&gt;conteinerização&lt;/a&gt; de uma aplicação.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/FaKV1cVKlVRxC/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/FaKV1cVKlVRxC/giphy.gif" width="500" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Table of contents
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Objetivo&lt;/li&gt;
&lt;li&gt;Requisitos&lt;/li&gt;
&lt;li&gt;
O que é

&lt;ul&gt;
&lt;li&gt;Dockerfile&lt;/li&gt;
&lt;li&gt;Docker Image&lt;/li&gt;
&lt;li&gt;Container&lt;/li&gt;
&lt;li&gt;Volume&lt;/li&gt;
&lt;li&gt;
Compose &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;CLI do Docker&lt;/li&gt;

&lt;li&gt;

Botando a mão na massa

&lt;ul&gt;
&lt;li&gt;Seu primeiro Dockerfile&lt;/li&gt;
&lt;li&gt;Configuração do Vite&lt;/li&gt;
&lt;li&gt;Criando a imagem do front&lt;/li&gt;
&lt;li&gt;Criando o container do front&lt;/li&gt;
&lt;li&gt;Criando uma network&lt;/li&gt;
&lt;li&gt;Baixando a imagem do Postgres&lt;/li&gt;
&lt;li&gt;Criando um volume para persistência de dados&lt;/li&gt;
&lt;li&gt;Executando container Postgres&lt;/li&gt;
&lt;li&gt;Criando a imagem do back&lt;/li&gt;
&lt;li&gt;Criando o container do back&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Compose&lt;/li&gt;

&lt;li&gt;Conteúdo complementar&lt;/li&gt;

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

&lt;/ul&gt;

&lt;h1&gt;
  
  
  Objetivo
&lt;/h1&gt;

&lt;p&gt;Meu principal objetivo é ajudar você leitor com os primeiros passos com &lt;strong&gt;Docker&lt;/strong&gt; no desenvolvimento de seus projetos. Pretendo ter uma abordagem pautada no contexto da aplicação que vou usar, vamos começar explicando as ferramentas de uma forma diferente das que encontrei pela internet, em seguida vou mostrá-las mais a prática, usando uma pequena aplicação como exemplo. Esse artigo conciliado ao conteúdo teórico que vou disponibilizar por links durante e ao final vão te dar uma boa base do que é essa ferramenta e como ela funciona por baixo dos panos, ao fim de tudo eu espero que você seja capaz de dar seus primeiros passos criando container de tudo 🐳.&lt;/p&gt;

&lt;h1&gt;
  
  
  Requisitos
&lt;/h1&gt;

&lt;p&gt;Ter instalado:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/desktop/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/desktop/install/windows-install/" rel="noopener noreferrer"&gt;Windows&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/desktop/install/mac-install/" rel="noopener noreferrer"&gt;Mac&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/desktop/install/linux-install/" rel="noopener noreferrer"&gt;Linux&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;a href="https://docs.docker.com/compose/install/" rel="noopener noreferrer"&gt;Docker-compose&lt;/a&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  O que é
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Dockerfile
&lt;/h2&gt;

&lt;p&gt;É um arquivo de configuração, onde está o passo inicial para a criação de uma &lt;strong&gt;Docker Image&lt;/strong&gt;. Nele contem as instruções para configurar sua aplicação no container. Veja o &lt;strong&gt;dockerfile&lt;/strong&gt; como um manual que lista o passo a passo de como montar algo (sua aplicação no caso) e as instruções de como ligar esse algo na tomada.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker Image
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;Docker Image&lt;/strong&gt; é o aglomerado de tudo o que é necessário para sua aplicação funcionar, é onde se encontra o código-fonte, bibliotecas, dependências e mais o que for necessário para que ela funcione. Seu &lt;em&gt;app&lt;/em&gt; em uma foto. &lt;/p&gt;

&lt;h2&gt;
  
  
  Container
&lt;/h2&gt;

&lt;p&gt;Imagine que você queira fazer uma festa independente do local que esteja, e para isso você carrega uma caixa com balões, caixinha de som e luzes coloridas, coisas leves. Pronto sua festa pode ser feita em qualquer lugar, essa caixa é o nosso container, ele reúne tudo o que é necessário para uma aplicação funcionar. Ele resolve aquele famoso problema de "Na minha máquina funciona". &lt;/p&gt;

&lt;p&gt;Em outras palavras, os containers são ambientes de software leves, portáteis e isolados que permitem aos desenvolvedores executar e empacotar aplicativos com suas dependências, de forma consistente em diferentes plataformas. Eles ajudam a agilizar os processos de desenvolvimento, implantação e gerenciamento de aplicativos, garantindo ao mesmo tempo que os aplicativos sejam executados de forma consistente, independentemente da infraestrutura.&lt;/p&gt;

&lt;h2&gt;
  
  
  Volume
&lt;/h2&gt;

&lt;p&gt;Em termos simples, um volume no contexto do &lt;strong&gt;Docker&lt;/strong&gt; é um mecanismo que permite que dados sejam compartilhados e persistam entre o host e os containers. Ele oferece uma maneira de armazenar e compartilhar informações de forma independente do ciclo de vida dos containers.&lt;/p&gt;

&lt;p&gt;Por exemplo, se você tiver um container de banco de dados, pode usar um volume para armazenar os dados do banco de forma que esses dados persistam mesmo se o container for removido. Isso proporciona flexibilidade e consistência na gestão de dados em ambientes &lt;strong&gt;Docker&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compose
&lt;/h2&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%2Fvwat4tpctijhxj07va51.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%2Fvwat4tpctijhxj07va51.png" alt="O mascote do docker e o mascote do compose" width="654" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O &lt;strong&gt;Docker Compose&lt;/strong&gt; é uma ferramenta que simplifica a gestão de aplicações Docker compostas por vários containers. Ele permite definir, configurar e executar vários serviços, redes e volumes em um arquivo &lt;code&gt;YAML&lt;/code&gt;, facilitando a criação e a execução de ambientes complexos com apenas um comando.&lt;/p&gt;

&lt;h1&gt;
  
  
  CLI do Docker
&lt;/h1&gt;

&lt;p&gt;Existe o &lt;strong&gt;Docker Desktop&lt;/strong&gt; onde você pode fazer a maioria das configurações, ele é até amigável, porem o mais indicado é você se acostumar com os comandos pelo terminal, até por que em caso de qualquer dúvida as respostas que você vai encontrar pela internet na sua grande maioria vão ser em formato de comandos, caso você queria configurar através do aplicativo desktop recomendo você olhar a documentação. Nesse tópico eu pretendo mostrar alguns comandos básicos e fala o que cada um faz.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nt"&gt;--help&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Começando pelo mais simples, mas também muito importante, o &lt;code&gt;--help&lt;/code&gt; mostra todos os comandos do Docker junto a uma pequena explicação, ele também pode ser usado em conjunto com os próximos comandos que vou mostrar no caso de você não se lembrar das opções que aquele comando tem.&lt;/p&gt;

&lt;p&gt;Todos os comandos que vou usar são da nova versão feita para fornecer uma experiência de usuário mais estruturada ao usar a linha de comando. Que eu saiba, ainda não houve nenhum anúncio oficial para abandonar o suporte aos comandos antigos (como &lt;code&gt;docker ps&lt;/code&gt; e outros), embora possa ser razoável supor que isso possa acontecer em algum momento no futuro. &lt;/p&gt;

&lt;h2&gt;
  
  
  Para gerenciar containers:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Criar e executar container:&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;docker container run nome-da-imagem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Listar containers em execução:&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;docker container &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Listar todos os containers (Inclusive parados):&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;docker container &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Parar um container:&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;docker container stop nome-ou-ID-do-container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Iniciar um container parado:&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;docker container start nome-ou-ID-do-container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Remover um container (deve estar parado):&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;docker container &lt;span class="nb"&gt;rm &lt;/span&gt;nome-ou-ID-do-container
&lt;span class="c"&gt;## com a opção '-f' ele força a parada do container e em seguida o remove&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Para Gerenciar Imagens:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Listar imagens locais:&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;docker image &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Baixar uma imagem do Docker Hub:&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;docker pull nome-da-imagem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Construir uma imagem a partir de um Dockerfile:&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;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; nome-da-imagem caminho-do-Dockerfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Remover uma imagem local:&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;docker &lt;span class="nb"&gt;rm &lt;/span&gt;nome-da-imagem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Para Gerenciar Redes:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Listar redes Docker:&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;docker network &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Criar uma rede Docker:&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;docker network create nome-da-rede
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Conectar um container a uma rede:&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;docker network connect nome-da-rede nome-ou-ID-do-container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Desconectar um container de uma rede:&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;docker network disconnect nome-da-rede nome-ou-ID-do-container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Outros comandos úteis:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Logs de um container:&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;docker logs nome-ou-ID-do-container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Informações Detalhadas de um container:&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;docker inspect nome-ou-ID-do-container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Botando a mão na massa
&lt;/h1&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%2F7970rk04n6dvqf7k8dxs.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%2F7970rk04n6dvqf7k8dxs.png" alt="imagem mostrando o caminho do dockerfile até o container" width="800" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nesse tópico vamos abordar as ferramentas acima citadas um pouco mais prática, e para isso vamos usar uma pequena aplicação com as tecnologias &lt;a href="https://pt-br.legacy.reactjs.org" rel="noopener noreferrer"&gt;React&lt;/a&gt;, &lt;a href="https://vitejs.dev" rel="noopener noreferrer"&gt;Vite&lt;/a&gt;,&lt;a href="https://expressjs.com" rel="noopener noreferrer"&gt;Express&lt;/a&gt; e &lt;a href="https://www.postgresql.org" rel="noopener noreferrer"&gt;PostgreSQL&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Clintonrocha98/getting-started-with-docker" rel="noopener noreferrer"&gt;Link do repositório da aplicação&lt;/a&gt;🐳&lt;/p&gt;

&lt;h2&gt;
  
  
  Seu primeiro Dockerfile
&lt;/h2&gt;

&lt;p&gt;No diretório &lt;code&gt;./front&lt;/code&gt; podemos ver o arquivo &lt;code&gt;.dockerignore&lt;/code&gt; que funcionar parecido com o &lt;code&gt;.gitignore&lt;/code&gt;, nele você define arquivos ou pastas que não são necessárias na imagem da sua aplicação. O arquivo &lt;code&gt;Dockerfile&lt;/code&gt; tem a seguinte estrutura:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:18.17.0-alpine&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm run build
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8080&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; [ "npm", "run", "preview" ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;code&gt;FROM&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Aqui é o ponto de partida da sua imagem, é onde você define a base do seu container, e para essa aplicação eu estou baixando a imagem do &lt;code&gt;node&lt;/code&gt; na versão &lt;code&gt;18.17.0-alpine&lt;/code&gt; e quando você ver o &lt;code&gt;alpine&lt;/code&gt; em alguma imagem significa que a imagem foi construída usando Alpine Linux como base. Essas imagens são populares porque são eficientes, rápidas de baixar e fornecem um ambiente leve para executar aplicativos em containers. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;WORKDIR&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Define o diretório de trabalho dentro do container como &lt;code&gt;/app&lt;/code&gt;. Isso significa que os próximos comandos serão executados dentro deste diretório.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;COPY&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Copia o arquivo &lt;code&gt;package.json&lt;/code&gt; (e qualquer arquivo que comece com "package") do diretório local para o diretório &lt;code&gt;/app&lt;/code&gt; no container.&lt;/p&gt;

&lt;p&gt;O segundo &lt;code&gt;COPY&lt;/code&gt; copia todos os outros arquivos do diretório local para o diretório &lt;code&gt;/app&lt;/code&gt; no container.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;RUN&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Executa o comando &lt;code&gt;npm install&lt;/code&gt; dentro do container, que instala as dependências especificadas no arquivo &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O segundo &lt;code&gt;RUN&lt;/code&gt; executa o comando &lt;code&gt;npm run build&lt;/code&gt; para construir a aplicação. Esse comando é geralmente usado para compilar e preparar a aplicação para execução.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;EXPOSE&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Informa que a aplicação dentro do container estará escutando na porta &lt;code&gt;8080&lt;/code&gt;. Isso não faz com que a porta seja automaticamente aberta, mas é uma informação útil para quem está usando a imagem para entender qual porta a aplicação espera ser exposta.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;CMD&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Define o comando padrão a ser executado quando um container baseado nesta imagem for iniciado. Neste caso, o comando é &lt;code&gt;npm run preview&lt;/code&gt;, que inicia o servidor da aplicação para que ela possa ser acessada.&lt;/p&gt;

&lt;p&gt;Essas vão ser as instruções mais básicas que vamos usar, existem algumas outras e recomendo você dá uma olhada na &lt;a href="https://docs.docker.com/engine/reference/builder/" rel="noopener noreferrer"&gt;documentação&lt;/a&gt; para ter uma base melhor. &lt;/p&gt;

&lt;h2&gt;
  
  
  Configuração do Vite
&lt;/h2&gt;

&lt;p&gt;No &lt;strong&gt;Vite&lt;/strong&gt; para que nossa aplicação rode na porta &lt;code&gt;8080&lt;/code&gt; é necessário configurar o arquivo &lt;code&gt;vite.config.ts&lt;/code&gt;. Caso você queira abordar outras configurações recomendo &lt;a href="https://vitejs.dev/config/" rel="noopener noreferrer"&gt;ler a documentação do &lt;strong&gt;Vite&lt;/strong&gt; &lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://thedkpatel.medium.com/dockerizing-react-application-built-with-vite-a-simple-guide-4c41eb09defa" rel="noopener noreferrer"&gt;Artigo que me ajudou a entender a configuração usada nesse projeto.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Criando a imagem do front
&lt;/h2&gt;

&lt;p&gt;Pronto, com o &lt;code&gt;Dockerfile&lt;/code&gt; preenchido corretamente podemos criar nossa primeira imagem. Se você prestou atenção no tópico &lt;code&gt;CLI do Docker&lt;/code&gt; já deve ter uma ideia de como vamos fazer isso, vá no terminal e acesse o diretório &lt;code&gt;./front&lt;/code&gt; e execute o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker image build &lt;span class="nt"&gt;-t&lt;/span&gt; front &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-t&lt;/code&gt; ou &lt;code&gt;-tag&lt;/code&gt; é usado para dar nome e dar &lt;code&gt;tag&lt;/code&gt; para a imagem, nesse exemplo estou dando o nome da imagem como &lt;code&gt;front&lt;/code&gt; caso eu quisesse ter diferentes versões dessa imagem poderia ser usado o segundo argumento para uma &lt;code&gt;tag&lt;/code&gt; como &lt;code&gt;front:nome-da-tag&lt;/code&gt;, geralmente na &lt;code&gt;tag&lt;/code&gt; é colocado a versão ou algo que facilite a identificação &lt;code&gt;front:1.0&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;No terminal eu estou no diretório &lt;code&gt;./front&lt;/code&gt; que é onde está o &lt;code&gt;dockerfile&lt;/code&gt; é por isso que só uso o &lt;code&gt;.&lt;/code&gt; (ponto).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se você presta atenção no seu terminal, vai notar que o Docker esta seguindo as instruções feitas no &lt;code&gt;Dockerfile&lt;/code&gt;.&lt;/p&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%2Fmysqqy9qosvk4rhn2bvg.gif" 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%2Fmysqqy9qosvk4rhn2bvg.gif" alt="gif monstrando os comandos que foram mostrados antes" width="640" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;No gif a build da imagem foi rápido porque boa parte dessa imagem no meu pc já estava em cache, no seu deve demorar mais.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Criando o container do front
&lt;/h2&gt;

&lt;p&gt;Já temos a imagem do front e com ela podemos criar o tão sonhado container, novamente vá no seu terminal e execute o comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker container run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 front
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-d&lt;/code&gt;: É usado para executar um container em segundo plano, ou seja, em modo "detached". Quando você executa um container Docker, por padrão, ele é iniciado em primeiro plano.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-p 8080:8080&lt;/code&gt;: essa opção indica que estamos mapeando a porta 8080 do container para a porta 8080 do host.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;front&lt;/code&gt;: é o nome da imagem o container vai usar.&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%2F4t5jy32mfggwi61nxy05.gif" 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%2F4t5jy32mfggwi61nxy05.gif" alt="Image com os comandos acima citados" width="640" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Acessando o &lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt; em seu navegador já vamos conseguir acessar o front da nossa aplicação, mas ainda falta o nosso back e banco esta no ar. &lt;/p&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%2F8yo41aw7zaim74vnjccd.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%2F8yo41aw7zaim74vnjccd.png" alt="Image do front no ar" width="800" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Criando uma network
&lt;/h2&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%2Fptffts98j3o0y14al6f8.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%2Fptffts98j3o0y14al6f8.png" alt="imagem mostrando um diagrama mostrando a conexão do entre os containers" width="698" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;docker network&lt;/code&gt; é um recurso do Docker que permite criar redes isoladas para containers. As redes do Docker desempenham um papel fundamental ao fornecer comunicação entre containers, garantindo isolamento, segurança e flexibilidade nas interações entre os diferentes componentes de um sistema distribuído.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker network artigo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;O nome da rede vai ser &lt;code&gt;artigo&lt;/code&gt;😁.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Baixando a imagem do Postgres
&lt;/h2&gt;

&lt;p&gt;O próximo passo é baixar a imagem do Postgres a partir do Docker Hub. Para fazer isso, execute o seguinte comando em seu terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Criando um volume para persistência de dados
&lt;/h2&gt;

&lt;p&gt;Antes de executar o containers do banco e do back, é importante criar um volume para persistência de dados. Isso garantirá que os dados do Postgres não sejam perdidos quando o container for interrompido ou excluído. Para criar um volume, execute o seguinte comando em seu terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume create pgdata
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;O nome do volume vai ser &lt;code&gt;pgdata&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Executando container Postgres
&lt;/h2&gt;

&lt;p&gt;Com o volume criado, agora você pode executar o container Postgres. Para fazer isso, execute o seguinte comando em seu terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker container run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; postgres &lt;span class="nt"&gt;--network&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;artigo &lt;span class="nt"&gt;-p&lt;/span&gt; 5432:5432 &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgres &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;POSTGRES_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgres &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;POSTGRES_DATABASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgres &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;password &lt;span class="nt"&gt;-v&lt;/span&gt; pgdata:/var/lib/postgresql/data postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-d&lt;/code&gt;: essa opção indica que o container será executado em segundo plano.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--name postgres&lt;/code&gt;: com essa opção, você pode dar um nome ao seu container. Neste caso, estamos nomeando o container como "postgres".&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--network&lt;/code&gt;: essa opção é utilizada para especificar a rede à qual um container deve ser conectado durante sua execução.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-p 5432:5432&lt;/code&gt;: essa opção indica que estamos mapeando a porta 5432 do container para a porta 5432 do host. A porta 5432 é a porta padrão do Postgres.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-e POSTGRES_USER=postgres&lt;/code&gt;: essa opção define a variável de ambiente POSTGRES_USER com o &lt;code&gt;user&lt;/code&gt; que você escolher. Por padrão, o &lt;code&gt;user&lt;/code&gt; do PostgreSQL é &lt;code&gt;postgres&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-e POSTGRES_HOST=postgres&lt;/code&gt;: normalmente se refere ao endereço do host onde o banco de dados PostgreSQL está em execução. Se você está executando o PostgreSQL em um container Docker, o &lt;code&gt;POSTGRES_HOST&lt;/code&gt; pode ser o nome do container ou o endereço IP do container, dependendo de como você está configurando a comunicação.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-e POSTGRES_DATABASE=postgres&lt;/code&gt;: essa opção é usada para especificar o nome do banco de dados ao qual você deseja se conectar.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-e POSTGRES_PASSWORD=sua-senha&lt;/code&gt;: essa opção define a variável de ambiente POSTGRES_PASSWORD com a senha que você escolher.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-v pgdata:/var/lib/postgresql/data&lt;/code&gt;: essa opção define o volume &lt;strong&gt;pgdata&lt;/strong&gt; criado anteriormente como o local onde os dados do Postgres serão armazenados.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;postgres&lt;/code&gt;: esse é o nome da imagem que estamos utilizando para criar o container.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;-d&lt;/code&gt; (ou &lt;code&gt;--detach&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;-p&lt;/code&gt; (ou &lt;code&gt;--publish&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;-e&lt;/code&gt; (ou &lt;code&gt;--env&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;-v&lt;/code&gt; (ou &lt;code&gt;--volume&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Criando a imagem do back
&lt;/h2&gt;

&lt;p&gt;O &lt;code&gt;Dockerfile&lt;/code&gt; que esta no diretório &lt;code&gt;/back&lt;/code&gt; não muda muita coisa do que fizemos no front, apenas o &lt;code&gt;EXPOSE&lt;/code&gt; e o &lt;code&gt;CMD&lt;/code&gt; para fazer o start na aplicação.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:18.17.0-alpine&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package*.json ./&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["npm", "run", "start"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No terminal e acesse o diretório &lt;code&gt;./back&lt;/code&gt; e execute o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker image build &lt;span class="nt"&gt;-t&lt;/span&gt; back &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Criando o container do back
&lt;/h2&gt;

&lt;p&gt;Sem segredo algum, vamos fazer o mesmo processo que fizemos com o container do &lt;code&gt;front&lt;/code&gt;. Já temos a imagem do back e com ela podemos criar o tão sonhado container, novamente vá no seu terminal e execute o comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker container run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--network&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;artigo &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:3000 back
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fogd16c4eqprv6ppyv0fk.gif" 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%2Fogd16c4eqprv6ppyv0fk.gif" alt="gif com exemplo de uso do comando do exemplo" width="640" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora nossa aplicação está funcionando completamente, você pode acessar &lt;a href="http://localhost:8080" rel="noopener noreferrer"&gt;http://localhost:8080&lt;/a&gt; e criar uma tarefa e deletar. &lt;/p&gt;

&lt;h1&gt;
  
  
  Docker Compose
&lt;/h1&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%2Fz8s776rui35mbzznp7pj.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%2Fz8s776rui35mbzznp7pj.png" alt="imagem mostrando a relação do compose com containers" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Podemos notar a quantidade de comandos no terminal que foi necessário para que essa pequena aplicação fosse ao ar, com o compose vamos encurtar todo esse processo colocando tudo em um só lugar, facilitando o nosso desenvolvimento. A estrutura do &lt;code&gt;compose.yaml&lt;/code&gt; lembra um pouco o &lt;code&gt;Dockerfile&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3'&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;  back&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;    build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./back/.&lt;/span&gt;
&lt;span class="na"&gt;    ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="s"&gt;      - 3000:3000&lt;/span&gt;
&lt;span class="na"&gt;    depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="s"&gt;      - postgres&lt;/span&gt;
&lt;span class="na"&gt;  front&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;    build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./front/.&lt;/span&gt;
&lt;span class="na"&gt;    ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="s"&gt;      - 8080:8080&lt;/span&gt;
&lt;span class="na"&gt;  postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;    image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:latest&lt;/span&gt;
&lt;span class="na"&gt;    environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;      POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
&lt;span class="na"&gt;      POSTGRES_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
&lt;span class="na"&gt;      POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;password&lt;/span&gt;
&lt;span class="na"&gt;      POSTGRES_DATABASE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
&lt;span class="na"&gt;    volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="s"&gt;      - api-postgres-data:/var/lib/postgresql/data&lt;/span&gt;
&lt;span class="na"&gt;    ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="s"&gt;      - 5432:5432&lt;/span&gt;
&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="na"&gt;  api-postgres-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;version: '3'&lt;/code&gt;: Especifica a versão da sintaxe do Docker Compose que está sendo usada. Neste caso, é a versão 3.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;services&lt;/code&gt;: Define os serviços que serão executados.

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;back&lt;/code&gt;: Configurações para o serviço chamado "back".

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;build: ./back/.&lt;/code&gt;: Especifica que a imagem para o serviço "back" deve ser construída a partir do diretório &lt;code&gt;./back/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ports: - 3000:3000&lt;/code&gt;: Mapeia a porta 3000 do contêiner para a porta 3000 do host.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;depends_on: - postgres&lt;/code&gt;: Indica que o serviço "back" depende do serviço "postgres", garantindo que o serviço "postgres" seja iniciado antes do serviço "back".&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;front&lt;/code&gt;: Configurações para o serviço chamado "front".

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;build: ./front/.&lt;/code&gt;: Especifica que a imagem para o serviço "front" deve ser construída a partir do diretório &lt;code&gt;./front/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ports: - 8080:8080&lt;/code&gt;: Mapeia a porta 8080 do contêiner para a porta 8080 do host.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;postgres&lt;/code&gt;: Configurações para o serviço chamado "postgres".

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;image: postgres:latest&lt;/code&gt;: Usa a imagem oficial mais recente do PostgreSQL disponível no Docker Hub.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;environment:&lt;/code&gt;: Define variáveis de ambiente para configurar o PostgreSQL.

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;POSTGRES_USER&lt;/code&gt;, &lt;code&gt;POSTGRES_HOST&lt;/code&gt;, &lt;code&gt;POSTGRES_PASSWORD&lt;/code&gt;, e &lt;code&gt;POSTGRES_DATABASE&lt;/code&gt; são configurados para criar um usuário, host, senha e banco de dados no PostgreSQL.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;volumes: - api-postgres-data:/var/lib/postgresql/data&lt;/code&gt;: Mapeia um volume chamado "api-postgres-data" para o diretório onde os dados do PostgreSQL são armazenados dentro do contêiner.&lt;/li&gt;

&lt;li&gt;
&lt;code&gt;ports: - 5432:5432&lt;/code&gt;: Mapeia a porta 5432 do contêiner para a porta 5432 do host.
&lt;code&gt;volumes:&lt;/code&gt;:&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;Define um volume chamado "api-postgres-data". Este volume é usado para persistir os dados do PostgreSQL, permitindo que os dados persistam mesmo se o contêiner for removido.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Antes de executar o comando do Compose finalize os dois containers feitos anteriormente para que não de conflito nas portas. Após isso no seu terminal acesse o diretório raiz do projeto, onde está o &lt;code&gt;compose.yaml&lt;/code&gt; e use o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fiom5n8izxhkmklr7nxy8.gif" 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%2Fiom5n8izxhkmklr7nxy8.gif" alt="gif com o comando do exemplo" width="640" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;O processo  de build demora um pouco, lembre-se que esse comando faz o build de 3 containers, no gif é nessa velocidade porque o build esta em cash.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Espero que você tenha percebido o quão maravilhoso é o Compose, a quantidade de trabalho que ele te poupa é absurdo. Apenas com um comando ele cria a imagem do front e back, cria um container a partir da imagem criada para o front, back e para o postgres e ainda cria uma network para que os container possam se comunicar entre eles. Existem muitas outras funcionalidades e opções para se fazer no compose, espero que você tenha ficado curioso com o que possa ser feito.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conteúdo complementar
&lt;/h1&gt;

&lt;p&gt;Tenha a documentação oficial como sua melhor amiga no processo de estudo, mas além dela existe o treinamento da &lt;strong&gt;LINUXtips&lt;/strong&gt;, feito pelo &lt;a href="https://twitter.com/badtux_" rel="noopener noreferrer"&gt;Jeferson Fernando&lt;/a&gt;. Ele disponibilizou &lt;strong&gt;completamente de graça&lt;/strong&gt; o:&lt;br&gt;
&lt;a href="https://livro.descomplicandodocker.com.br" rel="noopener noreferrer"&gt;Livro Descoplicando o Docker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Treinamento completo no &lt;strong&gt;Youtube&lt;/strong&gt;: &lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=qZevFPMtQho&amp;amp;list=PLf-O3X2-mxDn1VpyU2q3fuI6YYeIWp5rR&amp;amp;index=1&amp;amp;t=0s" rel="noopener noreferrer"&gt;Descomplicando Docker&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para quem é muito agoniado, tem o resumo:&lt;br&gt;
&lt;a href="https://youtu.be/MeFyp4VnNx0" rel="noopener noreferrer"&gt;Tudo o que você precisa saber sobre docker em 2h&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para quem quer se especializar um pouco mais:&lt;br&gt;
&lt;a href="https://roadmap.sh/docker" rel="noopener noreferrer"&gt;Roadmap Docker (english)&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Esse conteúdo foi o resultado de um aglomerado de anotações e abstrações que tive durante meu processo de estudo sobre docker, a parte que mais bati cabeça foi com o network, durante os meus testes eu ficava tentando fazer os container se comunicarem entre eles, mas um não encontrava o outro, foi uma grande dor de cabeça, mas no fim deu tudo certo. Algumas explicações acabei sendo bem raso, mas foi no intuito de tentar facilitar seu entendimento sobre alguns tópicos. &lt;/p&gt;

&lt;p&gt;Caso eu tenha feito alguma explicação errada, ficarei agradecido com seu feedback, você pode me encontrar no &lt;a href="https://twitter.com/ClintonRocha_" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; ou no Discord da &lt;a href="https://discord.gg/he4rt" rel="noopener noreferrer"&gt;He4rt&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Obrigado por ler ate aqui.&lt;/p&gt;

</description>
      <category>braziliandevs</category>
      <category>docker</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Lidando com exceções: como fazer erros práticos e elegantes no Express js</title>
      <dc:creator>Clinton Rocha</dc:creator>
      <pubDate>Tue, 16 Jan 2024 00:00:29 +0000</pubDate>
      <link>https://forem.com/clintonrocha98/lidando-com-excecoes-como-fazer-erros-praticos-e-elegantes-no-express-js-4k5b</link>
      <guid>https://forem.com/clintonrocha98/lidando-com-excecoes-como-fazer-erros-praticos-e-elegantes-no-express-js-4k5b</guid>
      <description>&lt;p&gt;Para você, desenvolvedor(a) que esta construindo sua API no &lt;strong&gt;Express&lt;/strong&gt; e se questiona sobre maneiras de aprimorar o tratamento de erros, este artigo promete demonstrar práticas comuns adotadas por muitos e os desafios que podem surgir. Mas a história não para por aí! Vou te apresentar uma abordagem para melhorar a qualidade e personalizar o tratamento de erros na sua aplicação. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/Q0OqU2N1MN3KU/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/Q0OqU2N1MN3KU/giphy.gif" alt="um giff com varios erros na tela" width="500" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Entendendo o que é uma exceção&lt;/li&gt;
&lt;li&gt;Try catch em ação&lt;/li&gt;
&lt;li&gt;Quando o try catch se torna um obstáculo&lt;/li&gt;
&lt;li&gt;Middleware de manipulação de erros&lt;/li&gt;
&lt;li&gt;Middleware como solução elegante&lt;/li&gt;
&lt;li&gt;Personalizando os erros&lt;/li&gt;
&lt;li&gt;Personalizando o middleware de erros&lt;/li&gt;
&lt;li&gt;Erros assíncronos &lt;/li&gt;
&lt;li&gt;Recomendações&lt;/li&gt;
&lt;li&gt;Conclusão&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Entendendo o que é uma exceção
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/bi6RQ5x3tqoSI/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/bi6RQ5x3tqoSI/giphy.gif" alt="gif error" width="450" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Na programação, uma &lt;strong&gt;exceção&lt;/strong&gt; é um evento ou condição que acontece durante a execução de um programa e que pode parar o fluxo da aplicação. O objetivo de lidar com exceções é garantir que o programa possa reagir da melhor maneira a esses eventos anormais, em vez de simplesmente quebrar ou encerrar com seu programa.&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="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextFunction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Response&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="s2"&gt;express&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="nx"&gt;fs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fs&lt;/span&gt;&lt;span class="dl"&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;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&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;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&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="err"&gt; &lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;naoExiste.txt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&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;Temos um código simples que tenta ler um arquivo &lt;code&gt;txt&lt;/code&gt; quando o usuário acessa a rota &lt;code&gt;/&lt;/code&gt;, você sabe o que acontece quando o usuário acessa essa rota sendo que o arquivo não existe? Isso mesmo, um erro 😯 e dos feios, o usuário recebe: &lt;/p&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%2F9hxrsb1uf1wm7jddzh4n.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%2F9hxrsb1uf1wm7jddzh4n.png" alt="Erro dizendo que o arquivo não existe" width="556" height="106"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Não para por aí, para piorar sua situação a aplicação para de funcionar e nenhum usuário vai conseguir acessar ela porque seu código não tem tratamento de erro: &lt;/p&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%2Fizcl6jd5zwj4m5ctop78.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%2Fizcl6jd5zwj4m5ctop78.png" alt="Um erro no console dizendo que o arquivo não foi encontrado" width="630" height="70"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;No seu console o erro vai se maior que isso...&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Entender e lidar com exceções é crucial para garantir a estabilidade do programa. No exemplo acima, a falta de tratamento de exceções resulta em mensagens de erro desagradáveis para o usuário e na interrupção da aplicação.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try catch em ação
&lt;/h2&gt;

&lt;p&gt;No JavaScript, &lt;a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Statements/try...catch" rel="noopener noreferrer"&gt;try catch&lt;/a&gt; é uma estrutura usada para lidar com exceções (erros) durante a execução do código. O bloco &lt;code&gt;try&lt;/code&gt; envolve o código que pode gerar uma exceção, enquanto o bloco &lt;code&gt;catch&lt;/code&gt; é usado para lidar com a exceção se ela ocorrer. Vamos por o &lt;a href="https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Statements/try...catch" rel="noopener noreferrer"&gt;try catch&lt;/a&gt; em ação:&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&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;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&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="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;naoExiste.txt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&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="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Arquivo não encontrado&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&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 usuário vai receber:&lt;/p&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%2Fzug33f5080m75db38u4t.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%2Fzug33f5080m75db38u4t.png" alt="Um erro com a mensagem " width="463" height="110"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bom, agora podemos tratar nossos erros, e note que nossa aplicação não caiu, isso é um avanço. Usar &lt;code&gt;try catch&lt;/code&gt; é uma prática comum para tornar o código mais robusto e controlar erros de maneira elegante, em vez de permitir que o programa pare de funcionar quando ocorre uma exceção.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quando o try catch se torna um obstáculo
&lt;/h2&gt;

&lt;p&gt;O problema que quero destacar neste momento está relacionada à quantidade de vezes que é necessário usar a estrutura &lt;code&gt;try-catch&lt;/code&gt; em uma simples aplicação. A implementação apresentada mostra a repetição do bloco &lt;code&gt;try-catch&lt;/code&gt; em cada endpoint, o que pode tornar o código menos eficiente e mais suscetível a erros de manutenção quando sua aplicação for crescer.&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="c1"&gt;//No mundo real essa variável 'livros' provavelmente seria uma interação com banco de dados&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;livros&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;id&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="nx"&gt;titulo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Livro 1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;autor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Autor 1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;titulo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Livro 2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;autor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Autor 2&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/livros&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;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&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="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt; &lt;/span&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;livros&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Nenhum Livro encontrado&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;livros&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&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="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&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="err"&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/livros/:id&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;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&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="k"&gt;try&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;livroId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&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="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;livroId&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
          &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ID Invalido&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;livro&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;livros&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;livroId&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;livro&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Livro não encontrado&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;livro&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&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="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&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="err"&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/livros&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;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&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="k"&gt;try&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;novoLivro&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;novoLivro&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Informações invalida&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;livros&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;novoLivro&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Livro adicionado 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;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="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&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;menssage&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;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%2F4dxij932zjyqpby9wq82.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%2F4dxij932zjyqpby9wq82.png" alt="um diagrama representando a rota" width="797" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Podemos ver a repetição que é usar essa estrutura para lidar com as exceções, mas não é só isso, existem momentos em que é necessário lidar com peculiaridades dessa estrutura, por exemplo, no exemplo anterior existe uma rota que pode gerar 3 tipos de &lt;code&gt;status&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Status Code 400 (Bad Request)&lt;/strong&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;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;livroId&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ID Invalido&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Status Code 404 (Not Found):&lt;/strong&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;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;livro&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Livro não encontrado&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Até daria para fazer um amontoado de &lt;code&gt;if&lt;/code&gt; e &lt;code&gt;else&lt;/code&gt; como podemos ver em:&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;if &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="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ID 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="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&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="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &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="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Livro não encontrado&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&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="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="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Erro interno do servidor&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;Mas convenhamos que isso deixa o código um pouco poluído e dificulta consequentemente a leitura e futuras manutenções. É importante considerar alternativas que permitam manter a manipulação de erros de forma eficaz, sem a sobrecarga de código.&lt;/p&gt;

&lt;h2&gt;
  
  
  Middleware de manipulação de erros
&lt;/h2&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%2Fk71za3kimgvp2d6rbnov.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%2Fk71za3kimgvp2d6rbnov.png" alt="Na imagem demonstra o lugar que o Middleware ''fica'' que é entre o client e o servidor" width="800" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vamos explorar uma solução para o nosso &lt;em&gt;problema&lt;/em&gt; em específico, visando simplificar a estrutura, melhorar a legibilidade e facilitar futuras modificações na API.&lt;/p&gt;

&lt;p&gt;Deixa eu te apresentar nosso amigo &lt;a href="http://expressjs.com/pt-br/guide/using-middleware.html" rel="noopener noreferrer"&gt;Middleware&lt;/a&gt;, ele tem acesso ao &lt;a href="http://expressjs.com/pt-br/4x/api.html#req" rel="noopener noreferrer"&gt;objeto de solicitação&lt;/a&gt; (&lt;code&gt;req&lt;/code&gt;), o &lt;a href="http://expressjs.com/pt-br/4x/api.html#res" rel="noopener noreferrer"&gt;objeto de resposta&lt;/a&gt; (&lt;code&gt;res&lt;/code&gt;) e com isso podemos solucionar os problemas que foram citados anteriormente, esse colega é atua entre o usuário e sua aplicação,  podemos usar ele em situações diversas, no nosso caso vamos usá-lo na manipulação de erros.&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&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="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextFunction&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="c1"&gt;//aqui que entra a magica =D&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Sempre defina os middlewares de manipulação de erros por último, após outros &lt;code&gt;app.use()&lt;/code&gt; e camadas de rota.&lt;/p&gt;

&lt;p&gt;Middlewares de manipulação de erros sempre levam &lt;em&gt;quatro&lt;/em&gt; argumentos. Você deve fornecer quatro argumentos para identificá-lo como uma função de middleware de manipulação de erros. Mesmo se você não precisar usar o objeto &lt;code&gt;next&lt;/code&gt;, você deve especificá-lo para manter a assinatura. Caso contrário, o objeto &lt;code&gt;next&lt;/code&gt; será interpretado como um middleware comum e a manipulação de erros falhará.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Essa é a estrutura básica de um &lt;strong&gt;Middleware&lt;/strong&gt; no &lt;strong&gt;Express&lt;/strong&gt; especificamente para &lt;a href="http://expressjs.com/pt-br/guide/error-handling.html" rel="noopener noreferrer"&gt;manipulação de erros&lt;/a&gt;.&lt;/p&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%2F17uenxm9bb702n3hjk4k.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%2F17uenxm9bb702n3hjk4k.png" alt="diagrama monstrando as rotas com o uso do middleware" width="389" height="664"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como ilustrado acima, o &lt;strong&gt;Middleware de erro&lt;/strong&gt; atua entre o usuário e as rotas. Tente ver ele como &lt;strong&gt;o responsável por lidar com problemas&lt;/strong&gt;. Qualquer exceção ocorrida em qualquer camada da aplicação pode ser interceptada por esse &lt;strong&gt;middleware&lt;/strong&gt;. Ele desempenha um papel crucial ao capturar e tratar erros, garantindo uma resposta apropriada ao usuário e facilitando a identificação e resolução de problemas na aplicação.&lt;/p&gt;

&lt;h2&gt;
  
  
  Middleware como solução elegante
&lt;/h2&gt;

&lt;p&gt;Agora que você compreendeu o funcionamento do &lt;code&gt;middleware&lt;/code&gt; e reconheceu sua importância na prevenção de falhas, surge a pergunta: "Devo deixar de usar o &lt;code&gt;try-catch&lt;/code&gt;?"&lt;/p&gt;

&lt;p&gt;Calma, pequeno &lt;em&gt;Padawan&lt;/em&gt;. O &lt;code&gt;try-catch&lt;/code&gt; tem seus problemas como foi citado ao decorrer desse conteúdo, essa estrutura é bastante útil em aplicações de pequeno porte, é necessário cogitar a retirada dessa estrutura quando sua aplicação começa a crescer e ter um aumento no nível de complexidade, é aqui que nosso aliado, o &lt;strong&gt;Middleware&lt;/strong&gt;, entra em cena para simplificar e aprimorar a manipulação de erros.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Padawan&lt;/strong&gt; significa aprendiz , iniciante , e é um termo utilizado nos filmes Star Wars.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No exemplo a seguir apresentado, utilizamos o &lt;strong&gt;Middleware&lt;/strong&gt; para lidar com erros de forma centralizada. Ao invés de repetir a estrutura &lt;code&gt;try-catch&lt;/code&gt; em cada rota, delegamos essa responsabilidade ao &lt;strong&gt;Middleware&lt;/strong&gt; de erros.&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/livros&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;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&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="err"&gt; &lt;/span&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;livros&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&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 existe nenhum livro&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;livros&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/livros/:id&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;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&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="err"&gt; &lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;livroId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&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="err"&gt; &lt;/span&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;livroId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ID invalido&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&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;livro&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;livros&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;livroId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&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;livro&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;O livro que você procura não existe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;livro&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/livros&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;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&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="err"&gt; &lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;novoLivro&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="err"&gt; &lt;/span&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;novoLivro&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Informe um livro valido&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nx"&gt;livros&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;novoLivro&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Livro adicionado 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="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&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="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextFunction&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="c1"&gt;//aqui que entra a magica =D&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O resultado é notável, o &lt;strong&gt;middleware&lt;/strong&gt; intercepta esses erros, evitando a necessidade de &lt;code&gt;try-catch&lt;/code&gt; em cada rota. Além disso, conseguimos personalizar as respostas de erro de maneira mais controlada e esteticamente agradável.&lt;/p&gt;

&lt;p&gt;Você deve ter notado que não conseguimos mudar o &lt;code&gt;status code&lt;/code&gt;, mas não se preocupe ainda vamos aprimorar esse código, ajustando os códigos de status e refinando as respostas de erro. O importante é que sua aplicação não falha catastroficamente, e agora, estamos trilhando um caminho mais elegante na gestão de exceções.&lt;/p&gt;

&lt;h2&gt;
  
  
  Personalizando os erros
&lt;/h2&gt;

&lt;p&gt;Você deve saber que a quantidade de &lt;a href="https://http.cat" rel="noopener noreferrer"&gt;status code&lt;/a&gt; é limitada, e isso pode diminuir muito mais ao depender da sua aplicação, tendo isso em mente, vamos usar o principio &lt;a href="https://dev.to/clintonrocha98/era-solid-o-que-me-faltava-bhp#s-princ%C3%ADpio-da-responsabilidade-%C3%BAnica"&gt;Princípio da responsabilidade única&lt;/a&gt; do SOLID para melhorar a legibilidade do nosso código e consequente deixando mais organizado.&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;ApiError&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Error&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;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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;message&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;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&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="k"&gt;this&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="nx"&gt;statusCode&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BadRequestError&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ApiError&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;message&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;super&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="mi"&gt;400&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotFoundError&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ApiError&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;message&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;super&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="mi"&gt;404&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UnauthorizedError&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ApiError&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;message&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;super&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="mi"&gt;401&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;Vamos usar a classe &lt;code&gt;ApiError&lt;/code&gt; como classe base que estende a classe nativa &lt;code&gt;Error&lt;/code&gt; e adicionar &lt;code&gt;statusCode&lt;/code&gt;. No tópico acima, ao falar do &lt;strong&gt;middleware&lt;/strong&gt; foi dito que não dava para mudar o &lt;code&gt;status code&lt;/code&gt; do erro ao usar &lt;code&gt;throw new Error()&lt;/code&gt;, mas com essa implementação podemos ver que esse problema foi solucionado.&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;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BadRequestError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ID Invalido&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NotFoundError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Livro não encontrado&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;UnauthorizedError&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 autorizado!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Personalizando o middleware de erros
&lt;/h2&gt;

&lt;p&gt;Ao implementar as melhorias no lançamento de erros é necessário melhorar o responsável por lidar com esses erros, confesso que não tem muito segredo.&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;NextFunction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Response&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="s2"&gt;express&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;ApiError&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="s2"&gt;./helpers/api-errors&lt;/span&gt;&lt;span class="dl"&gt;"&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;const&lt;/span&gt; &lt;span class="nx"&gt;errorMiddleware&lt;/span&gt; &lt;span class="o"&gt;=&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="nb"&gt;Error&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ApiError&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;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextFunction&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="nx"&gt;statusCode&lt;/span&gt; &lt;span class="o"&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;statusCode&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;500&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;message&lt;/span&gt; &lt;span class="o"&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;statusCode&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Internal Server Error&lt;/span&gt;&lt;span class="dl"&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;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Acredito que a parte que você precisa ter cuidado para não se esquecer é em relação ao &lt;code&gt;type&lt;/code&gt; do parâmetro &lt;code&gt;error&lt;/code&gt; que é &lt;code&gt;Error &amp;amp; Partial&amp;lt;ApiError&amp;gt;&lt;/code&gt; lembre-se que &lt;code&gt;statusCode&lt;/code&gt; não existe no &lt;code&gt;type&lt;/code&gt; nativo &lt;code&gt;Error&lt;/code&gt;, sendo necessário fazer essa intersecção e o uso do &lt;code&gt;Partial&amp;lt;&amp;gt;&lt;/code&gt; do &lt;strong&gt;Typescript&lt;/strong&gt; porque nem sempre o erro lançado vai ser gerado pelo seu código, às vezes pode ser algo relacionado ao baco de dados ou algum outro problema.&lt;/p&gt;

&lt;h2&gt;
  
  
  Erros assíncronos
&lt;/h2&gt;

&lt;p&gt;Legal, já melhoramos nosso código e estamos preparados para todo erro que aparecer, será mesmo? Todos os exemplos utilizados até agora foram códigos &lt;a href="https://developer.mozilla.org/pt-BR/docs/Glossary/Synchronous" rel="noopener noreferrer"&gt;síncronos&lt;/a&gt; e nenhum nenhum &lt;a href="https://developer.mozilla.org/pt-BR/docs/Glossary/Asynchronous" rel="noopener noreferrer"&gt;assíncrono&lt;/a&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="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/livros&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="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&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="nx"&gt;livros&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;buscarLivrosDoBancoDeDados&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;livros&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
     &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NotFoundError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Livro não encontrado&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;livros&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;Se ocorrer algum problema no banco de dados no exemplo acima, seu middleware seria incapaz de capturar o erro, resultando na quebra da aplicação.&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/livros&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="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NextFunction&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="k"&gt;try&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;livros&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;buscarLivrosDoBancoDeDados&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;livros&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NotFoundError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Livro não encontrado&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;livros&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
        &lt;span class="p"&gt;}&lt;/span&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="nf"&gt;next&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para que nosso middleware funcionasse teríamos que voltar a usar o &lt;code&gt;try catch&lt;/code&gt; em conjunto do &lt;code&gt;next(error)&lt;/code&gt; e só assim o &lt;strong&gt;Express&lt;/strong&gt; conseguiria ter acesso a esse erro, mas não se preocupe que existe uma solução para isso.&lt;/p&gt;

&lt;p&gt;A lib &lt;code&gt;express-async-errors&lt;/code&gt; oferece um suporte simples e eficaz para lidar com funções assíncronas utilizando ES6 async/await no Express. O principal objetivo é simplificar a manipulação de erros em funções assíncronas, eliminando a necessidade de chamar manualmente a função &lt;code&gt;next&lt;/code&gt; para propagar erros.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i express-async-errors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Em seguida, adicione no topo do seu arquivo &lt;code&gt;index.ts&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express-async-errors&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pronto, agora podemos voltar a lançar os erros sem o uso do &lt;code&gt;try catch&lt;/code&gt;. Essencialmente, a lib &lt;code&gt;express-async-errors&lt;/code&gt; simplifica a manipulação de erros em funções assíncronas no Express, permitindo que você use exceções para tratar erros sem a necessidade de chamar explicitamente &lt;code&gt;next&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recomendações
&lt;/h2&gt;

&lt;p&gt;Todos os links que foram utilizados nesse artigo são bastante uteis para sua compreensão, não pule nenhum. Fora isso eu tenho algumas recomendações: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/danielhe4rt"&gt;Daniel Reis&lt;/a&gt; com sua didática excepcional fez o artigo &lt;a href="https://dev.to/he4rt/criando-exceptions-para-impressionar-no-teste-tecnico-2nie"&gt;Criando Exceptions para impressionar no Teste Técnico&lt;/a&gt; a abordagem dele é parecida com a usada nesse artigo, provavelmente você vai conseguir melhorar ainda mais seu código ao ler esse artigo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/m1guelsb"&gt;Miguel Barbosa&lt;/a&gt; tem um artigo muito maneiro com tratamento de erro, &lt;a href="https://dev.to/m1guelsb/como-tratar-erros-http-no-spring-boot-41de"&gt;Como tratar erros http no Spring Boot&lt;/a&gt; , eu nunca fiz algo em Java, mas a explicação é tão legal e com uma abordagem super compreensível que chega a ser impossível você não entender, recomendo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/erickwendel_" rel="noopener noreferrer"&gt;Erick Wendel&lt;/a&gt; tem um vídeo muito maneiro sobre erros no Javascript &lt;a href="https://youtu.be/iC_tKAyLeag?si=6WxhIjYFx03FpALg" rel="noopener noreferrer"&gt;Sistemas feitos em JavaScript não são confiáveis?! Error Handling&lt;/a&gt; lá ele fala um pouco sobre o &lt;code&gt;try catch&lt;/code&gt; e muito mais.&lt;/p&gt;

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

&lt;p&gt;Esse conteúdo foi mais complicado do que imaginei, espero que você leitor tenha entendido e aprendido algo novo. No casso de algum erro no código ou falha na explicação eu ficarei grato com seu feedback, você consegue me encontrar no &lt;a href="https://twitter.com/ClintonRocha_" rel="noopener noreferrer"&gt;twitter&lt;/a&gt; ou no Discord da &lt;a href="https://discord.gg/he4rt" rel="noopener noreferrer"&gt;He4rt&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Obrigado por ler até aqui. &lt;/p&gt;

</description>
      <category>braziliandevs</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Era SOLID o que me faltava</title>
      <dc:creator>Clinton Rocha</dc:creator>
      <pubDate>Tue, 02 Jan 2024 22:16:37 +0000</pubDate>
      <link>https://forem.com/clintonrocha98/era-solid-o-que-me-faltava-bhp</link>
      <guid>https://forem.com/clintonrocha98/era-solid-o-que-me-faltava-bhp</guid>
      <description>&lt;p&gt;Começou agora na &lt;strong&gt;programação orientada a objetos&lt;/strong&gt; e não sabe sobre &lt;strong&gt;SOLID&lt;/strong&gt;? Não se preocupe, nesse artigo vou te explicar e dar exemplos de como usá-lo no desenvolvimento do seu código. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O que é SOLID?&lt;/li&gt;
&lt;li&gt;S - Princípio da responsabilidade única&lt;/li&gt;
&lt;li&gt;O - Princípio Aberto-Fechado&lt;/li&gt;
&lt;li&gt;L - Princípio da substituição de Liskov&lt;/li&gt;
&lt;li&gt;I - Princípio da Segregação da Interface&lt;/li&gt;
&lt;li&gt;D - Princípio da inversão da dependência&lt;/li&gt;
&lt;li&gt;Conclusão&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  O que é SOLID?
&lt;/h2&gt;

&lt;p&gt;Na programação orientada a objetos, o termo &lt;strong&gt;SOLID&lt;/strong&gt; é um &lt;a href="https://pt.wikipedia.org/wiki/Acr%C3%B3nimo" rel="noopener noreferrer"&gt;acrônimo&lt;/a&gt; para cinco postulados de design, destinados a facilitar a compreensão, o desenvolvimento e a manutenção de software.&lt;/p&gt;

&lt;p&gt;Ao usar esse conjunto de princípios é notável a redução na produção de bugs, melhora na qualidade do código, produção de códigos mais organizados, na redução de acoplamento, na melhora da refatoração e estimula o reaproveitamento do código.&lt;/p&gt;

&lt;h2&gt;
  
  
  S - Princípio da responsabilidade única
&lt;/h2&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%2Foebel9z9m0pupvh0bg02.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%2Foebel9z9m0pupvh0bg02.png" alt="exemplo Princípio da responsabilidade única" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;SRP - Single Responsibility Principle&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Esse principio diz que &lt;strong&gt;uma classe deve ter um, e somente um, motivo para mudar&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;É isso ai, nada de fazer classes que tenha varias funcionalidades e responsabilidades. Provavelmente você já fez ou se deparou com alguma classe que faz de tudo um pouco, a tal da &lt;em&gt;God Class&lt;/em&gt;. Pode parecer que está tudo bem naquele momento, porem quando for necessário fazer alguma alteração na logica dessa classe é certeza que os problemas vão começar a aparecer.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;God Class - Classe Deus:&lt;/strong&gt; Na programação orientada a objetos, é uma classe que sabe demais ou faz demais.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&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;Task&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;createTask&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="cm"&gt;/*...*/&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;updateTask&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="cm"&gt;/*...*/&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;deleteTask&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="cm"&gt;/*...*/&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;showAllTasks&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="cm"&gt;/*...*/&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;existsTask&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="cm"&gt;/*...*/&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;TaskCompleter&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="cm"&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;Essa classe &lt;strong&gt;Task&lt;/strong&gt; esta quebrando o princípio do &lt;strong&gt;SRP&lt;/strong&gt; por esta fazendo &lt;strong&gt;QUATRO&lt;/strong&gt; tarefas diferentes. Ela está lidando com os dados, exibição, validação e verificação da &lt;strong&gt;Task&lt;/strong&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Problemas que isso pode causar:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Falta de nexo&lt;/code&gt; - uma classe não deve assumir responsabilidades que não são suas;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Muita informação junta&lt;/code&gt;  - sua classe vai ficar com muitas dependências e uma grande dificuldade para alterações; &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Dificuldades na implementação de testes automatizados&lt;/code&gt; - é difícil de &lt;a href="https://pt.wikipedia.org/wiki/Objeto_Mock" rel="noopener noreferrer"&gt;“mockar”&lt;/a&gt; esse tipo de classe;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agora aplicando &lt;strong&gt;SRP&lt;/strong&gt; na classe &lt;em&gt;Task&lt;/em&gt;, vamos ver a melhora que esse principio pode causar:&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;TaskHandler&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nf"&gt;createTask&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/*...*/&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; 
    &lt;span class="nf"&gt;updateTask&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/*...*/&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; 
    &lt;span class="nf"&gt;deleteTask&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&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;TaskViewer&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nf"&gt;showAllTasks&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&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;TaskChecker&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nf"&gt;existsTask&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&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;TaskCompleter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nf"&gt;completeTask&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="cm"&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;blockquote&gt;
&lt;p&gt;Daria para colocar create, update e delete em classes separadas, mas ao depender do contexto e tamanho do projeto é bom evitar complexidade desnecessária.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Talvez você tenha se perguntado &lt;code&gt;só vou conseguir aplicar isso em classes?&lt;/code&gt; não, pelo contrário, da para aplicar em métodos e funções também.&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="c1"&gt;//❌&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;emailClients&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clients&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IClient&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nx"&gt;clients&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;client&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="nx"&gt;clientRecord&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;client&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="nx"&gt;clientRecord&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="nf"&gt;sendEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;client&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="c1"&gt;//✅&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;isClientActive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IClient&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clientRecord&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="nx"&gt;clientRecord&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getActiveClients&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clients&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IClient&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IClient&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&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="nx"&gt;clients&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;isClientActive&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;emailClients&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clients&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IClient&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;activeClients&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getActiveClients&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clients&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;activeClients&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;sandEmail&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;Código mais bonito, elegante e organizado. Esse principio é a base para os outros, ao conseguir aplicá-lo você estará fazendo um código de ótima qualidade, de fácil leitura e de fácil manutenção. &lt;/p&gt;

&lt;h2&gt;
  
  
  O - Princípio Aberto Fechado
&lt;/h2&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%2Fqk0e24cnjefd5e8r0h6c.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%2Fqk0e24cnjefd5e8r0h6c.png" alt="exemplo Princípio Aberto-Fechado" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;OCP - Open-Closed Principle&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Esse principio diz que &lt;strong&gt;Objetos ou entidades devem estar abertos para extensão, mas fechados para modificação&lt;/strong&gt;, se for necessário adicionar uma funcionalidade é melhor estender e não alterar seu código fonte. &lt;/p&gt;

&lt;p&gt;Imagine um pequeno sistema para secretaria de escolar, nele existem duas classes que representa a grade de aulas dos alunos, ensino fundamental e ensino médio. Além de uma classe que é para definir as aulas do aluno.&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;EnsinoFundamental&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;gradeCurricularFundamental&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;EnsinoMedio&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;gradeCurricularMedio&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;SecretariaEscola&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;aulasDoAluno&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="nf"&gt;cadastrarAula&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aulasAluno&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="nx"&gt;aulasAluno&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;EnsinoFundamental&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;aulasDoAluno&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aulasAluno&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gradeCurricularFundamental&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="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aulasAluno&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ensino&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;EnsinoMedio&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;aulasDoAluno&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aulasAluno&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gradeCurricularMedio&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;A classe &lt;code&gt;SecretariaEscola&lt;/code&gt; é responsável por verificar qual o ensino do aluno para conseguir aplicar a regra de negócio certa na hora do cadastrar as aulas. Agora imagine que essa escola tenha adicionado o ensino técnico e sua grade de aulas no sistema, vai ser necessário modificar essa classe, certo?, só que ai você esbarra em um problema, o de violar o &lt;code&gt;Princípio Aberto-Fechado&lt;/code&gt; do &lt;em&gt;SOLID&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Qual a solução que te vem a cabeça? Provavelmente adicionar um &lt;code&gt;else if&lt;/code&gt; na classe e pronto, problema resolvido 😁. Não pequeno Padawan 😐, ai que está o problema! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Alterar uma classe já existente para adicionar um novo comportamento, corremos um sério risco de introduzir bugs em algo que já estava funcionando.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Lembre-se:&lt;/strong&gt; &lt;strong&gt;OCP&lt;/strong&gt; preza que uma classe deve estar fechada para alteração e aberta para extensão.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Veja a beleza que fica ao refatorar o 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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;gradeCurricular&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;gradeDeAulas&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;EnsinoFundamental&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;gradeCurricular&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;gradeDeAulas&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;EnsinoMedio&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;gradeCurricular&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;gradeDeAulas&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;EnsinoTecnico&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;gradeCurricular&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;gradeDeAulas&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;SecretariaEscola&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;aulasDoAluno&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="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;cadastrarAula&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aulasAluno&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;gradeCurricular&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&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;aulasDoAluno&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aulasAluno&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gradeDeAulas&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&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;Veja a classe &lt;code&gt;SecretariaEscola&lt;/code&gt; ela não precisa mais saber quais os métodos chamar para cadastrar a aula. Ela será capaz de cadastrar a grade de aulas corretamente de qualquer novo tipo de modalidade de ensino que seja criado, observe que adicionei o &lt;code&gt;EnsinoTecnico&lt;/code&gt; sem nenhuma necessidade de mudar o código-fonte. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Desde que implemente a interface &lt;code&gt;gradeCurricular&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Separe o comportamento extensível por trás de uma interface e inverta as dependências.&lt;br&gt;&lt;br&gt;
Uncle Bob&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Aberto para extensão&lt;/code&gt;: você pode adicionar alguma nova funcionalidade ou comportamento a classe sem alterar seu código-fonte. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Fechado para modificação&lt;/code&gt;: se sua classe já tem uma funcionalidade ou comportamento que não apresenta problema algum, não altere o código-fonte dela para colocar algo novo.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  L - Princípio da substituição de Liskov
&lt;/h2&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%2Feyrl3p96aqzowf72ipcb.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%2Feyrl3p96aqzowf72ipcb.png" alt="exemplo Princípio da substituição de Liskov" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;LSP - Liskov Substitution Principle&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Princípio da substituição de Liskov — &lt;strong&gt;Uma&lt;/strong&gt; &lt;strong&gt;classe derivada deve ser substituível por sua classe base&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Esse principio que o &lt;em&gt;mano&lt;/em&gt; Liskov introduziu em uma conferência no ano de 1987 é um pouco complicada de se entender ao ler a explicação dele, mas não se preocupe, vou mostrar outra explicação e um exemplo que vai te ajudar a entender.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Se para cada objeto o1 do tipo S há um objeto o2 do tipo T de forma que, para todos os programas P definidos em termos de T, o comportamento de P é inalterado quando o1 é substituído por o2 então S é um subtipo de T&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Entendeu? Não né, eu também não entendi na primeira vez que li isso (nem nas outras dez vezes), mas calma aí, existe outra explicação:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Se S é um subtipo de T, então os objetos do tipo T, em um programa, podem ser substituídos pelos objetos de tipo S sem que seja necessário alterar as propriedades deste programa. — &lt;a href="https://pt.wikipedia.org/wiki/Princ%C3%ADpio_da_substitui%C3%A7%C3%A3o_de_Liskov" rel="noopener noreferrer"&gt;Wikipedia&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Se você é mais visual calma que tenho exemplos em 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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Fulano&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;falarNome&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sou fulano!&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;Sicrano&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Fulano&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;falarNome&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sou sicrano!&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;const&lt;/span&gt; &lt;span class="nx"&gt;a&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;Fulano&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;b&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;Sicrano&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;imprimirNome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&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="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="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;imprimirNome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;falarNome&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// sou fulano!&lt;/span&gt;
&lt;span class="nf"&gt;imprimirNome&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;falarNome&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; &lt;span class="c1"&gt;// sou sicrano!&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A classe pai e a classe derivada estão passando como parâmetro e o código continua funcionando da forma esperada, magica? Que nada, é o princípio do nosso mano Liskov. &lt;/p&gt;

&lt;h3&gt;
  
  
  Exemplos de violações:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Sobrescrever/implementar um método que não faz nada;&lt;/li&gt;
&lt;li&gt;Lançar uma exceção inesperada;&lt;/li&gt;
&lt;li&gt;Retornar valores de tipos diferentes da classe base;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  I - Princípio da Segregação da Interface
&lt;/h2&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%2Fp88do8ivd00s9aofo5yq.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%2Fp88do8ivd00s9aofo5yq.png" alt="exemplo Princípio da Segregação da Interface&amp;lt;br&amp;gt;
" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;ISP - Interface Segregation Principle&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Princípio da Segregação da Interface — &lt;strong&gt;Uma classe não deve ser forçada a implementar interfaces e métodos que não irão utilizar.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Esse principio diz que é melhor criar interfaces mais especificas do que uma interface genérica.&lt;/p&gt;

&lt;p&gt;No exemplo a seguir foi criado uma interface &lt;code&gt;Animal&lt;/code&gt; para abstrair os comportamentos de animais e em seguida as classes implementam essa interface, veja:&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;Animal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;comer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;dormir&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;voar&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;Pato&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;comer&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="cm"&gt;/*faz algo*/&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nf"&gt;dormir&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="cm"&gt;/*faz algo*/&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nf"&gt;voar&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="cm"&gt;/*faz algo*/&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;Peixe&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;comer&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="cm"&gt;/*faz algo*/&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nf"&gt;dormir&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="cm"&gt;/*faz algo*/&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="nf"&gt;voar&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="cm"&gt;/*faz algo*/&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="c1"&gt;// Esta implementação não faz sentido para um peixe &lt;/span&gt;
    &lt;span class="c1"&gt;// ela viola o Princípio da Segregação da Interface&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A interface genérica &lt;code&gt;Animal&lt;/code&gt; esta forçando a classe &lt;code&gt;Peixe&lt;/code&gt; a ter um comportamento que faz sentido e acaba viola o principio &lt;strong&gt;ISP&lt;/strong&gt; e o &lt;strong&gt;LSP&lt;/strong&gt; também. &lt;/p&gt;

&lt;p&gt;Resolvendo esse problema usando o &lt;strong&gt;ISP&lt;/strong&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Animal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;comer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;dormir&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;AnimalQueVoa&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Animal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;voar&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;Peixe&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;comer&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="cm"&gt;/*faz algo*/&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nf"&gt;dormir&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="cm"&gt;/*faz algo*/&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;Pato&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;AnimalQueVoa&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;comer&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="cm"&gt;/*faz algo*/&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nf"&gt;dormir&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="cm"&gt;/*faz algo*/&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nf"&gt;voar&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="cm"&gt;/*faz algo*/&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 ficou melhor, foi retirado o método &lt;code&gt;voar()&lt;/code&gt; da interface &lt;code&gt;Animal&lt;/code&gt; e adicionamos em uma interface derivada &lt;code&gt;AnimalQueVoa&lt;/code&gt;. Com isso o comportamento foi isolado de maneira correta dentro do nosso contexto e ainda respeitamos o principio de segregação das interfaces. &lt;/p&gt;

&lt;h2&gt;
  
  
  D - Princípio da inversão da dependência
&lt;/h2&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%2F9s5ywa9xijb41c1z2l1a.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%2F9s5ywa9xijb41c1z2l1a.png" alt="exemplo Princípio da inversão da dependência" width="503" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;DIP — Dependency Inversion Principle&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Princípio da Inversão de Dependência — &lt;strong&gt;Dependa de abstrações e não de implementações.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Módulos de alto nível não devem depender de módulos de baixo nível. Ambos devem depender da abstração.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Abstrações não devem depender de detalhes. Detalhes devem depender de abstrações. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Uncle Bob&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;No exemplo a seguir vou mostrar um codigo simples para ilustrar o &lt;strong&gt;DIP&lt;/strong&gt;. Nesse exemplo temos um sistema de notificação que envia mensagens por diferentes meios, como e-mail e SMS. Primeiro vamos criar classes concretas para esses meios de notificação:&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;EmailNotification&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;send&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="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: &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="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;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SMSNotification&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;send&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="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 SMS: &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="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;Agora, vamos criar uma classe de serviço que depende dessas implementações concretas:&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;NotificationService&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emailNotification&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;EmailNotification&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;smsNotification&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;SMSNotification&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;sendNotifications&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="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;emailNotification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;smsNotification&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&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="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 exemplo acima, &lt;code&gt;NotificationService&lt;/code&gt; depende diretamente das implementações concretas de &lt;code&gt;EmailNotification&lt;/code&gt; e &lt;code&gt;SMSNotification&lt;/code&gt;. Isso viola o DIP, pois a classe de alto nível &lt;code&gt;NotificationService&lt;/code&gt; está diretamente dependente de classes de baixo nível.&lt;/p&gt;

&lt;p&gt;Vamos corrigir esse código usando &lt;strong&gt;DIP&lt;/strong&gt;. Em vez de depender de implementações concretas, a classe de alto nível &lt;code&gt;NotificationService&lt;/code&gt; deve depender de abstrações. Vamos criar uma interface &lt;code&gt;Notification&lt;/code&gt; como abstração:&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="c1"&gt;// Abstração para o envio de notificações&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Notification&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nf"&gt;send&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="kr"&gt;string&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, as implementações concretas &lt;code&gt;EmailNotification&lt;/code&gt; e &lt;code&gt;SMSNotification&lt;/code&gt; devem implementar essa interface:&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;EmailNotification&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Notification&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;send&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="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="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: &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="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;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SMSNotification&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Notification&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;send&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="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="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 SMS: &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="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;Finalmente, a classe de serviço de notificação pode depender da abstração &lt;code&gt;Notification&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NotificationService&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;notificationMethod&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Notification&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;notificationMethod&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Notification&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;notificationMethod&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;notificationMethod&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;sendNotification&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="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="nx"&gt;notificationMethod&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&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="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;Dessa forma, a classe de serviço &lt;code&gt;NotificationService&lt;/code&gt; depende de uma abstração &lt;code&gt;Notification&lt;/code&gt;, e não das implementações concretas, cumprindo assim o &lt;strong&gt;Princípio da Inversão de Dependência&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;Ao adotar esses princípios, os desenvolvedores podem criar sistemas mais resilientes às mudanças, facilitando a manutenção e melhorando a qualidade do código ao longo do tempo. &lt;/p&gt;

&lt;p&gt;Todo esse conteúdo foi baseado em anotações, outros artigos e vídeos que encontrei pela internet durante meu estudo sobre POO, as explicações são próximas aos autores dos princípios, já os códigos usados nos exemplos eu criei baseado no meu entendimento dos princípios. Espero ter ajudado a você leitor na progressão dos seus estudos. &lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>productivity</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Sem Stress, Só Perguntas: Um mini guia para perguntar de maneira eficiente</title>
      <dc:creator>Clinton Rocha</dc:creator>
      <pubDate>Mon, 04 Dec 2023 12:03:45 +0000</pubDate>
      <link>https://forem.com/clintonrocha98/sem-stress-so-perguntas-um-mini-guia-para-perguntar-de-maneira-eficiente-18hd</link>
      <guid>https://forem.com/clintonrocha98/sem-stress-so-perguntas-um-mini-guia-para-perguntar-de-maneira-eficiente-18hd</guid>
      <description>&lt;p&gt;Se você já se viu diante de um problema de código ou teve dúvidas sobre alguma tecnologia, mas não soube como formular a pergunta de maneira eficiente, este artigo é para você.&lt;/p&gt;

&lt;p&gt;No twitter ou em grupos do Discord me deparo com perguntas que demandam tempo ou que são desgastantes para serem respondidas, e não é porque o problema é complexo ou algo do tipo, mas porque a pergunta é feita contendo pouca informação e de forma muito abrangente, dificultando uma resposta rápida e direta.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sumário
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;O que deve ser comunicado?&lt;/li&gt;
&lt;li&gt;Pesquise no Google&lt;/li&gt;
&lt;li&gt;Escrevendo perguntas&lt;/li&gt;
&lt;li&gt;Conclusão&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  O que deve ser comunicado?
&lt;/h2&gt;

&lt;p&gt;Ao buscar ajuda, se coloque no lugar de quem vai analisar o seu problema. Antes de enviar qualquer mensagem pedindo auxílio, pergunte a si: &lt;br&gt;
&lt;code&gt;"O que a pessoa que está olhando meu problema precisa para me ajudar?"&lt;/code&gt;&lt;br&gt;
Quem for olhar seu problema caiu de paraquedas e precisa entender a situação da melhor maneira possível para poder te ajudar. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Contextualize a situação:&lt;/code&gt; Antes de compartilhar seu código, forneça um contexto claro, fale do proposito do código e um pouco do que você está fazendo.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Descreva suas tentativas e objetivos:&lt;/code&gt; Fale o que você já tentou para resolver o problema. Isso não apenas evita sugestões repetitivas, mas também mostra que você está se esforçando resolver o problema. Inclua detalhes sobre mensagens de erro específicas que você encontrou e qualquer ideia que tenha tido durante o processo.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Capturas de Tela e Códigos Relevantes:&lt;/code&gt; Se o problema estiver relacionado a uma mensagem de erro, capture a tela dessa mensagem. Imagens podem oferecer uma visão instantânea do problema. Além disso, compartilhe pequenos blocos de código diretamente relacionados à questão. Isso simplifica a análise para quem está ajudando e aumenta a probabilidade de uma resposta eficaz.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Use &lt;a href="https://carbon.now.sh" rel="noopener noreferrer"&gt;carbon&lt;/a&gt;, &lt;a href="https://docs.github.com/pt/get-started/writing-on-github/editing-and-sharing-content-with-gists/creating-gists#creating-a-gist" rel="noopener noreferrer"&gt;gist&lt;/a&gt; ou &lt;a href="https://codepen.io/" rel="noopener noreferrer"&gt;codepen&lt;/a&gt;  para compartilhar seu código de maneira limpa e organizada.&lt;/p&gt;

&lt;p&gt;Evite tire fotos usando o celular, use alguma ferramenta de captura de tela.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Pesquise no Google
&lt;/h2&gt;

&lt;p&gt;Isso pode ser um conselho muito obvio, mas vejo muita gente perguntando algo que com apenas uma pesquisa resolveria o problema dela.&lt;/p&gt;

&lt;p&gt;Seu problema não é especial, provavelmente alguém já passou por ele e perguntou em algum lugar da internet. Pesquisar no Google não apenas economiza tempo. Além disso, ao explorar fóruns, comunidades online e sites, você pode descobrir soluções detalhadas para problemas comuns.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tenha cuidado com sites e fóruns que tenham respostas antigas, provavelmente aquela solução esteja desatualizada.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;É importante destacar que a documentação da linguagem, biblioteca ou framework que você está utilizando é a fonte primária de informações. Ler a documentação pode fornecer inspirações valiosos sobre funcionalidades, métodos e práticas recomendadas. &lt;/p&gt;

&lt;p&gt;Portanto, antes de postar sua pergunta em um fórum ou comunidade, reserve um tempo para pesquisar no Google. Essa abordagem não apenas fortalecerá suas habilidades de resolução de problemas, mas também o conectará com a riqueza de conhecimento disponível na vasta rede de desenvolvedores.&lt;/p&gt;

&lt;h2&gt;
  
  
  Escrevendo perguntas
&lt;/h2&gt;

&lt;p&gt;Agora vou te mostrar como perguntar de maneira mais eficiente, facilitando a sua vida e a vida do programador que vai te ajudar.&lt;/p&gt;

&lt;h3&gt;
  
  
  Não pergunte assim❌
&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%2F5c3evgskdyht1qkymx0y.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%2F5c3evgskdyht1qkymx0y.png" alt="Uma pessoa perguntando: " width="359" height="66"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Pergunte assim ✅
&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%2F6gwvponcad0fia6s2vza.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%2F6gwvponcad0fia6s2vza.png" alt="A mesma pessoa fazendo outra pergunta de forma mais elaborada" width="465" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As perguntas acima foram feitas apenas para ilustrar o meu ponto. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Na maioria das vezes a primeira pergunta é ignorada ou então atrai pessoas que não vão conseguir solucionar seu problema. O que a pessoa perguntou, na verdade, aqui é:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Qualquer programador que esteja disposto a se comprometer a investigar meu problema, seja ele qual for, mesmo que não seja realmente relacionado a programação ou se alguém que não sabe nada sobre programação poderia realmente responder à minha pergunta?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Agora veja duas perguntas feitas em uma comunidade do Discord, você vai notar a diferença de resposta.&lt;/p&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%2F0u3sr7o6krq0djlp66kn.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%2F0u3sr7o6krq0djlp66kn.png" alt="Uma pessoa perguntando se tem alguém para ajudar e outras duas pessoas pedindo para que a pessoa fale sobre a dúvida" width="306" height="282"&gt;&lt;/a&gt;&lt;/p&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%2Fqa233tiznxz6099f1bfa.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%2Fqa233tiznxz6099f1bfa.png" alt="Uma pessoa fazendo uma pergunta bem elaborada e com contexto junto dela tem uma captura de tela com o erro que ela quer ajuda" width="800" height="539"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No segundo, um pequeno contexto do problema, a dúvida que a pessoa tinha e em seguida uma captura de tela do erro, dá para perceber que as pessoas já aparecem com diferentes soluções.&lt;/p&gt;

&lt;p&gt;No primeiro, tem menos diálogo, e as pessoas precisam perguntar o contexto e o seu objetivo para tentar te ajudar, isso parece algo pequeno, mas demanda energia e disposição.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.possoperguntar.com.br" rel="noopener noreferrer"&gt;Posso perguntar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pt.stackoverflow.com/help/how-to-ask" rel="noopener noreferrer"&gt;Como fazer uma boa pergunta&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Esse é meu primeiro post no dev.to e espero ter ajudado alguém😁. Foi um processo interessante.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>tutorial</category>
      <category>productivity</category>
      <category>braziliandevs</category>
    </item>
  </channel>
</rss>
