<?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: Yuri Peixinho</title>
    <description>The latest articles on Forem by Yuri Peixinho (@yuripeixinho).</description>
    <link>https://forem.com/yuripeixinho</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%2F1647416%2Fcb24132f-cdc1-4080-8977-0786f79ceb26.png</url>
      <title>Forem: Yuri Peixinho</title>
      <link>https://forem.com/yuripeixinho</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/yuripeixinho"/>
    <language>en</language>
    <item>
      <title>ISP — Interface Segregation Principle (Princípio da Segregação de Interface)</title>
      <dc:creator>Yuri Peixinho</dc:creator>
      <pubDate>Thu, 29 Jan 2026 21:42:18 +0000</pubDate>
      <link>https://forem.com/yuripeixinho/isp-interface-segregation-principle-principio-da-segregacao-de-interface-3om7</link>
      <guid>https://forem.com/yuripeixinho/isp-interface-segregation-principle-principio-da-segregacao-de-interface-3om7</guid>
      <description>&lt;h1&gt;
  
  
  Interface Segregation Principle
&lt;/h1&gt;

&lt;p&gt;O ISP afirma que uma interface não deve forçar a classe a implementar métodos que elas não utilizam.  A ideia é quebras grandes interfaces em menores e mais específicas, ou seja, em vez de interfaces gigantes e genéricas (”interfaces gordas”),  devemos ter “interfaces magras”, quebradas e mais específicas.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Clientes não devem ser forçados a depender de métodos que não usam.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pense nisso como um menu de restaurante:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Violação do ISP:&lt;/strong&gt; O restaurante obriga você a comprar o combo com hambúrguer, batata, refrigerante, sorvete e café, mesmo que você só queira o hambúrguer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aplicação do ISP:&lt;/strong&gt; O menu é segregado. Você pode pedir itens individuais ou combos menores que façam sentido para o seu "apetite" (necessidade)&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Exemplo didático do problema
&lt;/h1&gt;

&lt;p&gt;Imagine que temos a Interface chamada &lt;code&gt;ITrabalhador&lt;/code&gt;, ela possui métodos como &lt;code&gt;Codificar()&lt;/code&gt;, &lt;code&gt;Testar()&lt;/code&gt; e &lt;code&gt;GerenciarProjetos()&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Você vai criar uma classe chamada &lt;code&gt;Programador&lt;/code&gt; que implementa essa interface. Até esse cenário tudo ocorre como o esperado.&lt;/li&gt;
&lt;li&gt;O problema é que se você criar uma classe &lt;code&gt;Gerente&lt;/code&gt;, e implementar a mesma interface ela será obrigada a implementar &lt;code&gt;Codificar()&lt;/code&gt;, mesmo que o gerente não escreva código.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Essa prática cria um acoplamento desnecessário e “polui” o código com métodos vazios ou que lançam exceções como &lt;code&gt;throw new NotImplementedException&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Exemplo técnico do problema
&lt;/h1&gt;

&lt;p&gt;Vamos retomar o exemplo acima e desenvolver com o código com C# de duas formas, uma que viola o ISP e outra que não viola.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Violação estrutural
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Uma "Interface Gorda" que tenta fazer tudo&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ITrabalhador&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Codificar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Testar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;GerenciarProjeto&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;class&lt;/span&gt; &lt;span class="nc"&gt;Programador&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ITrabalhador&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;void&lt;/span&gt; &lt;span class="nf"&gt;Codificar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Escrevendo código C#..."&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;void&lt;/span&gt; &lt;span class="nf"&gt;Testar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Testando bugs..."&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;void&lt;/span&gt; &lt;span class="nf"&gt;GerenciarProjeto&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Atualizando o JIRA..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
    &lt;span class="c1"&gt;// Ok, talvez o programador faça um pouco de tudo.&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;class&lt;/span&gt; &lt;span class="nc"&gt;Gerente&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ITrabalhador&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;void&lt;/span&gt; &lt;span class="nf"&gt;Codificar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Oxente! O Gerente não deveria ser obrigado a ter este método.&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotImplementedException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Gerentes não codificam!"&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;void&lt;/span&gt; &lt;span class="nf"&gt;Testar&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="nf"&gt;NotImplementedException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Gerentes não testam!"&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;void&lt;/span&gt; &lt;span class="nf"&gt;GerenciarProjeto&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Gerenciando o time..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. O Jeito Correto
&lt;/h2&gt;

&lt;p&gt;Agora, vamos segregar (separar) as interfaces. Assim, cada classe só assina o "contrato" que realmente consegue cumprir.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Interfaces segregadas e específicas (Interfaces Magras)&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ICodificador&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Codificar&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;interface&lt;/span&gt; &lt;span class="nc"&gt;ITestador&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Testar&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;interface&lt;/span&gt; &lt;span class="nc"&gt;IGerente&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;GerenciarProjeto&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// O Programador implementa apenas o que faz sentido para ele&lt;/span&gt;
&lt;span class="c1"&gt;// Ele pode implementar múltiplas interfaces se necessário!&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Programador&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ICodificador&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ITestador&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;void&lt;/span&gt; &lt;span class="nf"&gt;Codificar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Escrevendo código C#..."&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;void&lt;/span&gt; &lt;span class="nf"&gt;Testar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Testando bugs..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// O Gerente agora está limpo e focado&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Gerente&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IGerente&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;void&lt;/span&gt; &lt;span class="nf"&gt;GerenciarProjeto&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Gerenciando o time..."&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;



</description>
      <category>architecture</category>
      <category>codequality</category>
      <category>programming</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>LSP - Liskov Substitution Principle (Princípio da Substituição de Liskov)</title>
      <dc:creator>Yuri Peixinho</dc:creator>
      <pubDate>Tue, 27 Jan 2026 01:41:36 +0000</pubDate>
      <link>https://forem.com/yuripeixinho/lsp-liskov-substitution-principle-principio-da-substituicao-de-liskov-37o6</link>
      <guid>https://forem.com/yuripeixinho/lsp-liskov-substitution-principle-principio-da-substituicao-de-liskov-37o6</guid>
      <description>&lt;p&gt;O terceiro princípio é o Liskov Substituition Principle. Ele foi definido por Barbara Liskov em 1987 e, embora que por definição academia pareça ser um “bicho de setes cabeças”, na prática é bem simples e ideal para criar sistemas robustos.&lt;/p&gt;

&lt;p&gt;O princípio diz que: Uma classe derivada deve poder ser substituída por sua classe base sem que o comportamento do programa seja alterado ou quebrado.&lt;/p&gt;

&lt;p&gt;Para cumprir  o príncpio pense assim: “O filho (classe que herda) deve conseguir fazer tudo que o pai (classe pai) prometeu que faria”. Se o pai diz "eu sei somar dois números", o filho não pode dizer "eu só sei somar se os números forem positivos". Isso seria uma surpresa desagradável para quem usa o código.&lt;/p&gt;

&lt;h2&gt;
  
  
  Analogia com Pássaros
&lt;/h2&gt;

&lt;p&gt;Imagine que você tem um sistema para um zoológico. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Você cria a Entidade &lt;code&gt;Passaro&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Você define que todo &lt;code&gt;Passaro&lt;/code&gt; tem a habilidade de voar.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Até aqui, tudo bem. Aí você cria os tipos específicos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pardal&lt;/strong&gt; (É um Pássaro): Voa? Sim. ✅ (Tudo certo, segue o princípio).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Águia&lt;/strong&gt; (É um Pássaro): Voa? Sim. ✅ (Tudo certo).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agora vem o problema. Você precisa adicionar um &lt;strong&gt;Pinguim&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pinguim&lt;/strong&gt; (É um Pássaro): Voa? &lt;strong&gt;Não.&lt;/strong&gt; ❌&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Onde o princípio quebra?
&lt;/h3&gt;

&lt;p&gt;Se você tem uma parte do seu código que diz: “Pegue todos os pássaros e faça-os voar”, quando chegar a vez do Pinguim o programa vai travar ou dar erro, porque pinguins não voam. Na aplicação promete que &lt;strong&gt;todo&lt;/strong&gt; pássaro voa, mas o pinguim não cumpre essa promessa.&lt;/p&gt;

&lt;h3&gt;
  
  
  Como consertar o exemplo do Pinguim?
&lt;/h3&gt;

&lt;p&gt;Em vez de colocar "Voar" na categoria principal &lt;strong&gt;&lt;code&gt;Passaro&lt;/code&gt;&lt;/strong&gt;, você deve criar uma categoria mais específica ou separar as habilidades:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Classe &lt;strong&gt;`Passaro&lt;/strong&gt;` (Tem bico, bota ovos).&lt;/li&gt;
&lt;li&gt;Classe &lt;strong&gt;&lt;code&gt;PassaroQueVoa&lt;/code&gt;&lt;/strong&gt; (Herda de Pássaro + sabe voar).&lt;/li&gt;
&lt;li&gt;Classe &lt;strong&gt;&lt;code&gt;PassaroQueNada&lt;/code&gt;&lt;/strong&gt; Herda de Pássaro + sabe nadar).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Dessa forma o Pardal entra em &lt;strong&gt;&lt;code&gt;PassaroQueVoa&lt;/code&gt;&lt;/strong&gt; e o Peguim em &lt;strong&gt;&lt;code&gt;PassaroQueNada&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;E o melhor: ninguém promete o que não pode cumprir, e o código não quebra.&lt;/p&gt;

&lt;h1&gt;
  
  
  Exemplo aplicado ao código
&lt;/h1&gt;

&lt;p&gt;Vamos retomar o exemplo acima e desenvolver com o código com C# de duas formas, uma que viola o LSP e outra que não viola.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Violação Estrutural
&lt;/h2&gt;

&lt;p&gt;Imagine que você tem uma classe abstrata &lt;code&gt;Passaro&lt;/code&gt;. Em C#, é comum usarmos classes abstratas ou interfaces para definir contratos.&lt;/p&gt;

&lt;p&gt;O exemplo abaixo viola o LSP porque o &lt;code&gt;Pinguim&lt;/code&gt; não pode substituir &lt;code&gt;Passaro&lt;/code&gt; sem causar efeitos colaterais (a exceção).&lt;/p&gt;

&lt;h3&gt;
  
  
  Classe Base
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Passaro&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;abstract&lt;/span&gt; &lt;span class="k"&gt;void&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Implementação Concreta
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pardal&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Passaro&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;override&lt;/span&gt; &lt;span class="k"&gt;void&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="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Pardal voando alto!"&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;
  
  
  Implementação que viola o LSP
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pinguim&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Passaro&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;override&lt;/span&gt; &lt;span class="k"&gt;void&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="c1"&gt;// O compilador obriga a implementar Voar(),&lt;/span&gt;
        &lt;span class="c1"&gt;// mas a lógica não permite. O dev lança uma exceção.&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotImplementedException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Pinguins não voam!"&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;h2&gt;
  
  
  2. O Jeito Correto
&lt;/h2&gt;

&lt;p&gt;Em C#, a melhor forma de resolver isso é segregando as capacidades através de &lt;strong&gt;Interfaces&lt;/strong&gt;. Nem todo pássaro é um &lt;code&gt;IVoador&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Essa implementação abaixo torna impossível passar um Pinguim para um método que espera &lt;code&gt;IVoador&lt;/code&gt;. O compilador do C# vai te impedir antes mesmo de você rodar o programa.&lt;/p&gt;

&lt;h3&gt;
  
  
  Definição de abstração (interface e classe abstrata)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Define apenas o que é comum a TODOS&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Ave&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;void&lt;/span&gt; &lt;span class="nf"&gt;Comer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Comendo..."&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;// Interface (Capacidade) separada&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IVoador&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Implementações
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Pardal é uma Ave E sabe voar&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pardal&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Ave&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IVoador&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;void&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="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Pardal voando!"&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;// Pinguim é apenas uma Ave (não implementa IVoador)&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pinguim&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Ave&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Pode ter métodos de nadar aqui&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>architecture</category>
      <category>beginners</category>
      <category>codequality</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>OCP — Open/Closed Principle (Princípio Aberto/Fechado)</title>
      <dc:creator>Yuri Peixinho</dc:creator>
      <pubDate>Mon, 26 Jan 2026 23:58:55 +0000</pubDate>
      <link>https://forem.com/yuripeixinho/ocp-openclosed-principle-principio-abertofechado-1n31</link>
      <guid>https://forem.com/yuripeixinho/ocp-openclosed-principle-principio-abertofechado-1n31</guid>
      <description>&lt;h1&gt;
  
  
  Princípio Aberto/Fechado
&lt;/h1&gt;

&lt;p&gt;Esse é o segunda pilar do SOLID. Sua fundamentação existe para que os softwares criados sejam fáceis de manter e evoluir sem quebrar o que já funciona.&lt;/p&gt;

&lt;p&gt;Certo! Mas o que diabos isso significa?  Os sistemas não são estáticos, eles tendem a evoluír. O cenário comum no mercado, portanto, é: com novas definições de funcionalidades os desenvolvedores geralmente alteram o código-fonte existente, código este, que já foi testado e homologado. Resultando em um sistema difícil de manter e “sustentar”.&lt;/p&gt;

&lt;p&gt;O OCP surge para mitigar esse problema e a definição foi criada por Bertrand Meyer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Entidades de software (classes, módulos, funções, etc.) devem estar abertas para extensão, mas fechadas para modificação."&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Aberto pra Extensão:&lt;/strong&gt; Você é deve ser capaz de adicionar novos comportamentos e funcionalidades ao sistema à medida que os requisitos mudam.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fechada para Modificações:&lt;/strong&gt; Ao adicionar essa nova funcionalidade, você não deve alterar o código-fonte existente que já foi estado e está funcionando&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Metáfora da Tomada
&lt;/h1&gt;

&lt;p&gt;Tenho um professor que comparou esse princípio com uma tomada. elétrica de parede.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ela é &lt;strong&gt;fechada pra modificação&lt;/strong&gt;, já que você não precisa quebrar a parede e refazer a fiação elétrica da casa toda vez que compra um novo eletrodoméstico&lt;/li&gt;
&lt;li&gt;Ela é &lt;strong&gt;abertura para extensão&lt;/strong&gt;, você pode instalar uma TV, ventilador ou carregador estendendo a utilidade daquela rede relétrica, apenas plugando algo novo. A interface (os buracos da tomada) permitee isso.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Exemplo prático
&lt;/h1&gt;

&lt;p&gt;Vamos desenvolver um cálculo de Bônus Anual. Imagine uma classe &lt;code&gt;CalculadoraDeBonus&lt;/code&gt;. Inicialmente, a empresa só tem "Desenvolvedores" e "Gerentes". &lt;/p&gt;

&lt;h2&gt;
  
  
  Exemplo Ruim (Violando OCP)
&lt;/h2&gt;

&lt;p&gt;Nesta abordagem comum (mas ruim), usamos um &lt;code&gt;switch&lt;/code&gt; ou &lt;code&gt;if/else&lt;/code&gt; para verificar o cargo. O problema: quero adicionar dois novos cargos, diretor e estagiário. Para isso eu preciso abrir a classe e modificá-la diretamente! Isso viola o OCP&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CalculadoraDeBonus&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="nf"&gt;Calcular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;cargo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;salario&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="n"&gt;cargo&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Gerente"&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="n"&gt;salario&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.2m&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="n"&gt;cargo&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Desenvolvedor"&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="n"&gt;salario&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.1m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Se a empresa criar o cargo "Diretor" amanhã, &lt;/span&gt;
        &lt;span class="c1"&gt;// VOU TER QUE ALTERAR ESTE ARQUIVO.&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;O Risco:&lt;/strong&gt; Ao editar esse arquivo para adicionar o "Diretor", você pode sem querer apagar uma linha ou mudar a lógica do "Gerente", causando bugs em algo que já estava testado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solução (Aplicando OCP)
&lt;/h2&gt;

&lt;p&gt;Vou trazer duas abordagens para fechar a classe para modificação e abri-las para extensão. Ambas abordagens resolvem o OCP, mas elas comunicam intenções diferentes sobre o seu sistema.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Abordagem com Classe Abstrata&lt;/li&gt;
&lt;li&gt;Abordagem com Interfaces&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. Abordagem com Classe Abstrata
&lt;/h2&gt;

&lt;p&gt;Use essa abrodagem quando existe uma relação forte de herança e você quer reaproveitar propriedades ou métodos&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cenário:&lt;/strong&gt; Todo funcionário tem &lt;code&gt;Nome&lt;/code&gt; e &lt;code&gt;Salario&lt;/code&gt; (código compartilhado), mas o cálculo do bônus muda.&lt;/p&gt;

&lt;h3&gt;
  
  
  Contrato
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FuncionarioBase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Código compartilhado (Reuso)&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Nome&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&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="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;Salario&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Obriga as classes filhas a implementarem a lógica específica&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="nf"&gt;CalcularBonus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Método comum que já funciona para todos (não precisa sobrescrever)&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;ObterCracha&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;$"Funcionário: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Nome&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&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;
  
  
  Aberto para extensões:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Gerente&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FuncionarioBase&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;override&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="nf"&gt;CalcularBonus&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="n"&gt;Salario&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.2m&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;class&lt;/span&gt; &lt;span class="nc"&gt;Desenvolvedor&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FuncionarioBase&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;override&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="nf"&gt;CalcularBonus&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="n"&gt;Salario&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.1m&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;
  
  
  Uso
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Processar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FuncionarioBase&lt;/span&gt; &lt;span class="n"&gt;funcionario&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;funcionario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CalcularBonus&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Abordagem com Interface
&lt;/h2&gt;

&lt;p&gt;Use esta abordagem quando o foco é o &lt;strong&gt;"O QUE FAZ"&lt;/strong&gt; (Comportamento). Interfaces são contratos puros. Elas não carregam "bagagem" (estado ou variáveis) e permitem maior flexibilidade, pois uma classe pode implementar múltiplas interfaces.&lt;br&gt;
&lt;strong&gt;Cenário:&lt;/strong&gt; Aqui não nos importamos se é um funcionário, um prestador de serviço ou um robô. Só nos importamos se ele tem uma regra de bônus. Isso é frequentemente chamado de &lt;strong&gt;Strategy Pattern&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Contrato
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// --- O Contrato (Interface) ---&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IRegraDeBonus&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="nf"&gt;Calcular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;salarioBase&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;class&lt;/span&gt; &lt;span class="nc"&gt;BonusParaDesenvolvedor&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IRegraDeBonus&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="nf"&gt;Calcular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;salarioBase&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="n"&gt;salarioBase&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.1m&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;
  
  
  Aberto para extensões:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// Note que não herdamos de ninguém, apenas assinamos o contrato&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BonusParaGerente&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IRegraDeBonus&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="nf"&gt;Calcular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;salarioBase&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="n"&gt;salarioBase&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.2m&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;
  
  
  Uso
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CalculadoraServico&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Recebemos a INTERFACE. Baixíssimo acoplamento.&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="nf"&gt;ExecutarCalculo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;salario&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IRegraDeBonus&lt;/span&gt; &lt;span class="n"&gt;regra&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="n"&gt;regra&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Calcular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;salario&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;h1&gt;
  
  
  Comparação entre abordagens: Abstract Class vs. Interface
&lt;/h1&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Característica&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Abstract Class&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Interface&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Relacionamento&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;"É um"&lt;/strong&gt; (Hierarquia estrita). Um Gerente &lt;em&gt;é um&lt;/em&gt; Funcionário.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;"Faz isso"&lt;/strong&gt; (Capacidade). Essa classe &lt;em&gt;sabe calcular&lt;/em&gt; bônus.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reuso de Código&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Alto.&lt;/strong&gt; Permite compartilhar propriedades (&lt;code&gt;Nome&lt;/code&gt;, &lt;code&gt;ID&lt;/code&gt;) e métodos concretos.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Baixo/Nenhum.&lt;/strong&gt; Apenas define as assinaturas dos métodos.*&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Herança&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Limitada.&lt;/strong&gt; C# só permite herdar de 1 classe. Se usar Abstract, você "gasta" essa cartada.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Múltipla.&lt;/strong&gt; Uma classe pode implementar 5 interfaces diferentes (&lt;code&gt;IBonificavel&lt;/code&gt;, &lt;code&gt;IAutenticavel&lt;/code&gt;, etc).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Acoplamento&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Médio. As filhas dependem da classe pai.&lt;/td&gt;
&lt;td&gt;Baixíssimo. As classes só dependem do contrato.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Quando usar no OCP?&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Quando você tem uma família de objetos intimamente relacionados que compartilham estrutura.&lt;/td&gt;
&lt;td&gt;Quando você quer plugar comportamentos diferentes (Strategy Pattern) ou testabilidade máxima (Mocks).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No desenvolvimento moderno de C# (.NET Core/Dependency Injection), &lt;strong&gt;Interfaces são usadas em 90% dos casos&lt;/strong&gt; para garantir o OCP, pois facilitam muito os testes unitários (Mocking).&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>codequality</category>
      <category>programming</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>SRP — Single Responsibility Principle (Princípio da Responsabilidade Única)</title>
      <dc:creator>Yuri Peixinho</dc:creator>
      <pubDate>Mon, 26 Jan 2026 23:36:18 +0000</pubDate>
      <link>https://forem.com/yuripeixinho/srp-single-responsibility-principle-principio-da-responsabilidade-unica-4e1a</link>
      <guid>https://forem.com/yuripeixinho/srp-single-responsibility-principle-principio-da-responsabilidade-unica-4e1a</guid>
      <description>&lt;h1&gt;
  
  
  Single Responsability Principle
&lt;/h1&gt;

&lt;p&gt;Esse é o primeiro pilar do SOLID. A definição clássica é “Uma classse deve ter um, e apenas um motivo pra mudar.”.&lt;/p&gt;

&lt;p&gt;Na prática, isso quer dizer que uma classe deve ser responsável por uma funcionalidade/parte específica do software. Em sistemas “blocos de cimentos”, é comum encontrarmos as chamadas “God Objects” (Objeto Deus), uma classe gigantesca que sabem e fazem tudo. O que contradiz o princípio da responsabilidade única.&lt;/p&gt;

&lt;h2&gt;
  
  
  Analogia
&lt;/h2&gt;

&lt;p&gt;Imagine um funcionário de um restaurante que é, ao mesmo tempo, o cozinheiro, o garçom e o faxineiro . Se ele precisar mudar a forma como limpa o chão, o serviço de cozinha e o atendimento podem ser afetados ou interrompidos. No SRP, dividimos essas tarefas entre especialistas para que um não atrapalhe a evolução do outro.&lt;/p&gt;

&lt;h1&gt;
  
  
  Exemplo
&lt;/h1&gt;

&lt;p&gt;Vamos imaginar um cenário em que o princípio não foi aplicado e após isso vamos transformá-lo em um código modular. Imagine um sistema que gerencia pedidos de e-commerce.&lt;/p&gt;

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

&lt;p&gt;Na classe &lt;code&gt;Pedido&lt;/code&gt; abaixo, temos três motivos diferentes para serem alterados. Se a regra de calculo, banco e e-mail mudar. Cada método representa uma responsabilidade diferente para a classe &lt;code&gt;Pedido&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pedido&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calcular_total&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="n"&gt;gica&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;neg&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="nf"&gt;cio&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pre&lt;/span&gt;&lt;span class="err"&gt;ç&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;impostos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;descontos&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;pass&lt;/span&gt;

    &lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;salvar_no_banco&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="n"&gt;gica&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="nf"&gt;infraestrutura&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Conex&lt;/span&gt;&lt;span class="err"&gt;ã&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="n"&gt;SQL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tabelas&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;pass&lt;/span&gt;

    &lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;enviar_email_confirmacao&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="n"&gt;gica&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;comunica&lt;/span&gt;&lt;span class="err"&gt;çã&lt;/span&gt;&lt;span class="nf"&gt;o&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Servidor&lt;/span&gt; &lt;span class="n"&gt;SMTP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;mail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Para aplicar o SRP, separamos as tarefas em “especialistas”. Cada classe agora tem apenas uma razão para existir e mudar. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Pedido&lt;/code&gt; vai conter apenas a lógica de cálculo &lt;code&gt;calcular_total&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;salvar_no_banco&lt;/code&gt; vai ser uma nova classe chamada &lt;code&gt;PedidoRepository&lt;/code&gt;, que vai implementar o &lt;a href="https://www.notion.so/Repository-1b2671b57a3e8165ae03fa63305dccce?pvs=21" rel="noopener noreferrer"&gt;Padrão Repository&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;enviar_email_confirmacao&lt;/code&gt; vai ser um serviço separado apenas por enviar comunicações&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Desse modo, se você decidir trocar o e-mail por uma mensagem no WhatsApp, você altera apenas o serviço respectivo. A regra de cálculo do &lt;code&gt;Pedido&lt;/code&gt; então permanece segura e intocada, como uma peça LEGO independente&lt;/p&gt;

&lt;h2&gt;
  
  
  Exemplo aplicado a contexto: Clean Architecture, Mediator, CQRS e DDD
&lt;/h2&gt;

&lt;p&gt;Veja como o SRP se manifesta em um &lt;strong&gt;CommandHandler&lt;/strong&gt; usando Mediator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Este Handler tem UMA única razão para mudar: &lt;/span&gt;
&lt;span class="c1"&gt;// Se o fluxo de "Criação de Pedido" for alterado.&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CriarPedidoHandler&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IRequestHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CriarPedidoCommand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IPedidoRepository&lt;/span&gt; &lt;span class="n"&gt;_repository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Interface (DIP)&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IMediator&lt;/span&gt; &lt;span class="n"&gt;_mediator&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;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CriarPedidoCommand&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// 1. Regra de Negócio (DDD: Entidade decide se pode ser criada)&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;pedido&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Pedido&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClienteId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Itens&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// 2. Persistência (Clean Arch: O Handler não sabe se é SQL ou NoSQL)&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SalvarAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// 3. Comunicação (Mediator: Dispara um evento para quem interessar)&lt;/span&gt;
        &lt;span class="c1"&gt;// Isso separa a criação do pedido do envio de e-mail (SRP puro!)&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_mediator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;PedidoCriadoEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&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://dev.to/yuripeixinho/principios-solid-3ahm"&gt;Veja o conteúdo completo aqui!&lt;/a&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>beginners</category>
      <category>programming</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Princípios SOLID</title>
      <dc:creator>Yuri Peixinho</dc:creator>
      <pubDate>Fri, 23 Jan 2026 01:57:50 +0000</pubDate>
      <link>https://forem.com/yuripeixinho/principios-solid-3ahm</link>
      <guid>https://forem.com/yuripeixinho/principios-solid-3ahm</guid>
      <description>&lt;h1&gt;
  
  
  Contexto do SOLID
&lt;/h1&gt;

&lt;p&gt;Antigamente os sistemas eram desenvolvidos com um único objetivo: fazer o software funcionar. Os padrões utilizados eram monolíticos e rígidos, com forte acoplamento e com tudo interligado. Atualmente sistemas conhecidos como “Código espaguete” ou “Grande Bola de Lama”. Como tudo estava interligado, corrigir um erro em uma ponta do sistema geralmente causava erros em outras partes do sistema.&lt;/p&gt;

&lt;h2&gt;
  
  
  Crise do Software
&lt;/h2&gt;

&lt;p&gt;Na década de 70 e 80 o desenvolvimento de software enfrentava uma crise. O hardware estava ficando incrivelmente potente e barato, mas o software estava se tornando tão complexo que as equipes não conseguiam mantê-los de forma eficiente.&lt;/p&gt;

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

&lt;p&gt;O SOLID veio pra transformar o desenvolvimento de software em uma tarefa artesanal em uma engenharia, focada em criar peças que se encaixam sem estarem “soldadas” umas nas outras. Ele é um conjunto de cinco princípios de design de software para a programação orientada a objetos (POO).&lt;/p&gt;

&lt;p&gt;Em resumo, podemos dizer que os princípios funcionam como uma base/guia para os desenvolvedores arquitetarem soluções fáceis de manter, testar e evoluír ao longo do tempo.&lt;/p&gt;

&lt;p&gt;Ao invés de desenvolvermos sistemas como “um grande bloco de cimento”, o SOLID nos ensina a construir softwares como peças “LEGO”, que se encaixam de forma inteligente.&lt;/p&gt;

&lt;h1&gt;
  
  
  1. Princípio da Responsabilidade Única
&lt;/h1&gt;

&lt;p&gt;Esse é o primeiro pilar do SOLID. A definição clássica é “Uma classse deve ter um, e apenas um motivo pra mudar.”.&lt;/p&gt;

&lt;p&gt;Na prática, isso quer dizer que uma classe deve ser responsável por uma funcionalidade/parte específica do software. Em sistemas “blocos de cimentos”, é comum encontrarmos as chamadas “God Objects” (Objeto Deus), uma classe gigantesca que sabem e fazem tudo. O que contradiz o princípio da responsabilidade única.&lt;/p&gt;

&lt;h2&gt;
  
  
  Analogia
&lt;/h2&gt;

&lt;p&gt;Imagine um funcionário de um restaurante que é, ao mesmo tempo, o cozinheiro, o garçom e o faxineiro . Se ele precisar mudar a forma como limpa o chão, o serviço de cozinha e o atendimento podem ser afetados ou interrompidos. No SRP, dividimos essas tarefas entre especialistas para que um não atrapalhe a evolução do outro.&lt;/p&gt;

&lt;h1&gt;
  
  
  Exemplo
&lt;/h1&gt;

&lt;p&gt;Vamos imaginar um cenário em que o princípio não foi aplicado e após isso vamos transformá-lo em um código modular. Imagine um sistema que gerencia pedidos de e-commerce.&lt;/p&gt;

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

&lt;p&gt;Na classe &lt;code&gt;Pedido&lt;/code&gt; abaixo, temos três motivos diferentes para serem alterados. Se a regra de calculo, banco e e-mail mudar. Cada método representa uma responsabilidade diferente para a classe &lt;code&gt;Pedido&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pedido&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calcular_total&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="n"&gt;gica&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;neg&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="nf"&gt;cio&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Pre&lt;/span&gt;&lt;span class="err"&gt;ç&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;impostos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;descontos&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;pass&lt;/span&gt;

    &lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;salvar_no_banco&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="n"&gt;gica&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="nf"&gt;infraestrutura&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Conex&lt;/span&gt;&lt;span class="err"&gt;ã&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="n"&gt;SQL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tabelas&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;pass&lt;/span&gt;

    &lt;span class="n"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;enviar_email_confirmacao&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;L&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="n"&gt;gica&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;comunica&lt;/span&gt;&lt;span class="err"&gt;çã&lt;/span&gt;&lt;span class="nf"&gt;o&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Servidor&lt;/span&gt; &lt;span class="n"&gt;SMTP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;template&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;mail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Para aplicar o SRP, separamos as tarefas em “especialistas”. Cada classe agora tem apenas uma razão para existir e mudar. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Pedido&lt;/code&gt; vai conter apenas a lógica de cálculo &lt;code&gt;calcular_total&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;salvar_no_banco&lt;/code&gt; vai ser uma nova classe chamada &lt;code&gt;PedidoRepository&lt;/code&gt;, que vai implementar o &lt;a href="https://www.notion.so/Repository-1b2671b57a3e8165ae03fa63305dccce?pvs=21" rel="noopener noreferrer"&gt;Padrão Repository&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;enviar_email_confirmacao&lt;/code&gt; vai ser um serviço separado apenas por enviar comunicações&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Desse modo, se você decidir trocar o e-mail por uma mensagem no WhatsApp, você altera apenas o serviço respectivo. A regra de cálculo do &lt;code&gt;Pedido&lt;/code&gt; então permanece segura e intocada, como uma peça LEGO independente&lt;/p&gt;

&lt;h2&gt;
  
  
  Exemplo aplicado a contexto: Clean Architecture, Mediator, CQRS e DDD
&lt;/h2&gt;

&lt;p&gt;Veja como o SRP se manifesta em um &lt;strong&gt;CommandHandler&lt;/strong&gt; usando Mediator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Este Handler tem UMA única razão para mudar: &lt;/span&gt;
&lt;span class="c1"&gt;// Se o fluxo de "Criação de Pedido" for alterado.&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CriarPedidoHandler&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IRequestHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CriarPedidoCommand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IPedidoRepository&lt;/span&gt; &lt;span class="n"&gt;_repository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Interface (DIP)&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IMediator&lt;/span&gt; &lt;span class="n"&gt;_mediator&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;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CriarPedidoCommand&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// 1. Regra de Negócio (DDD: Entidade decide se pode ser criada)&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;pedido&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Pedido&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClienteId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Itens&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// 2. Persistência (Clean Arch: O Handler não sabe se é SQL ou NoSQL)&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SalvarAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// 3. Comunicação (Mediator: Dispara um evento para quem interessar)&lt;/span&gt;
        &lt;span class="c1"&gt;// Isso separa a criação do pedido do envio de e-mail (SRP puro!)&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_mediator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;PedidoCriadoEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;pedido&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&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;h1&gt;
  
  
  2. Princípio Aberto/Fechado
&lt;/h1&gt;

&lt;p&gt;Esse é o segunda pilar do SOLID. Sua fundamentação existe para que os softwares criados sejam fáceis de manter e evoluir sem quebrar o que já funciona.&lt;/p&gt;

&lt;p&gt;Certo! Mas o que diabos isso significa?  Os sistemas não são estáticos, eles tendem a evoluír. O cenário comum no mercado, portanto, é: com novas definições de funcionalidades os desenvolvedores geralmente alteram o código-fonte existente, código este, que já foi testado e homologado. Resultando em um sistema difícil de manter e “sustentar”.&lt;/p&gt;

&lt;p&gt;O OCP surge para mitigar esse problema e a definição foi criada por Bertrand Meyer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Entidades de software (classes, módulos, funções, etc.) devem estar abertas para extensão, mas fechadas para modificação."&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Aberto pra Extensão:&lt;/strong&gt; Você é deve ser capaz de adicionar novos comportamentos e funcionalidades ao sistema à medida que os requisitos mudam.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fechada para Modificações:&lt;/strong&gt; Ao adicionar essa nova funcionalidade, você não deve alterar o código-fonte existente que já foi estado e está funcionando&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Metáfora da Tomada
&lt;/h1&gt;

&lt;p&gt;Tenho um professor que comparou esse princípio com uma tomada. elétrica de parede.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ela é &lt;strong&gt;fechada pra modificação&lt;/strong&gt;, já que você não precisa quebrar a parede e refazer a fiação elétrica da casa toda vez que compra um novo eletrodoméstico&lt;/li&gt;
&lt;li&gt;Ela é &lt;strong&gt;abertura para extensão&lt;/strong&gt;, você pode instalar uma TV, ventilador ou carregador estendendo a utilidade daquela rede relétrica, apenas plugando algo novo. A interface (os buracos da tomada) permitee isso.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Exemplo prático
&lt;/h1&gt;

&lt;p&gt;Vamos desenvolver um cálculo de Bônus Anual. Imagine uma classe &lt;code&gt;CalculadoraDeBonus&lt;/code&gt;. Inicialmente, a empresa só tem "Desenvolvedores" e "Gerentes". &lt;/p&gt;

&lt;h2&gt;
  
  
  Exemplo Ruim (Violando OCP)
&lt;/h2&gt;

&lt;p&gt;Nesta abordagem comum (mas ruim), usamos um &lt;code&gt;switch&lt;/code&gt; ou &lt;code&gt;if/else&lt;/code&gt; para verificar o cargo. O problema: quero adicionar dois novos cargos, diretor e estagiário. Para isso eu preciso abrir a classe e modificá-la diretamente! Isso viola o OCP&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CalculadoraDeBonus&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="nf"&gt;Calcular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;cargo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;salario&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="n"&gt;cargo&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Gerente"&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="n"&gt;salario&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.2m&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="n"&gt;cargo&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"Desenvolvedor"&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="n"&gt;salario&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.1m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Se a empresa criar o cargo "Diretor" amanhã, &lt;/span&gt;
        &lt;span class="c1"&gt;// VOU TER QUE ALTERAR ESTE ARQUIVO.&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;O Risco:&lt;/strong&gt; Ao editar esse arquivo para adicionar o "Diretor", você pode sem querer apagar uma linha ou mudar a lógica do "Gerente", causando bugs em algo que já estava testado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solução (Aplicando OCP)
&lt;/h2&gt;

&lt;p&gt;Vou trazer duas abordagens para fechar a classe para modificação e abri-las para extensão. Ambas abordagens resolvem o OCP, mas elas comunicam intenções diferentes sobre o seu sistema.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Abordagem com Classe Abstrata&lt;/li&gt;
&lt;li&gt;Abordagem com Interfaces&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Abordagem com Classe Abstrata
&lt;/h2&gt;

&lt;p&gt;Use essa abrodagem quando existe uma relação forte de herança e você quer reaproveitar propriedades ou métodos&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cenário:&lt;/strong&gt; Todo funcionário tem &lt;code&gt;Nome&lt;/code&gt; e &lt;code&gt;Salario&lt;/code&gt; (código compartilhado), mas o cálculo do bônus muda.&lt;/p&gt;

&lt;h3&gt;
  
  
  Contrato
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FuncionarioBase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Código compartilhado (Reuso)&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Nome&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&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="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;Salario&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Obriga as classes filhas a implementarem a lógica específica&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="nf"&gt;CalcularBonus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Método comum que já funciona para todos (não precisa sobrescrever)&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;ObterCracha&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;$"Funcionário: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Nome&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&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;
  
  
  Aberto para extensões:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Gerente&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FuncionarioBase&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;override&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="nf"&gt;CalcularBonus&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="n"&gt;Salario&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.2m&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;class&lt;/span&gt; &lt;span class="nc"&gt;Desenvolvedor&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FuncionarioBase&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;override&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="nf"&gt;CalcularBonus&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="n"&gt;Salario&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.1m&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;
  
  
  Uso
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Processar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FuncionarioBase&lt;/span&gt; &lt;span class="n"&gt;funcionario&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;funcionario&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CalcularBonus&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Abordagem com Interface
&lt;/h2&gt;

&lt;p&gt;Use esta abordagem quando o foco é o &lt;strong&gt;"O QUE FAZ"&lt;/strong&gt; (Comportamento). Interfaces são contratos puros. Elas não carregam "bagagem" (estado ou variáveis) e permitem maior flexibilidade, pois uma classe pode implementar múltiplas interfaces.&lt;br&gt;
&lt;strong&gt;Cenário:&lt;/strong&gt; Aqui não nos importamos se é um funcionário, um prestador de serviço ou um robô. Só nos importamos se ele tem uma regra de bônus. Isso é frequentemente chamado de &lt;strong&gt;Strategy Pattern&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Contrato
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// --- O Contrato (Interface) ---&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IRegraDeBonus&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="nf"&gt;Calcular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;salarioBase&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;class&lt;/span&gt; &lt;span class="nc"&gt;BonusParaDesenvolvedor&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IRegraDeBonus&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="nf"&gt;Calcular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;salarioBase&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="n"&gt;salarioBase&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.1m&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;
  
  
  Aberto para extensões:
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// Note que não herdamos de ninguém, apenas assinamos o contrato&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BonusParaGerente&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IRegraDeBonus&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="nf"&gt;Calcular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;salarioBase&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="n"&gt;salarioBase&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.2m&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;
  
  
  Uso
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CalculadoraServico&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Recebemos a INTERFACE. Baixíssimo acoplamento.&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="nf"&gt;ExecutarCalculo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;salario&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IRegraDeBonus&lt;/span&gt; &lt;span class="n"&gt;regra&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="n"&gt;regra&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Calcular&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;salario&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;h2&gt;
  
  
  Comparação entre abordagens: Abstract Class vs. Interface
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Característica&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Abstract Class&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Interface&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Relacionamento&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;"É um"&lt;/strong&gt; (Hierarquia estrita). Um Gerente &lt;em&gt;é um&lt;/em&gt; Funcionário.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;"Faz isso"&lt;/strong&gt; (Capacidade). Essa classe &lt;em&gt;sabe calcular&lt;/em&gt; bônus.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reuso de Código&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Alto.&lt;/strong&gt; Permite compartilhar propriedades (&lt;code&gt;Nome&lt;/code&gt;, &lt;code&gt;ID&lt;/code&gt;) e métodos concretos.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Baixo/Nenhum.&lt;/strong&gt; Apenas define as assinaturas dos métodos.*&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Herança&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Limitada.&lt;/strong&gt; C# só permite herdar de 1 classe. Se usar Abstract, você "gasta" essa cartada.&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Múltipla.&lt;/strong&gt; Uma classe pode implementar 5 interfaces diferentes (&lt;code&gt;IBonificavel&lt;/code&gt;, &lt;code&gt;IAutenticavel&lt;/code&gt;, etc).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Acoplamento&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Médio. As filhas dependem da classe pai.&lt;/td&gt;
&lt;td&gt;Baixíssimo. As classes só dependem do contrato.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Quando usar no OCP?&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Quando você tem uma família de objetos intimamente relacionados que compartilham estrutura.&lt;/td&gt;
&lt;td&gt;Quando você quer plugar comportamentos diferentes (Strategy Pattern) ou testabilidade máxima (Mocks).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No desenvolvimento moderno de C# (.NET Core/Dependency Injection), &lt;strong&gt;Interfaces são usadas em 90% dos casos&lt;/strong&gt; para garantir o OCP, pois facilitam muito os testes unitários (Mocking).&lt;/p&gt;
&lt;h1&gt;
  
  
  3. Princípio da Substituição de Liskov
&lt;/h1&gt;

&lt;p&gt;O terceiro princípio é o Liskov Substituition Principle. Ele foi definido por Barbara Liskov em 1987 e, embora que por definição academia pareça ser um “bicho de setes cabeças”, na prática é bem simples e ideal para criar sistemas robustos.&lt;/p&gt;

&lt;p&gt;O princípio estabelece que uma classe derivada deve poder substituir sua classe base sem alterar ou comprometer o comportamento esperado do programa. Em outras palavras, ao herdar a classe &lt;strong&gt;B&lt;/strong&gt; a partir da classe &lt;strong&gt;A&lt;/strong&gt;, o desenvolvedor deve conseguir realizar tudo o que era possível com &lt;strong&gt;A&lt;/strong&gt; utilizando &lt;strong&gt;B&lt;/strong&gt;, mantendo as mesmas garantias de funcionamento e, se necessário, acrescentando novos comportamentos, mas nunca removendo ou quebrando os existentes.&lt;/p&gt;

&lt;p&gt;Para cumprir  o príncpio pense assim: “O filho (classe que herda) deve conseguir fazer tudo que o pai (classe pai) prometeu que faria”. Se o pai diz "eu sei somar dois números", o filho não pode dizer "eu só sei somar se os números forem positivos". Isso seria uma surpresa desagradável para quem usa o código.&lt;/p&gt;
&lt;h2&gt;
  
  
  Analogia com Pássaros
&lt;/h2&gt;

&lt;p&gt;Imagine que você tem um sistema para um zoológico. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Você cria a Entidade &lt;code&gt;Passaro&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Você define que todo &lt;code&gt;Passaro&lt;/code&gt; tem a habilidade de voar.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Até aqui, tudo bem. Aí você cria os tipos específicos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pardal&lt;/strong&gt; (É um Pássaro): Voa? Sim. ✅ (Tudo certo, segue o princípio).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Águia&lt;/strong&gt; (É um Pássaro): Voa? Sim. ✅ (Tudo certo).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agora vem o problema. Você precisa adicionar um &lt;strong&gt;Pinguim&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pinguim&lt;/strong&gt; (É um Pássaro): Voa? &lt;strong&gt;Não.&lt;/strong&gt; ❌&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Onde o princípio quebra?
&lt;/h3&gt;

&lt;p&gt;Se você tem uma parte do seu código que diz: “Pegue todos os pássaros e faça-os voar”, quando chegar a vez do Pinguim o programa vai travar ou dar erro, porque pinguins não voam. Na aplicação promete que &lt;strong&gt;todo&lt;/strong&gt; pássaro voa, mas o pinguim não cumpre essa promessa.&lt;/p&gt;
&lt;h3&gt;
  
  
  Como consertar o exemplo do Pinguim?
&lt;/h3&gt;

&lt;p&gt;Em vez de colocar "Voar" na categoria principal &lt;strong&gt;&lt;code&gt;Passaro&lt;/code&gt;&lt;/strong&gt;, você deve criar uma categoria mais específica ou separar as habilidades:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Classe &lt;strong&gt;`Passaro&lt;/strong&gt;` (Tem bico, bota ovos).&lt;/li&gt;
&lt;li&gt;Classe &lt;strong&gt;&lt;code&gt;PassaroQueVoa&lt;/code&gt;&lt;/strong&gt; (Herda de Pássaro + sabe voar).&lt;/li&gt;
&lt;li&gt;Classe &lt;strong&gt;&lt;code&gt;PassaroQueNada&lt;/code&gt;&lt;/strong&gt; Herda de Pássaro + sabe nadar).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Dessa forma o Pardal entra em &lt;strong&gt;&lt;code&gt;PassaroQueVoa&lt;/code&gt;&lt;/strong&gt; e o Peguim em &lt;strong&gt;&lt;code&gt;PassaroQueNada&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;E o melhor: ninguém promete o que não pode cumprir, e o código não quebra.&lt;/p&gt;
&lt;h1&gt;
  
  
  Exemplo aplicado ao código
&lt;/h1&gt;

&lt;p&gt;Vamos retomar o exemplo acima e desenvolver com o código com C# de duas formas, uma que viola o LSP e outra que não viola.&lt;/p&gt;
&lt;h2&gt;
  
  
  Violação Estrutural
&lt;/h2&gt;

&lt;p&gt;Imagine que você tem uma classe abstrata &lt;code&gt;Passaro&lt;/code&gt;. Em C#, é comum usarmos classes abstratas ou interfaces para definir contratos.&lt;/p&gt;

&lt;p&gt;O exemplo abaixo viola o LSP porque o &lt;code&gt;Pinguim&lt;/code&gt; não pode substituir &lt;code&gt;Passaro&lt;/code&gt; sem causar efeitos colaterais (a exceção).&lt;/p&gt;
&lt;h3&gt;
  
  
  Classe Base
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Passaro&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;abstract&lt;/span&gt; &lt;span class="k"&gt;void&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Implementação Concreta
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pardal&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Passaro&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;override&lt;/span&gt; &lt;span class="k"&gt;void&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="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Pardal voando alto!"&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;
  
  
  Implementação que viola o LSP
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pinguim&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Passaro&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;override&lt;/span&gt; &lt;span class="k"&gt;void&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="c1"&gt;// O compilador obriga a implementar Voar(),&lt;/span&gt;
        &lt;span class="c1"&gt;// mas a lógica não permite. O dev lança uma exceção.&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotImplementedException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Pinguins não voam!"&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;h2&gt;
  
  
  O Jeito Correto
&lt;/h2&gt;

&lt;p&gt;Em C#, a melhor forma de resolver isso é segregando as capacidades através de &lt;strong&gt;Interfaces&lt;/strong&gt;. Nem todo pássaro é um &lt;code&gt;IVoador&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Essa implementação abaixo torna impossível passar um Pinguim para um método que espera &lt;code&gt;IVoador&lt;/code&gt;. O compilador do C# vai te impedir antes mesmo de você rodar o programa.&lt;/p&gt;
&lt;h3&gt;
  
  
  Definição de abstração (interface e classe abstrata)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Define apenas o que é comum a TODOS&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Ave&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;void&lt;/span&gt; &lt;span class="nf"&gt;Comer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Comendo..."&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;// Interface (Capacidade) separada&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IVoador&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Implementações
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Pardal é uma Ave E sabe voar&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pardal&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Ave&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IVoador&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;void&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="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Pardal voando!"&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;// Pinguim é apenas uma Ave (não implementa IVoador)&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Pinguim&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Ave&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Pode ter métodos de nadar aqui&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  4. Principio da Segragação de Interface
&lt;/h1&gt;

&lt;p&gt;O ISP afirma que uma interface não deve forçar a classe a implementar métodos que elas não utilizam.  A ideia é quebras grandes interfaces em menores e mais específicas, ou seja, em vez de interfaces gigantes e genéricas (”interfaces gordas”),  devemos ter “interfaces magras”, quebradas e mais específicas.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Clientes não devem ser forçados a depender de métodos que não usam.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pense nisso como um menu de restaurante:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Violação do ISP:&lt;/strong&gt; O restaurante obriga você a comprar o combo com hambúrguer, batata, refrigerante, sorvete e café, mesmo que você só queira o hambúrguer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Aplicação do ISP:&lt;/strong&gt; O menu é segregado. Você pode pedir itens individuais ou combos menores que façam sentido para o seu "apetite" (necessidade)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;
  
  
  Exemplo didático do problema
&lt;/h1&gt;

&lt;p&gt;Imagine que temos a Interface chamada &lt;code&gt;ITrabalhador&lt;/code&gt;, ela possui métodos como &lt;code&gt;Codificar()&lt;/code&gt;, &lt;code&gt;Testar()&lt;/code&gt; e &lt;code&gt;GerenciarProjetos()&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Você vai criar uma classe chamada &lt;code&gt;Programador&lt;/code&gt; que implementa essa interface. Até esse cenário tudo ocorre como o esperado.&lt;/li&gt;
&lt;li&gt;O problema é que se você criar uma classe &lt;code&gt;Gerente&lt;/code&gt;, e implementar a mesma interface ela será obrigada a implementar &lt;code&gt;Codificar()&lt;/code&gt;, mesmo que o gerente não escreva código.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Essa prática cria um acoplamento desnecessário e “polui” o código com métodos vazios ou que lançam exceções como &lt;code&gt;throw new NotImplementedException&lt;/code&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  Exemplo técnico do problema
&lt;/h1&gt;

&lt;p&gt;Vamos retomar o exemplo acima e desenvolver com o código com C# de duas formas, uma que viola o ISP e outra que não viola.&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Violação estrutural
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Uma "Interface Gorda" que tenta fazer tudo&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ITrabalhador&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Codificar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Testar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;GerenciarProjeto&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;class&lt;/span&gt; &lt;span class="nc"&gt;Programador&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ITrabalhador&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;void&lt;/span&gt; &lt;span class="nf"&gt;Codificar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Escrevendo código C#..."&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;void&lt;/span&gt; &lt;span class="nf"&gt;Testar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Testando bugs..."&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;void&lt;/span&gt; &lt;span class="nf"&gt;GerenciarProjeto&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Atualizando o JIRA..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
    &lt;span class="c1"&gt;// Ok, talvez o programador faça um pouco de tudo.&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;class&lt;/span&gt; &lt;span class="nc"&gt;Gerente&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ITrabalhador&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;void&lt;/span&gt; &lt;span class="nf"&gt;Codificar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Oxente! O Gerente não deveria ser obrigado a ter este método.&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotImplementedException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Gerentes não codificam!"&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;void&lt;/span&gt; &lt;span class="nf"&gt;Testar&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="nf"&gt;NotImplementedException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Gerentes não testam!"&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;void&lt;/span&gt; &lt;span class="nf"&gt;GerenciarProjeto&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Gerenciando o time..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  2. O Jeito Correto
&lt;/h2&gt;

&lt;p&gt;Agora, vamos segregar (separar) as interfaces. Assim, cada classe só assina o "contrato" que realmente consegue cumprir.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Interfaces segregadas e específicas (Interfaces Magras)&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ICodificador&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Codificar&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;interface&lt;/span&gt; &lt;span class="nc"&gt;ITestador&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Testar&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;interface&lt;/span&gt; &lt;span class="nc"&gt;IGerente&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;GerenciarProjeto&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// O Programador implementa apenas o que faz sentido para ele&lt;/span&gt;
&lt;span class="c1"&gt;// Ele pode implementar múltiplas interfaces se necessário!&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Programador&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ICodificador&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ITestador&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;void&lt;/span&gt; &lt;span class="nf"&gt;Codificar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Escrevendo código C#..."&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;void&lt;/span&gt; &lt;span class="nf"&gt;Testar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Testando bugs..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// O Gerente agora está limpo e focado&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Gerente&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IGerente&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;void&lt;/span&gt; &lt;span class="nf"&gt;GerenciarProjeto&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Gerenciando o time..."&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;h1&gt;
  
  
  5. Princípio da Inversão de Dependência
&lt;/h1&gt;

&lt;p&gt;A definição formal do quinto princípio parece um pouco técnica:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Módulos de alto nível não devem depender de módulos de baixo nível. Ambos devem depender de abstraçãoes”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;O conceito de Dependency Inversion (DI) pode deixar desenvolvedores imaturos confuso, isso porque esse conceito geralmente surge de uma necessidade prática e real e as explicações geralmente possuem níveis de abstrações que exiga a compreensão por completo do fluxo de um sistema. Antes de entendermos sobre o assunto temos que entender o que são os módulos de baixo e alto nível de um sistema&lt;/p&gt;

&lt;h1&gt;
  
  
  Módulos de alto e baixo nível
&lt;/h1&gt;

&lt;p&gt;Entender como o sistema de comporta em níveis de módulos e a relação entre eles é de extrema importância para a compreensão do conceito de DI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alto nível
&lt;/h2&gt;

&lt;p&gt;O foco aqui é a regra de negócio, lógica central, é aqui que existe o “valor” do que é o sistema. Deve ser algo estável e mudar pouco. Por exemplo: calcular o frete de um pedido, gerar uma fatura ou processar um pagamento.&lt;/p&gt;

&lt;h2&gt;
  
  
  Baixo nível
&lt;/h2&gt;

&lt;p&gt;O foco é os detalhes de implementação, mecanismos concretos. São os braços e as pernas que executam o que é demandado pelo módulo de alto nível, mas não definem as regras. Isto posto, está mais sujeito a mudanças e alguns exemplos são: bancos de dados específicos, frameworks de interfaces, etc…&lt;/p&gt;

&lt;h2&gt;
  
  
  Relação entre alto e baixo nível
&lt;/h2&gt;

&lt;p&gt;De forma resumida, podemos dizer que:&lt;/p&gt;

&lt;p&gt;Alto nível = o que o sistema faz (regras de negócio).&lt;/p&gt;

&lt;p&gt;Baixo nível = como o sistema faz (detalhes técnicos).&lt;/p&gt;

&lt;p&gt;Abstração = a ponte que une os dois, mantendo o alto nível protegido dos detalhes.&lt;/p&gt;

&lt;p&gt;Didaticamente explicando o conceito:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O &lt;strong&gt;alto nível&lt;/strong&gt; diz: “Preciso calculas fretes”&lt;/li&gt;
&lt;li&gt;O &lt;strong&gt;baixo nível&lt;/strong&gt; responde: “Ok, sei falar com os Correios e calcular o valor”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se o alto nível depender diretamente dos detalhes (Correios), ele fica preso apenas a um serviço, então se amanhã mudar para FedEx, a alteração deverá ser feita na alta escala do sistema (alto nível), o que é uma péssima prática.&lt;/p&gt;

&lt;p&gt;Para resolver a problemática acima, podemos utilizar a seguinte abordagem:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;O alto nível só conhece a regra “alguém que calcule frete”&lt;/li&gt;
&lt;li&gt;O desenvolvedor cria a abstração &lt;code&gt;ICalculadoraFrete&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;O baixo nível (Correios ou FedEx) implementa essa abstração&lt;/li&gt;
&lt;li&gt;O alto nível não precisa mudar quando trocarmos serviço postal&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Inversão de dependência
&lt;/h1&gt;

&lt;p&gt;A ideia central da inversão de dependência é “desamarrar” as regras de negócios a um detalhe específico de implementação. Já que essa prática deixa o sistema rígido e difícil de mudar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Analogia do dia a dia
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sem&lt;/strong&gt; &lt;strong&gt;DI:&lt;/strong&gt; Um carro que só funciona se você abastecer com a gasolina da “Bandeira X”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Com DI:&lt;/strong&gt; O carro depende apenas da abstação (interface) “combustível líquido inflamável”

&lt;ul&gt;
&lt;li&gt;Pode ser gasolina comum, aditivada, etanol ou até biocombustível&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Com base na analogia acima, a gente é capaz de perceber que com a Inversão de dependência o carro não se prende aos detalhe da gasolina (baixo nível), ele só depende da abstração de um combustível &lt;/p&gt;

&lt;h1&gt;
  
  
  Aplicando o princípio da Inversão de Dependência
&lt;/h1&gt;

&lt;p&gt;Para utilizar a inversão de dependência vamos aplicar a Inversão de Controle (IoC) e Injeção de Dependência (DI) &lt;/p&gt;

&lt;h3&gt;
  
  
  1. Criamos uma interface (um contrato)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;INotificacaoService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Enviar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;mensagem&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;Aqui estamos dizendo: "Eu não me importo &lt;em&gt;como&lt;/em&gt; a mensagem será enviada. Só quero que exista alguém capaz de executar o método &lt;code&gt;Enviar()&lt;/code&gt;." Isso é lindo. Porque o PedidoService não quer saber de e-mail, SMS, WhatsApp, sinal de fumaça... ele só quer &lt;em&gt;enviar&lt;/em&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  2. Criamos implementações dessa interface
&lt;/h3&gt;

&lt;p&gt;Enviar por E-mail:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailService&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;INotificacaoService&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;void&lt;/span&gt; &lt;span class="nf"&gt;Enviar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;mensagem&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Enviando Email: "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;mensagem&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;h2&gt;
  
  
  3. PedidoService não se importa mais com o &lt;em&gt;como&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Agora ele só recebe a dependência via construtor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PedidoService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;INotificacaoService&lt;/span&gt; &lt;span class="n"&gt;_notificacaoService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// INJEÇÃO DE DEPENDÊNCIA VIA CONSTRUTOR&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;PedidoService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;INotificacaoService&lt;/span&gt; &lt;span class="n"&gt;notificacaoService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_notificacaoService&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;notificacaoService&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;void&lt;/span&gt; &lt;span class="nf"&gt;FinalizarPedido&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_notificacaoService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Enviar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Pedido finalizado!"&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;



</description>
      <category>architecture</category>
      <category>codequality</category>
      <category>design</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Deploy: Cenário: Azure App Service + Github + SQL Server</title>
      <dc:creator>Yuri Peixinho</dc:creator>
      <pubDate>Thu, 08 Jan 2026 23:07:31 +0000</pubDate>
      <link>https://forem.com/yuripeixinho/deploy-cenario-azure-app-service-github-sql-server-2b0d</link>
      <guid>https://forem.com/yuripeixinho/deploy-cenario-azure-app-service-github-sql-server-2b0d</guid>
      <description>&lt;h1&gt;
  
  
  Introdução
&lt;/h1&gt;

&lt;p&gt;Deploy não é um botão. É um &lt;strong&gt;processo consciente&lt;/strong&gt; de levar software para o mundo real. Geralmente quando não temos conhecimento sobre os processos de deploy ficamos com algumas questões pendentes em nossa mente:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Onde o código roda?&lt;/li&gt;
&lt;li&gt;Como ele chega lá?&lt;/li&gt;
&lt;li&gt;Como ele acessa o banco?&lt;/li&gt;
&lt;li&gt;Como configuro sem expor segredo (secret)?&lt;/li&gt;
&lt;li&gt;Como atualizo sem quebrar tudo?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vamos passar por todo esse processo com aplicação em um cenário real.&lt;/p&gt;

&lt;h1&gt;
  
  
  As peças do cenário que vamos montar
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Azure App Service:&lt;/strong&gt; onde a aplicação roda&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Github:&lt;/strong&gt; onde seu código vive&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Github Actions (opcional, mas recomendado)&lt;/strong&gt;: automação de build e deploy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Azure SQL Database (SQL Server):&lt;/strong&gt; onde seus dados ficam
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="nf"&gt;GitHub&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="n"&gt;digo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;↓&lt;/span&gt;
&lt;span class="nf"&gt;Pipeline&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="n"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;↓&lt;/span&gt;
&lt;span class="n"&gt;Azure&lt;/span&gt; &lt;span class="n"&gt;App&lt;/span&gt; &lt;span class="nf"&gt;Service&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;API&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="err"&gt;↓&lt;/span&gt;
&lt;span class="n"&gt;Azure&lt;/span&gt; &lt;span class="n"&gt;SQL&lt;/span&gt; &lt;span class="nf"&gt;Database&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dados&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  1. O que é o Azure App Service?
&lt;/h1&gt;

&lt;p&gt;Como já vimos nos tipos de servidores, podemos dizer que o Azure Service é um serviço gerenciado. Isso significa que você:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Não cria servidor&lt;/li&gt;
&lt;li&gt;Não instala Windows/Linux&lt;/li&gt;
&lt;li&gt;Configura IIS, Kestrel, Nginx manualmente&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1.1 App Service
&lt;/h2&gt;

&lt;p&gt;A plataforma Azure cuida de todas essas questões pra você e quando você cria um App Service, você está definindo&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Runtime (ex: .NET 8)&lt;/li&gt;
&lt;li&gt;Plano de hospedagem (CPU / memória / custo)&lt;/li&gt;
&lt;li&gt;Região (onde o servidor fica)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Que resulta em uma URL pública e um ambiente pronto pra a execução do seu código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//minha-api.azurewebsites.net&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nesse momento, &lt;strong&gt;não tem código nenhum rodando ainda&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  1.2 Como o código chega na Azure? (Github Actions)
&lt;/h2&gt;

&lt;p&gt;Após a configuração do Azure App Service ser concluída precisamos efetivamente subir o nosso código de um determinado repositório para o Azure. Em nossa abordagem vamos utilizar o Github Actions e entender o problema que ele resolve.&lt;/p&gt;

&lt;h3&gt;
  
  
  1.1.1 Processo manual
&lt;/h3&gt;

&lt;p&gt;Antes do Github Actions, o deploy normalmente era assim:&lt;/p&gt;

&lt;p&gt;O desenvolvedor faz o seguinte processo:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Compila local&lt;/li&gt;
&lt;li&gt;Publica manualmente&lt;/li&gt;
&lt;li&gt;Sobre arquivo por FTP&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Esse processo gera problemas como inconsistência, erro humano, falta de histórico e deploys imprevisíveis&lt;/p&gt;

&lt;h3&gt;
  
  
  1.1.2 Github Actions
&lt;/h3&gt;

&lt;p&gt;Podemos dizer que o GitHub Actions é um robô configurável que roda dentro do GitHub sempre que algo acontece no repositório.&lt;/p&gt;

&lt;p&gt;Esse “algo” pode ser:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;push&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pull request&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;criação de tag&lt;/li&gt;
&lt;li&gt;horário agendado&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esse robô pode compilar código, rodar testes, gerar build, fazer deploy, enviar notificações, etc. Isso tudo só acontece porque um workflow é configurado.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;1.3 O que é um workflow e o que ele tem a ver com tudo isso?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Um workflow é um arquivo &lt;code&gt;.yml&lt;/code&gt; que diz sugere: “Quando X acontecer, execute Y passos nessa ordem”, então, por exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;SE&lt;/span&gt; &lt;span class="n"&gt;algu&lt;/span&gt;&lt;span class="err"&gt;é&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="n"&gt;fizer&lt;/span&gt; &lt;span class="n"&gt;push&lt;/span&gt; &lt;span class="n"&gt;na&lt;/span&gt; &lt;span class="n"&gt;branch&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;
&lt;span class="n"&gt;ENT&lt;/span&gt;&lt;span class="err"&gt;Ã&lt;/span&gt;&lt;span class="n"&gt;O&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;compile&lt;/span&gt;
  &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;teste&lt;/span&gt;
  &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;publique&lt;/span&gt;
  &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;fa&lt;/span&gt;&lt;span class="err"&gt;ç&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;deploy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E esse arquivo fica em:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;workflows&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;yml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse arquivo é código, portanto, o Deploy passa a ser &lt;strong&gt;versionado&lt;/strong&gt;, auditável e repetível.&lt;/p&gt;

&lt;h1&gt;
  
  
  2. Criando o SQL Server no Azure
&lt;/h1&gt;

&lt;p&gt;Ao criar um banco de dados no Azure, você já vai ter backup automático, alta disponibilidade e sem precisar instalar nada.&lt;/p&gt;

&lt;p&gt;Ao final do processo você vai ter o nome do servidor, nome do banco, usuário e senha. Essas informações nunca deve ir no código.&lt;/p&gt;

&lt;p&gt;Quando você cria o &lt;strong&gt;Azure SQL Database&lt;/strong&gt;, o Azure cria duas coisas:&lt;/p&gt;

&lt;h2&gt;
  
  
  2.1 Servidor Lógico (SQL Server)
&lt;/h2&gt;

&lt;p&gt;Não é uma VM (Virtual Machine) e sim um endpoint gerenciado para autenticação e conexões. Esse servidor:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pode ter vários bancos&lt;/li&gt;
&lt;li&gt;Centraliza segurança&lt;/li&gt;
&lt;li&gt;Controla firewall&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  No portal do Azure:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Azure SQL → Create&lt;/li&gt;
&lt;li&gt;Você define:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Server name&lt;/strong&gt; → &lt;code&gt;meu-servidor.database.windows.net&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Admin login&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Senha&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  2.2 Banco de dados
&lt;/h2&gt;

&lt;p&gt;Dentro do servidor: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Você cria o banco &lt;code&gt;nomeDoBanco&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Define

&lt;ul&gt;
&lt;li&gt;Camada (Basic / General Purpose / Business Critical)&lt;/li&gt;
&lt;li&gt;DTUs / vCores&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  2.3 Firewall do SQL Server
&lt;/h2&gt;

&lt;p&gt;Por padrão ninguém consegue acessar o banco.&lt;/p&gt;

&lt;p&gt;Você precisa configurar: &lt;strong&gt;Networking → Firewall rules&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Opções:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✔️ Allow Azure services&lt;/li&gt;
&lt;li&gt;✔️ Adicionar IP da sua máquina (para migrations locais)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚠️ Sem isso:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;App não conecta&lt;/li&gt;
&lt;li&gt;Migration falha&lt;/li&gt;
&lt;li&gt;Erro de timeout&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;👉 Em produção real:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ideal é &lt;strong&gt;Private Endpoint&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Mas para início: firewall simples resolve&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  3. Connection String, o elo entre a aplicação e o banco
&lt;/h1&gt;

&lt;p&gt;Essa é uma das partes mais importante de todo deploy. Sem essa conexão, nada conecta com a base de dados.&lt;/p&gt;

&lt;p&gt;Sem ela:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A aplicação sobe ✔️&lt;/li&gt;
&lt;li&gt;O banco existe ✔️&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mas nada se comunica&lt;/strong&gt; ❌&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ou seja: API no ar, mas &lt;strong&gt;toda requisição que depende de dados falha&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3.1 O que você já criou no Azure SQL Database
&lt;/h2&gt;

&lt;p&gt;Ao criar sua base de dados no Azure (SQL Server), você definiu:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Nome do servidor&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nome da base de dados&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Admin Login&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Senha&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tipo de autenticação (SQL Authentication)&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Essas informações são a base da sua connection string.&lt;/p&gt;

&lt;h2&gt;
  
  
  3.2 O que é, na prática, uma Connection String?
&lt;/h2&gt;

&lt;p&gt;É um texto que informa à aplicação:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Onde está o banco&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Qual banco acessar&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Como autenticar&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Como se comportar durante a conexão&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Exemplo genérico:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Server=...
Database=...
User Id=...
Password=...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3.3 De onde vem o valor da Connection String?
&lt;/h2&gt;

&lt;p&gt;No Azure SQL Database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SQLDatabase
 → Settings
     → Connection strings
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Normalmente você verá algo como:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Server=tcp:meuservidor.database.windows.net,1433;
Initial Catalog=MinhaBase;
PersistSecurityInfo=False;
User ID=adminuser;
Password=********;
MultipleActiveResultSets=False;
Encrypt=True;
TrustServerCertificate=False;
Connection Timeout=30;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Copie exatamente essa string&lt;/strong&gt; e cole no campo &lt;strong&gt;Value&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  3.4 Agora vamos ligar &lt;strong&gt;App → Banco&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Essa configuração é feita &lt;strong&gt;diretamente no Azure App Service&lt;/strong&gt;, sem precisar alterar código.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.4.1 Caminho no Azure Portal
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;App Service
 → Settings
 → Configuration
 → Connection strings
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa área funciona como um &lt;strong&gt;cofre de segredos&lt;/strong&gt; da aplicação.&lt;/p&gt;

&lt;p&gt;✅ Mais seguro&lt;/p&gt;

&lt;p&gt;✅ Separado do código&lt;/p&gt;

&lt;p&gt;✅ Ideal para ambientes (Dev / Homologação / Produção)&lt;/p&gt;

&lt;h3&gt;
  
  
  3.4.2 Nome da Connection String (Muito Importante)
&lt;/h3&gt;

&lt;p&gt;Se você usa &lt;strong&gt;Entity Framework Core&lt;/strong&gt;, o nome mais comum (e recomendado) é:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DefaultConnection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse nome precisa &lt;strong&gt;bater exatamente&lt;/strong&gt; com o que está no seu &lt;code&gt;Program.cs&lt;/code&gt; ou &lt;code&gt;appsettings.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Exemplo comum no código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AppDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseSqlServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetConnectionString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"DefaultConnection"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se o nome for diferente no Azure:&lt;/p&gt;

&lt;p&gt;❌ A aplicação sobe&lt;/p&gt;

&lt;p&gt;❌ Mas não encontra o banco&lt;/p&gt;

&lt;p&gt;❌ Erro clássico: &lt;em&gt;The ConnectionString property has not been initialized&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  4. Migrações
&lt;/h1&gt;

&lt;p&gt;Agora vem a parte &lt;strong&gt;mais importante do deploy com banco&lt;/strong&gt;. Vamos separar em três trilhas bem práticas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Migration Manual Local → Azure SQL &lt;/li&gt;
&lt;li&gt;Migration via GithubActions → Azure SQL (Pipeline)&lt;/li&gt;
&lt;li&gt;Migration por script SQL (práticas usadas por empresas)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  4.1. Migration Manual (local → Azure SQL)
&lt;/h2&gt;

&lt;p&gt;Pré-requisitos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Projeto com EF Core&lt;/li&gt;
&lt;li&gt;Migrations já criadas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Isso não mexe no banco ainda, apenas gera os arquivos C#.&lt;/p&gt;

&lt;h2&gt;
  
  
  4.2. Liberar o acesso ao banco no Azure
&lt;/h2&gt;

&lt;p&gt;Por padrão, o Azure SQL bloqueia tudo e precisamos autorizar nossa máquina local, sem isso nosso sistema dará o erro: Login failed / Timeout expired&lt;/p&gt;

&lt;p&gt;O que isso faz:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Autoriza &lt;strong&gt;sua máquina local&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Permite que o &lt;code&gt;dotnet ef&lt;/code&gt; conecte no banco remoto&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  No Portal Azure:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Azure SQL Server&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Networking&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Firewall rules&lt;/li&gt;
&lt;li&gt;Add your client IPv4 address&lt;/li&gt;
&lt;li&gt;Save&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  4.3. Garantir que sua aplicação aponta para o Azure
&lt;/h2&gt;

&lt;p&gt;Garante que seu arquivo &lt;code&gt;appsettings.Development.json&lt;/code&gt; está apontando para o SQL Server no azure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s"&gt;"ConnectionStrings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;"DefaultConnection"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Server=tcp:meuservidor.database.windows.net;..."&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4.4. Executar a migration
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt; &lt;span class="n"&gt;ef&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  O que acontece por trás:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;EF abre conexão com o Azure SQL&lt;/li&gt;
&lt;li&gt;Verifica se existe a tabela:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;__EFMigrationsHistory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Se &lt;strong&gt;não existir&lt;/strong&gt; → cria&lt;/li&gt;
&lt;li&gt;Se existir → lê quais migrations já rodaram&lt;/li&gt;
&lt;li&gt;Compara:

&lt;ul&gt;
&lt;li&gt;Migrations no código&lt;/li&gt;
&lt;li&gt;Migrations no banco&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Executa &lt;strong&gt;somente as pendentes&lt;/strong&gt;
&lt;/li&gt;

&lt;li&gt;Registra a versão aplicada&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>azure</category>
      <category>devops</category>
      <category>github</category>
      <category>sql</category>
    </item>
    <item>
      <title>Introdução ao Deploy</title>
      <dc:creator>Yuri Peixinho</dc:creator>
      <pubDate>Thu, 08 Jan 2026 23:06:12 +0000</pubDate>
      <link>https://forem.com/yuripeixinho/introducao-ao-deploy-2a07</link>
      <guid>https://forem.com/yuripeixinho/introducao-ao-deploy-2a07</guid>
      <description>&lt;h1&gt;
  
  
  Introdução
&lt;/h1&gt;

&lt;p&gt;Quando estamos desenvolvendo uma aplicação escrevemos o código em nosso computador. Esse código depois de escrito só consegue ser rodado em ambiente local e a aplicaçõo só pode ser acessada pelo seu próprio dispositivo.&lt;/p&gt;

&lt;p&gt;Mas como faz pra esse código rodar 24h por dia e acessível para outras pessoas? O deploy é a resposta. É o processo de “pegar” um software e colocá-lo em um ambiente que execute ele continuamente de forma estável, segura e acessível.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que precisa pra rodar o software?
&lt;/h2&gt;

&lt;p&gt;Todo sistema em produção precisa de 4 coisas básicas.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Código (sua aplicação)&lt;/li&gt;
&lt;li&gt;Máquina pra executar o código&lt;/li&gt;
&lt;li&gt;Dados (banco de dados, arquivos)&lt;/li&gt;
&lt;li&gt;Rede (internet)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Mais afinal, onde onde o deploy acontece?
&lt;/h2&gt;

&lt;p&gt;O Deploy acontece no servidor. O servidor é um computador ligado 24h, com CPU, memória, disco, sistema operacional, internet, etc. Uma observação importante é que você pode usar seu computador como um servidor (mas não é recomendado)&lt;/p&gt;

&lt;h1&gt;
  
  
  Tipos de servidores (do mais simples ao moderno)
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Servidor Físico
&lt;/h3&gt;

&lt;p&gt;É uma máquina real em um datacenter, você cuida de tudo. Geralmente é caro e complexo&lt;/p&gt;

&lt;h3&gt;
  
  
  Máquina Virtual (VM)
&lt;/h3&gt;

&lt;p&gt;Um servidor virtual dentro de outro servidor, você controla o SO (Sistema Operacional). &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Azure VM&lt;/li&gt;
&lt;li&gt;EC2 (AWS)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Plataforma Gerenciada (PaaS)
&lt;/h3&gt;

&lt;p&gt;Você só cuida do código e a nuvem cuida do servidor&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Azure App Service&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Containers (Docker)
&lt;/h3&gt;

&lt;p&gt;Seu aplicativo é empacotado com tudo que precisa e roda igual em qualquer lugar&lt;/p&gt;

&lt;h3&gt;
  
  
  Orquestração (Kubernates)
&lt;/h3&gt;

&lt;p&gt;Gerencia vários containers, alta escala e complexidade&lt;/p&gt;

&lt;h1&gt;
  
  
  O que acontece durante um deploy?
&lt;/h1&gt;

&lt;p&gt;Agora que sabemos o que é o deploy e quais são os tipos de servidores, vamos imaginar um deploy manual?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Desenvolvedor escreve o código&lt;/li&gt;
&lt;li&gt;Compila o código &lt;code&gt;(build)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Copia os arquivos para o servidor&lt;/li&gt;
&lt;li&gt;Configura variáveis de ambiente (ex: string de conexão, senhas de integrações, etc.).&lt;/li&gt;
&lt;li&gt;Inicia a aplicação&lt;/li&gt;
&lt;li&gt;Abre porta de rede&lt;/li&gt;
&lt;li&gt;Aponta um domínio &lt;/li&gt;
&lt;li&gt;Monitora erros&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>beginners</category>
      <category>devops</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Camadas de Validações de um Sistema backend</title>
      <dc:creator>Yuri Peixinho</dc:creator>
      <pubDate>Mon, 10 Nov 2025 23:46:55 +0000</pubDate>
      <link>https://forem.com/yuripeixinho/camadas-de-validacoes-de-um-sistema-backend-hdg</link>
      <guid>https://forem.com/yuripeixinho/camadas-de-validacoes-de-um-sistema-backend-hdg</guid>
      <description>&lt;h1&gt;
  
  
  Introdução
&lt;/h1&gt;

&lt;p&gt;Como você já deve saber, sistemas geralmente têm entrada e saída de dados (Input/Output).  Esses dados de entradas são armazenados em alguma base de dados existente.  Portanto, esses dados precisam ser controlados e validados para manter a consistência de sua aplicação.&lt;/p&gt;

&lt;p&gt;Por exemplo, se temos um campo de CPF (11 dígitos fixos) não podemos deixar o usuário inserir em nossa base de dados um CPF que contém 8 ou 15 dígitos ou que ele consiga criar dois CPFs iguais.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tipos de validações
&lt;/h2&gt;

&lt;p&gt;No backend existem três níveis principais de validação e é importante entender a diferença entre os conceitos. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validação de Entrada (Camada de API/Controller)&lt;/li&gt;
&lt;li&gt;Validação de Negócio (Camada de Aplicação /Domain Service)\&lt;/li&gt;
&lt;li&gt;Validação de Consistência/Infraestrutura&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Validação de Entrada (Camadas de API/Controller)
&lt;/h2&gt;

&lt;p&gt;Ocorre logo no início da aplicação (entrada de dados) e o objetivo é garantir que os dados cheguem válidos na camada de aplicação. É nessa camada que será realizado a validação posterior, de negócios.  É aqui que o sistema valida a estrutura e o formato, mas nunca a lógica do negócio.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplo:&lt;/strong&gt; verificar se o CPF tem 11 dígitos, mas não se ele existe no banco.&lt;/p&gt;

&lt;h2&gt;
  
  
  Validação de Negócio (Camada da Aplicação/Domain Service)
&lt;/h2&gt;

&lt;p&gt;Essa camada é posterior a validação de entrada. Caso todas as informações fornecidas no input da aplicação esteja correta, passamos para a fase da validação de negócio, seu objetivo é garantir que a ação faça sentido pra o sistema.&lt;/p&gt;

&lt;p&gt;Existem dois níveis de validação de regra de negócio.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Regras de Entidades (invariantes)&lt;/li&gt;
&lt;li&gt;Regras de negócio entre entidades (Serviço de Domínio)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Regras de Entidades (invariantes)
&lt;/h3&gt;

&lt;p&gt;São regras auto-suficientes que pertencem a uma única entidade e vão dentro da própria classe. As invariantes servem pra garantir consistência do domínio.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplos:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Não permitir criar um boleto para um cliente bloqueado.&lt;/li&gt;
&lt;li&gt;Impedir alteração de uma remessa já enviada.&lt;/li&gt;
&lt;li&gt;Garantir unicidade de um registro lógico (ex: CPF de uma pessoa).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Remessa&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;RemessaId&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;set&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="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;BancoId&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;set&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="n"&gt;Header&lt;/span&gt; &lt;span class="n"&gt;Header&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;set&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="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;ArquivoTXT&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;set&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="nf"&gt;Remessa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;bancoId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Header&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;arquivoTXT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;BancoId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bancoId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Header&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;ArquivoTXT&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arquivoTXT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nf"&gt;ValidarDominio&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;void&lt;/span&gt; &lt;span class="nf"&gt;ValidarDominio&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="n"&gt;Header&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;null&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="nf"&gt;DomainException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Header da remessa não pode ser nulo."&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="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrWhiteSpace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ArquivoTXT&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="nf"&gt;DomainException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Arquivo TXT não pode estar vazio."&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="n"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Agencia&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="m"&gt;4&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="nf"&gt;DomainException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"A agência deve ter 4 dígitos."&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;Repare que:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ValidarDominio()&lt;/code&gt; garante que &lt;strong&gt;nenhum objeto &lt;code&gt;Remessa&lt;/code&gt; inválido&lt;/strong&gt; possa existir.&lt;/li&gt;
&lt;li&gt;O construtor força a validação logo na criação.&lt;/li&gt;
&lt;li&gt;As propriedades têm &lt;code&gt;private set&lt;/code&gt;, ou seja, ninguém de fora pode alterar o estado diretamente.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;E você pode criar uma &lt;code&gt;DomainException&lt;/code&gt; personalizada (mais elegante do que &lt;code&gt;ValidationException&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DomainException&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Exception&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;DomainException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&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;base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&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;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Regras de negócios entre Entidades
&lt;/h3&gt;

&lt;p&gt;Essa camada geralmente valida as relações entre entidades, processos e cenário do negócio. Ele é o ponto que entende o contexto e orquestra o uso correto das entidades. &lt;/p&gt;

&lt;p&gt;Essa validação não valida formatos ou invariantes. Ele valida cenários de negócios como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Um cliente não pode ter duas assinaturas ativas”&lt;/li&gt;
&lt;li&gt;“Não é possível emitir uma fatura para um pedido cancelado”&lt;/li&gt;
&lt;li&gt;“O banco informado precisa existir e estar ativo”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Percebe que são regras contextuais e relacionais e não estruturais?&lt;/p&gt;

&lt;p&gt;Em qua fluxo de processo ela se encaixa? Ela vive entre o application Service e o Domain, e geralmente é acionada logo depois que os dados foram validados e antes de criar ou persistir entidades.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Controller&lt;/span&gt;  
  &lt;span class="err"&gt;⇣&lt;/span&gt;  
&lt;span class="n"&gt;DTO&lt;/span&gt; &lt;span class="nf"&gt;Validation&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;FluentValidation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Valida&lt;/span&gt;&lt;span class="err"&gt;çã&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;formato&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="err"&gt;⇣&lt;/span&gt;  
&lt;span class="n"&gt;Application&lt;/span&gt; &lt;span class="n"&gt;Service&lt;/span&gt;  
  &lt;span class="err"&gt;⇣&lt;/span&gt;  
&lt;span class="n"&gt;Business&lt;/span&gt; &lt;span class="nf"&gt;Validation&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;processo&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="n"&gt;contexto&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="err"&gt;É&lt;/span&gt; &lt;span class="n"&gt;aqui&lt;/span&gt; &lt;span class="n"&gt;que&lt;/span&gt; &lt;span class="n"&gt;entra&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;
  &lt;span class="err"&gt;⇣&lt;/span&gt;  
&lt;span class="n"&gt;Domain&lt;/span&gt; &lt;span class="nf"&gt;Validation&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invariantes&lt;/span&gt; &lt;span class="n"&gt;da&lt;/span&gt; &lt;span class="n"&gt;entidade&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
  &lt;span class="err"&gt;⇣&lt;/span&gt;  
&lt;span class="n"&gt;Repository&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="n"&gt;Persist&lt;/span&gt;&lt;span class="err"&gt;ê&lt;/span&gt;&lt;span class="n"&gt;ncia&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Normalmente essa etapa de validação se localiza den tro de &lt;code&gt;Application:&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Application&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="n"&gt;Validation&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="n"&gt;DTO&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;                &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;FluentValidation&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;Business&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;           &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;Regras&lt;/span&gt; &lt;span class="n"&gt;contextuais&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="n"&gt;Domain&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="n"&gt;opcional&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;regras&lt;/span&gt; &lt;span class="n"&gt;complexas&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="n"&gt;dom&lt;/span&gt;&lt;span class="err"&gt;í&lt;/span&gt;&lt;span class="n"&gt;nio&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa camada de validação geralmente utiliza repositórios, serviços de domínios e contexto de processos. Isto é:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Repositório:&lt;/strong&gt; verificar estados do sistema (se já exist algo no banco)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Serviços de Domínio:&lt;/strong&gt; se a regra envolve lógica consolidada, por exemplo: verificar limite de crédito, calcular juros, validar estoque&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contexto de Processo:&lt;/strong&gt; estado do sistema e coerência entre entidades, exemplo:  impedir fatura de pedido cancelado, proibir duplicidade de remessa.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Validação de Consistência/Infraestrutura
&lt;/h2&gt;

&lt;p&gt;Essa é a última etapa de validação e a mais crucial. O objetivo é proteger o sistema e o banco de dados de inconsistências estruturais. Ocorre na camada de repository e banco de dados.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplos:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chaves únicas (&lt;code&gt;UNIQUE&lt;/code&gt;, &lt;code&gt;PRIMARY KEY&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Relacionamentos (&lt;code&gt;FOREIGN KEY&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Restrições de tipo (&lt;code&gt;CHECK&lt;/code&gt;, &lt;code&gt;NOT NULL&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Abordagem Vertical Slice (VSA) em MediatR</title>
      <dc:creator>Yuri Peixinho</dc:creator>
      <pubDate>Wed, 29 Oct 2025 02:13:53 +0000</pubDate>
      <link>https://forem.com/yuripeixinho/abordagem-vertical-slice-vsa-em-mediatr-4kbp</link>
      <guid>https://forem.com/yuripeixinho/abordagem-vertical-slice-vsa-em-mediatr-4kbp</guid>
      <description>&lt;h1&gt;
  
  
  Introdução
&lt;/h1&gt;

&lt;p&gt;Existem algumas formas de estruturar o MediatR. Geralmente a estrutura utilziada é chamada de Estrutura Horizontal e é bem utiliza em projetos de pequeno porte. Acontece que abordagem horizontal ficaria insustentável rapidamente, pois a pasta &lt;code&gt;Commands&lt;/code&gt; e &lt;code&gt;Queries&lt;/code&gt; ficaria com centenas de arquivos.&lt;/p&gt;

&lt;h2&gt;
  
  
  Estrutura Horizontal
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Projeto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Application&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;Commands&lt;/span&gt;
&lt;span class="err"&gt;│ &lt;/span&gt; &lt;span class="err"&gt; ├──&lt;/span&gt; &lt;span class="n"&gt;Remessa&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="n"&gt;CreateRemessaCommand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&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="n"&gt;CreateRemessaCommandHandler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&lt;/span&gt;
&lt;span class="err"&gt;│ &lt;/span&gt; &lt;span class="err"&gt; ├──&lt;/span&gt; &lt;span class="n"&gt;Usuario&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;---&lt;/span&gt; &lt;span class="n"&gt;Crescendo&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="n"&gt;CreateUserCommand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&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="n"&gt;ChangePasswordCommand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;Queries&lt;/span&gt;
&lt;span class="err"&gt;│ &lt;/span&gt; &lt;span class="err"&gt; ├──&lt;/span&gt; &lt;span class="n"&gt;Remessa&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="n"&gt;GetRemessaByIdQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&lt;/span&gt;
&lt;span class="err"&gt;│ &lt;/span&gt; &lt;span class="err"&gt; ├──&lt;/span&gt; &lt;span class="n"&gt;Usuario&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;---&lt;/span&gt; &lt;span class="n"&gt;Crescendo&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="n"&gt;GetUserByEmailQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&lt;/span&gt;
&lt;span class="p"&gt;..&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  &lt;strong&gt;A Melhor Abordagem: Vertical Slice Architecture (VSA)&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;O VSA com CQRS/MediatR prioriza a organização do código pro funcionalidade (feature/casos de usos) em vez de por tipo de objeto.&lt;/p&gt;

&lt;p&gt;Então, em vez de ter comandos de várias entidades misturados na mesma pasta, você agrupa tudo que se refere aquela funcionalidade específica no mesmo lugar.&lt;/p&gt;

&lt;p&gt;O trabalho do VSA é inverter isso, criando pastas para cada feature principal do sistema, e dentro dela, agrupa os Commands, Queries e DTOS relacionados.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Projeto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Application&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="n"&gt;Features&lt;/span&gt;  &lt;span class="c1"&gt;// Ou 'UseCases', 'Slices', etc.&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="n"&gt;Remessas&lt;/span&gt;  &lt;span class="c1"&gt;// Feature: Gerenciamento de Arquivos de Remessa&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="n"&gt;CreateRemessa&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="n"&gt;CreateRemessaCommand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&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="n"&gt;CreateRemessaCommandHandler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&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="n"&gt;GetRemessaById&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="n"&gt;GetRemessaByIdQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&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="n"&gt;GetRemessaByIdQueryHandler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&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="n"&gt;RemessaDTO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&lt;/span&gt; &lt;span class="c1"&gt;// DTOs que são específicos da feature Remessa&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="n"&gt;Usuarios&lt;/span&gt; &lt;span class="c1"&gt;// Feature: Gerenciamento de Usuários e Contas&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="n"&gt;CreateUser&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="n"&gt;CreateUserCommand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&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="n"&gt;CreateUserCommandHandler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&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="n"&gt;GetUserDetails&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="n"&gt;GetUserDetailsQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&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="n"&gt;GetUserDetailsQueryHandler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&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="n"&gt;UserDTO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&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="n"&gt;Contas&lt;/span&gt; &lt;span class="c1"&gt;// Feature: Gerenciamento de Contas Bancárias&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="n"&gt;CreateContaBancaria&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="err"&gt; ├──&lt;/span&gt; &lt;span class="n"&gt;CreateContaBancariaCommand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&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="err"&gt; └──&lt;/span&gt; &lt;span class="n"&gt;CreateContaBancariaCommandHandler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cs&lt;/span&gt;
&lt;span class="p"&gt;..&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Desse modo, a gente consegue concluir que existe algumas vantagens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Alta coesão e baixo acoplamento&lt;/li&gt;
&lt;li&gt;Escalabilidade e Onborading (fácil para o desenvolvedor entender o sistema)&lt;/li&gt;
&lt;li&gt;Isolamento de Dependências (DI)&lt;/li&gt;
&lt;li&gt;Otimização do MediatR&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Dica extra: Handle na mesma pasta de Command
&lt;/h1&gt;

&lt;p&gt;Muitas vezes, o Command e o Handler são colocados no mesmo arquivo, reduzindo a poluição de arquivos, mas mantendo a estrutura de pastas clara. Exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Projeto.Application/Features/Remessas/CreateRemessa/CreateRemessa.cs&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreateRemessaCommand&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IRequest&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;RemessaDTO&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Propriedades do Command&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;class&lt;/span&gt; &lt;span class="nc"&gt;CreateRemessaCommandHandler&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IRequestHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CreateRemessaCommand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;RemessaDTO&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IRemessaRepository&lt;/span&gt; &lt;span class="n"&gt;_remessaRepository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;RemessaDTO&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CreateRemessaCommand&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Lógica de domínio/infraestrutura&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



</description>
      <category>architecture</category>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Descomplicando Simple Factory Method</title>
      <dc:creator>Yuri Peixinho</dc:creator>
      <pubDate>Wed, 29 Oct 2025 01:30:52 +0000</pubDate>
      <link>https://forem.com/yuripeixinho/descomplicando-simple-factory-method-5hfk</link>
      <guid>https://forem.com/yuripeixinho/descomplicando-simple-factory-method-5hfk</guid>
      <description>&lt;h1&gt;
  
  
  Introdução
&lt;/h1&gt;

&lt;p&gt;O Simple Factory Method não é um padrão de projeto oficial GOF, isso significa que ele não está catalogados nos livros, portanto é reconhecido como uma introdução a outros dois design patterns: Factory Method e Abstract Factory.&lt;/p&gt;

&lt;p&gt;Sua função é centralizar a responsabilidade de criar e entregar objetos de acordo com os parâmetros de entrada. Ele ajuda a reduzir o acoplamento e organizar a lógica de criação, por isso é considerado um design pattern criacional.&lt;/p&gt;

&lt;h1&gt;
  
  
  Quando surge a necessidade?
&lt;/h1&gt;

&lt;p&gt;Como já dito, podemos utilizar quando queremos centralizar a criação de objetos, com o objetivo do cliente não precisar reconhecer as classes concretas, o que gera desacoplamento.&lt;/p&gt;

&lt;p&gt;Então, alguns contextos são:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vários tipos de objetos que compartillham a mesma interface&lt;/li&gt;
&lt;li&gt;Reduzir o acoplamento de criação&lt;/li&gt;
&lt;li&gt;Facilita manutenção, extensão e escalabilidade do projeto. Se você tem um novo tipo de objeto basta adicionar no Factory sem tocar no cliente.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Exemplo prático
&lt;/h1&gt;

&lt;p&gt;Temos um sistema de geração de boletos que implementam para diferentes bancos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;BancoDoBrasil&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;BancoBradesco&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Queremos que o cliente da API peça um boleto sem se preocupar com qual classe concreta será instanciada.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interface do Boleto
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IBoleto&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;Gerar&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;
  
  
  Boletos Concretos
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BoletoBancoDoBrasil&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IBoleto&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;Gerar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Boleto gerado pelo Banco A"&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;class&lt;/span&gt; &lt;span class="nc"&gt;BoletoBradesco&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IBoleto&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;Gerar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Boleto gerado pelo Banco B"&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;
  
  
  Controller SEM Factory
&lt;/h3&gt;

&lt;p&gt;Nesse exemplo temos os seguintes problemas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Controller acoplado às classes concretas (&lt;code&gt;BancoDoBrasil&lt;/code&gt;, &lt;code&gt;BancoBradesco&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Adicionar um novo banco mexe diretamente no &lt;code&gt;Controller&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Código depende diretamente da implementação completa
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.AspNetCore.Mvc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ApiController&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"api/[controller]"&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;class&lt;/span&gt; &lt;span class="nc"&gt;BoletosController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ControllerBase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;HttpGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{banco}"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IActionResult&lt;/span&gt; &lt;span class="nf"&gt;GerarBoleto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;banco&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;IBoleto&lt;/span&gt; &lt;span class="n"&gt;boleto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;banco&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToLower&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"BancoDoBrasil"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;boleto&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;BoletoBancoDoBrasil&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s"&gt;"BancoBradesco"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;boleto&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;BoletoBradesco&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;BadRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Erro&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Banco não suportado"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;resultado&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boleto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Gerar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Mensagem&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resultado&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;h2&gt;
  
  
  Controller COM Factory
&lt;/h2&gt;

&lt;p&gt;Aqui, o controller usa a fábrica (Factory), não se importando com as classes concretas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Controller não conhece classes concretas.&lt;/li&gt;
&lt;li&gt;Fácil de adicionar novos tipos de boletos: só precisa atualizar a &lt;strong&gt;factory&lt;/strong&gt;, o controller continua intacto.&lt;/li&gt;
&lt;li&gt;Código mais limpo e desacoplado, seguindo o princípio Open/Closed (aberto para extensão, fechado para modificação).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Criando o método estático Factory&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BoletoFactory&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="n"&gt;IBoleto&lt;/span&gt; &lt;span class="nf"&gt;Criar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;banco&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="n"&gt;banco&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToLower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"BancoDoBrasil"&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;BoletoBancoDoBrasil&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="s"&gt;"BancoBradesco"&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;BoletoBradesco&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="p"&gt;=&amp;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="nf"&gt;ArgumentException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Banco não suportado"&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.AspNetCore.Mvc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ApiController&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"api/[controller]"&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;class&lt;/span&gt; &lt;span class="nc"&gt;BoletosController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ControllerBase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;HttpGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{banco}"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IActionResult&lt;/span&gt; &lt;span class="nf"&gt;GerarBoleto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;banco&lt;/span&gt;&lt;span class="p"&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;boleto&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BoletoFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Criar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;banco&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Factory faz o trabalho&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;resultado&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boleto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Gerar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Mensagem&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resultado&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="n"&gt;ArgumentException&lt;/span&gt; &lt;span class="n"&gt;ex&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="nf"&gt;BadRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Erro&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&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;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



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

&lt;p&gt;Quando o projeto cresce, geralmente o Simple Factory evolui para o Factory Method, onde cada tipo concreto pode ter sua própria classe factory.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>beginners</category>
      <category>designpatterns</category>
    </item>
    <item>
      <title>MediatR (bônus CQRS + Clean Architecture)</title>
      <dc:creator>Yuri Peixinho</dc:creator>
      <pubDate>Tue, 28 Oct 2025 00:04:34 +0000</pubDate>
      <link>https://forem.com/yuripeixinho/mediatr-bonus-cqrs-clean-architecture-i6n</link>
      <guid>https://forem.com/yuripeixinho/mediatr-bonus-cqrs-clean-architecture-i6n</guid>
      <description>&lt;h1&gt;
  
  
  Introdução
&lt;/h1&gt;

&lt;p&gt;O MediatR é uma biblioteca .NET que facilita a implementação prática do &lt;a href="https://www.notion.so/Mediator-284671b57a3e806d8d1afc074e6b971c?pvs=21" rel="noopener noreferrer"&gt;design pattern comportamental Mediator&lt;/a&gt;. O mediator centraliza a comunicação entre os componentes do sistema usando mensagens (Requests) e handlers (Handlers). &lt;/p&gt;

&lt;p&gt;Existem dois tipos principais de mensagens:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tipo&lt;/th&gt;
&lt;th&gt;Uso&lt;/th&gt;
&lt;th&gt;Retorno&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Command&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Executa uma ação (criar, atualizar, deletar)&lt;/td&gt;
&lt;td&gt;Pode retornar &lt;code&gt;Unit&lt;/code&gt; (void) ou algum resultado&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Query&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Busca dados&lt;/td&gt;
&lt;td&gt;Retorna um valor, DTO ou objeto&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Estrutura básica:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;IRequest&amp;lt;TResponse&amp;gt;&lt;/code&gt;&lt;strong&gt;:&lt;/strong&gt; representa a requisição (Command ou Query)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;IRequestHandler&amp;lt;TRequest, TResponse&amp;gt;&lt;/code&gt;&lt;strong&gt;:&lt;/strong&gt; lida com a requisição&lt;/p&gt;

&lt;p&gt;&lt;code&gt;IMediator:&lt;/code&gt; interface usada para enviar as requisições&lt;/p&gt;

&lt;h1&gt;
  
  
  Commands, Handlers e Queries
&lt;/h1&gt;

&lt;p&gt;Antes de aprofundarmos tecnicamente e de forma prática em MediatR é importante entender sobre os Commands e Queries. Esses dois termo são conceitos que estão diretamente ligados ao &lt;a href="https://www.notion.so/CQRS-Command-Query-Responsibility-Segregation-280671b57a3e8054849ef5dba192568b?pvs=21" rel="noopener noreferrer"&gt;CQRS (Command Query Responsability Segregation).&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;No MediatR, você envia um Command ou Query, e o Handler é responsável por processar e orquestrar toda a lógica relacionada a essa requisição. Dessa forma, Controllers ou Services não precisam conhecer os detalhes internos de implementação do Command ou Query, mantendo o código mais desacoplado e organizado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Commands
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Definem a ação que muda o estado do objeto (entidade no banco)&lt;/li&gt;
&lt;li&gt;Devem &lt;strong&gt;implementar&lt;/strong&gt; &lt;code&gt;IRequest&amp;lt;T&amp;gt;&lt;/code&gt;, onde &lt;code&gt;T&lt;/code&gt; é o tipo de retorno (pode ser &lt;code&gt;Unit&lt;/code&gt; se não retornar nada)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;CreateUserCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IRequest&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui &lt;code&gt;int&lt;/code&gt; é o ID do usuário criado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Queries
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Definem a ação de leitura de um objeto (entidade no banco), sem alteração de dados&lt;/li&gt;
&lt;li&gt;Também implementam um&lt;code&gt;IRequest&amp;lt;T&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;GetUserByIdQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IRequest&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UserDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Retorna &lt;code&gt;UserDto&lt;/code&gt;, ou seja, os dados do usuário.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Handlers
&lt;/h2&gt;

&lt;p&gt;É aqui que a mágica acontece, cada Command/Query tem um handler separado, implementando &lt;code&gt;IRequestHandler&amp;lt;TRequest, TResponse&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Exemplo de Command Handler
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreateUserCommandHandler&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IRequestHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CreateUserCommand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IUserRepository&lt;/span&gt; &lt;span class="n"&gt;_repo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;CreateUserCommandHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IUserRepository&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_repo&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repo&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;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CreateUserCommand&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="p"&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;request&lt;/span&gt;&lt;span class="p"&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;Email&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Email&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&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;
  
  
  Exemplo de Query Handler
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GetUserByIdQueryHandler&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IRequestHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;GetUserByIdQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UserDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IUserRepository&lt;/span&gt; &lt;span class="n"&gt;_repo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;GetUserByIdQueryHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IUserRepository&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_repo&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repo&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;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UserDto&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GetUserByIdQuery&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_repo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetByIdAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&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="nf"&gt;UserDto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&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;user&lt;/span&gt;&lt;span class="p"&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;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Email&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;h1&gt;
  
  
  Exemplo prático
&lt;/h1&gt;

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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Install&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Package&lt;/span&gt; &lt;span class="n"&gt;MediatR&lt;/span&gt;
&lt;span class="n"&gt;Install&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Package&lt;/span&gt; &lt;span class="n"&gt;MediatR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Extensions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DependencyInjection&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Exemplo prático – CRUD de Produto
&lt;/h2&gt;

&lt;p&gt;Vamos comparar o projeto de API em &lt;strong&gt;Clean Architecture&lt;/strong&gt; com camadas. Teremos dois cenários, o primeiro sem a utilização do MediatR, e o segundo cenário com ele aplicado.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Application
 ├── Commands
 │    ├── CreateProductCommand.cs
 │    └── UpdateProductCommand.cs
 ├── Queries
 │    ├── GetProductByIdQuery.cs
 │    └── GetAllProductsQuery.cs
 ├── Handlers
 │    ├── CreateProductHandler.cs
 │    ├── GetProductByIdHandler.cs
Infrastructure
 └── Repositories
Presentation (API)
 └── Controllers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Sem MediatR (código acoplado)
&lt;/h3&gt;

&lt;p&gt;Aqui o Controller conhece diretamente o serviço/repositório e faz toda a lógica:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Controller&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ApiController&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"api/users"&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;class&lt;/span&gt; &lt;span class="nc"&gt;UsersController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ControllerBase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IUserRepository&lt;/span&gt; &lt;span class="n"&gt;_userRepository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;UsersController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IUserRepository&lt;/span&gt; &lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_userRepository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userRepository&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="n"&gt;HttpPost&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;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IActionResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UserCreateDto&lt;/span&gt; &lt;span class="n"&gt;dto&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Lógica de negócio diretamente no controller&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;BadRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Nome e email são obrigatórios."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="p"&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;dto&lt;/span&gt;&lt;span class="p"&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;Email&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Email&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_userRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O problema aqui é:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Controller faz validação e persistência, acumulando responsabilidades.&lt;/li&gt;
&lt;li&gt;Difícil testar a lógica isoladamente.&lt;/li&gt;
&lt;li&gt;Difícil reaproveitar a lógica em outro ponto da aplicação.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Com MediatR (código desacoplado)
&lt;/h3&gt;

&lt;p&gt;Nesse cenário separamos Command, Handler e Controller.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Command&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;record&lt;/span&gt; &lt;span class="nc"&gt;CreateUserCommand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IRequest&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Handler&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CreateUserCommandHandler&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IRequestHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CreateUserCommand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IUserRepository&lt;/span&gt; &lt;span class="n"&gt;_userRepository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;CreateUserCommandHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IUserRepository&lt;/span&gt; &lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_userRepository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userRepository&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;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CreateUserCommand&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&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="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Email&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="nf"&gt;ArgumentException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Nome e email são obrigatórios."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="p"&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;request&lt;/span&gt;&lt;span class="p"&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;Email&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Email&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_userRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&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;// Controller&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ApiController&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;Route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"api/users"&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;class&lt;/span&gt; &lt;span class="nc"&gt;UsersController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ControllerBase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IMediator&lt;/span&gt; &lt;span class="n"&gt;_mediator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;UsersController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IMediator&lt;/span&gt; &lt;span class="n"&gt;mediator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_mediator&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mediator&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="n"&gt;HttpPost&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;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IActionResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;FromBody&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;CreateUserCommand&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_mediator&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="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// envia o comando para o Handler&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&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;ul&gt;
&lt;li&gt;Controller não conhece a lógica interna, só envia o comando.&lt;/li&gt;
&lt;li&gt;Lógica isolada no Handler, fácil de testar unitariamente.&lt;/li&gt;
&lt;li&gt;Fácil adicionar validações, logs, notificações, etc., sem mudar o Controller.&lt;/li&gt;
&lt;li&gt;Código mais organizado e escalável em projetos grandes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Mediator aplicado ao Clean Arch + CQRS
&lt;/h1&gt;

&lt;p&gt;Ao aplicar o padrão MediatR + CQRS + Clean Arch em um cenário simples como apenas a listagem de alguns produtos (uma única ação) pode deixar a visão dos desenvolvedores nebulosa.&lt;/p&gt;

&lt;p&gt;Em sistemas complexos, essa separação evita acoplamento rígido, quando uma mudança na infraestrutura é dada, como trocar o banco de dados, que bra a lógica de negócio. &lt;/p&gt;

&lt;p&gt;O objetivo aqui é entender o propósito de “tanta separação de camadas e responsabilidades” e deixar claro como o &lt;strong&gt;Handle isola a complexidade do serviço.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;O Fluxo Complexo com CQRS/Mediator:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Vamos imaginar o sistema de gerenciamentos de pedidos e estoques (e-commerce)&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Controller e Command&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;O Controller recebe a requisição de finalização e despacha um &lt;strong&gt;Command&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// OrdersController (Complexo)&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IActionResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;PlaceOrder&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;FromBody&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;PlaceOrderDTO&lt;/span&gt; &lt;span class="n"&gt;orderDto&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// 1. Mapeia DTO para Command&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_mapper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PlaceOrderCommand&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;orderDto&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. Despacha o Command via Mediator&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;orderId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_mediator&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="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;orderId&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;2. Service/Mediator e CommandHandler (Onde a Complexidade é Isolada)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;O &lt;code&gt;PlaceOrderCommand&lt;/code&gt; é enviado para o &lt;code&gt;PlaceOrderCommandHandler&lt;/code&gt;. &lt;strong&gt;É aqui que o Mediator/CQRS justifica sua existência.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Em CleanArchMvc.Application.Products.Handlers;&lt;/span&gt;
&lt;span class="c1"&gt;// Dependências injetadas que representam o acesso à infraestrutura e a outros serviços&lt;/span&gt;
&lt;span class="c1"&gt;// As interfaces (IOrderRepository, IInventoryService, IPaymentGateway, etc.)&lt;/span&gt;
&lt;span class="c1"&gt;// estão definidas na Camada de Domínio e implementadas na Camada de Infraestrutura.&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PlaceOrderCommandHandler&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IRequestHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PlaceOrderCommand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IOrderRepository&lt;/span&gt; &lt;span class="n"&gt;_orderRepository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IInventoryService&lt;/span&gt; &lt;span class="n"&gt;_inventoryService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Ex: Serviço para chamar API de Estoque&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IPaymentGateway&lt;/span&gt; &lt;span class="n"&gt;_paymentGateway&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Ex: Serviço para chamar API de Pagamento (Stripe/PagSeguro)&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;PlaceOrderCommandHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;IOrderRepository&lt;/span&gt; &lt;span class="n"&gt;orderRepository&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;IInventoryService&lt;/span&gt; &lt;span class="n"&gt;inventoryService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;IPaymentGateway&lt;/span&gt; &lt;span class="n"&gt;paymentGateway&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_orderRepository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;orderRepository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;_inventoryService&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inventoryService&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;_paymentGateway&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;paymentGateway&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;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PlaceOrderCommand&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// 1. Lógica de Domínio: Criação da Entidade&lt;/span&gt;
        &lt;span class="c1"&gt;// Assumimos que a Entidade 'Order' tem um método estático de criação que &lt;/span&gt;
        &lt;span class="c1"&gt;// aplica as regras de negócio de criação (ex: define o status inicial).&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateNew&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CustomerEmail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ShippingAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TotalAmount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;OrderItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProductId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Quantity&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// 2. Orquestração: Verificação de Estoque (Chama um serviço de infraestrutura)&lt;/span&gt;
        &lt;span class="c1"&gt;// Isso pode ser uma chamada a uma API externa de gerenciamento de estoque.&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;stockCheck&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_inventoryService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CheckStockAvailability&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Items&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="n"&gt;stockCheck&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsAvailable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Lança uma exceção de domínio (que será tratada globalmente na WebUI)&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DomainException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Estoque indisponível para o(s) produto(s): &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;stockCheck&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UnavailableProducts&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&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;// 3. Persistência (Ponto 1): Salva o Pedido Inicial (Status: Pendente/Aguardando Pagamento)&lt;/span&gt;
        &lt;span class="c1"&gt;// Isso garante que o pedido existe no banco antes de tentar o pagamento,&lt;/span&gt;
        &lt;span class="c1"&gt;// permitindo o rastreio de pagamentos falhos.&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_orderRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// 4. Orquestração: Processamento de Pagamento (Chama outro serviço de infraestrutura)&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;paymentResult&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_paymentGateway&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ProcessPayment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&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;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TotalAmount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PaymentInfo&lt;/span&gt; &lt;span class="c1"&gt;// Assumindo que o Command tem dados de cartão/boleto&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="n"&gt;paymentResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// 5. Lógica de Compensação (Rollback Lógico)&lt;/span&gt;
            &lt;span class="c1"&gt;// Se o pagamento falhar, atualiza o status do pedido e lança uma exceção.&lt;/span&gt;
            &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CancelOrder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Método na Entidade Order&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_orderRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UpdateAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&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="nf"&gt;PaymentFailedException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;paymentResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrorMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// 6. Lógica de Domínio: Pedido Aprovado&lt;/span&gt;
        &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ApproveOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;paymentResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TransactionId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Método na Entidade Order (muda o status)&lt;/span&gt;

        &lt;span class="c1"&gt;// 7. Persistência (Ponto 2): Salva as Mudanças da Aprovação&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_orderRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UpdateAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&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;Como dá pra perceber acima, o código é a materialização da SoC, separação de preocupações (Separation of Concerns) e do SRP, Princípio da Responsabilidade única (SRP).&lt;/p&gt;

&lt;p&gt;A função principal do handle acima não é executar nenhuma tarefa bruta (como acessar o banco de dados), mas sim ORQUESTRAR a sequência dos passos que definem o processo de “Fazer um pedido”. (a lógica de negócio complexa)&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>designpatterns</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>.NET AutoMapper (DTOs)</title>
      <dc:creator>Yuri Peixinho</dc:creator>
      <pubDate>Sat, 25 Oct 2025 16:24:35 +0000</pubDate>
      <link>https://forem.com/yuripeixinho/automapper-dtos-1708</link>
      <guid>https://forem.com/yuripeixinho/automapper-dtos-1708</guid>
      <description>&lt;h1&gt;
  
  
  Introdução
&lt;/h1&gt;

&lt;p&gt;O AutoMapper é uma biblioteca utilizada para mapear objetos. Ele ajuda a resolver esse problema ao automatizar o mapeamento entre diferentes objetos de diferentes camadas, como entre entidades de bancos de dados e objetos de transferências de dados (DTOs). Isso facilita o desenvolvimento ao reduzir a quantidade de código manual para conversões, promovendo um maior desacoplamento e flexibiliade do projeto.&lt;/p&gt;

&lt;h1&gt;
  
  
  O problema que o AutoMapper resolve
&lt;/h1&gt;

&lt;p&gt;Imagine que você tem uma aplicação que têm muitas entidades e &lt;a href="https://dev.to/yuripeixinho/utilizacao-de-dtos-4ilk"&gt;DTOs&lt;/a&gt; parecidos, como por exemplo &lt;code&gt;Product&lt;/code&gt;. Você precisará mapear manualmente dezenas ou centenas de classes e DTO, e fazer isso&lt;/p&gt;

&lt;h2&gt;
  
  
  Exemplo didático do problema
&lt;/h2&gt;

&lt;p&gt;Vamos retomar o exemplo do &lt;code&gt;Product&lt;/code&gt;, descrito acima.&lt;/p&gt;

&lt;p&gt;Imagine que você tem um &lt;code&gt;Model&lt;/code&gt; de &lt;code&gt;Product&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&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="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&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="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;Price&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&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;E um DTO que representa o que você quer enviar ao cliente sem o ID:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&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="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&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="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;Price&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O problema é: toda vez que você quiser converter de &lt;code&gt;Product&lt;/code&gt; -&amp;gt; &lt;code&gt;ProductDTO&lt;/code&gt;, você teria que escrever:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;productDTO&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ProductDTO&lt;/span&gt;
&lt;span class="p"&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;product&lt;/span&gt;&lt;span class="p"&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;Price&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Price&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;e quando for o contrário (DTO → Entidade)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Product&lt;/span&gt;
&lt;span class="p"&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;productDTO&lt;/span&gt;&lt;span class="p"&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;Price&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;productDTO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Price&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa prática em projetos de pequeno porte pode ser eficiente, mas em projetos grandes significa:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Muito código repetitivo&lt;/li&gt;
&lt;li&gt;Alta chance de erro (esquecer um campo, errar um nome, etc.).&lt;/li&gt;
&lt;li&gt;Difícil manutenção (se mudar o nome de uma propriedade, você precisará alterar em todos os lugares)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Exemplo didático da solução (AutoMapper)
&lt;/h2&gt;

&lt;p&gt;O papel do automapper é automatizar essa conversão. Ele faz um mapeamento de propriedades entre objetos de tipos diferentes, desde que o nomes e tipos sejam compatíveis.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Primeiro você cria uma configuração de mapeamento &lt;code&gt;(Profile)&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;AutoMapper&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;class&lt;/span&gt; &lt;span class="nc"&gt;MappingProfile&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Profile&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;MappingProfile&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;CreateMap&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ProductDTO&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt; &lt;span class="c1"&gt;// diz como mapear de Product → ProductDTO&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Depois registra essa configuração no seu projeto (normalmente no Program.cs ou em arquivo de configurações como método de extensão)
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;AutoMapper&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;class&lt;/span&gt; &lt;span class="nc"&gt;MappingProfile&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Profile&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;MappingProfile&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;CreateMap&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ProductDTO&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt; &lt;span class="c1"&gt;// diz como mapear de Product → ProductDTO&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;E finalmente, em qualquer lugar do código, você pode converter objetos facilmente:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;productDTO&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_mapper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ProductDTO&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Desse modo o AutoMapper automatica copia as propriedades &lt;code&gt;Name, Price&lt;/code&gt; sem você precisar escrever nada disso manualmente.&lt;/p&gt;

&lt;h1&gt;
  
  
  Registrar serviços do AutoMapper
&lt;/h1&gt;

&lt;p&gt;O registro do automapper pode ser feito de diferentes maneiras, e dependem da estrutura e do tamanho do projeto.&lt;/p&gt;

&lt;p&gt;Ele deve ser feito uma única vez no ponto central da aplicação, onde o container de injeção de dependência deve ser configurado&lt;/p&gt;

&lt;p&gt;Dependendo da arquitetura, isso pode ficar em lugares diferentes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Program.cs&lt;/code&gt; (projetos .NET 6+)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Startup.cs&lt;/code&gt; (projetos .NET 5 ou anteriores)&lt;/li&gt;
&lt;li&gt;um &lt;strong&gt;método de extensão&lt;/strong&gt; (boa prática para Clean Architecture)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Projeto simples sem camadas
&lt;/h2&gt;

&lt;p&gt;Nos projetos mais simples, geralmente configuramos no &lt;code&gt;Program.cs&lt;/code&gt; do projeto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;AutoMapper&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;MyApp.Mappings&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// pasta onde ficam seus Profiles&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Registro do AutoMapper&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddAutoMapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MappingProfile&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Projeto com Clean Architecture
&lt;/h2&gt;

&lt;p&gt;Esse é o cenário mais comuns em projetos profisisonais. A ideia é criar um método de extensão para centralizar os registros dessa camada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Extensions.DependencyInjection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Reflection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;MyApp.Application&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;class&lt;/span&gt; &lt;span class="nc"&gt;DependencyInjection&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="n"&gt;IServiceCollection&lt;/span&gt; &lt;span class="nf"&gt;AddApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="n"&gt;IServiceCollection&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddAutoMapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetExecutingAssembly&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;services&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;h1&gt;
  
  
  Quando usar vs. Quando não usar
&lt;/h1&gt;

&lt;p&gt;É importante entender o contexto de arquitetura e escalabilidade do projeto antes de decidir utilizar o AutoMapper.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situação&lt;/th&gt;
&lt;th&gt;Recomendação&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Muitos DTOs parecidos e simples&lt;/td&gt;
&lt;td&gt;✅ AutoMapper é ótimo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Projeto pequeno / poucos mapeamentos&lt;/td&gt;
&lt;td&gt;❌ Faça manualmente&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Precisa de controle fino / regras de negócio&lt;/td&gt;
&lt;td&gt;❌ Manual&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Busca performance máxima&lt;/td&gt;
&lt;td&gt;⚠️ Prefira Mapster ou manual&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h1&gt;
  
  
  Alternativas modernas ao AutoMapper
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Mapster:&lt;/strong&gt; mais rápido e com menos configuração.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Manual mapping + extensions:&lt;/strong&gt; simples e explícito, ideal para APIs pequenas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;UserDto&lt;/span&gt; &lt;span class="nf"&gt;ToDto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;UserDto&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&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;user&lt;/span&gt;&lt;span class="p"&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;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>webdev</category>
    </item>
  </channel>
</rss>
