<?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: Rafael Honório</title>
    <description>The latest articles on Forem by Rafael Honório (@rafahs).</description>
    <link>https://forem.com/rafahs</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%2F682574%2F5c853e0f-01ee-485d-9c44-2f46fe7cc96d.jpeg</url>
      <title>Forem: Rafael Honório</title>
      <link>https://forem.com/rafahs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/rafahs"/>
    <language>en</language>
    <item>
      <title>Understanding SOLID once and for all | Part 04 - (ISP)</title>
      <dc:creator>Rafael Honório</dc:creator>
      <pubDate>Wed, 06 Aug 2025 02:43:51 +0000</pubDate>
      <link>https://forem.com/rafahs/understanding-solid-once-and-for-all-part-03-isp-3kla</link>
      <guid>https://forem.com/rafahs/understanding-solid-once-and-for-all-part-03-isp-3kla</guid>
      <description>&lt;p&gt;Hey folks, continuing the series about &lt;strong&gt;SOLID&lt;/strong&gt;, today we will talk about the &lt;strong&gt;Interface Segregation Principle (ISP)&lt;/strong&gt;. In my view, this is the easiest concept of the five principles. The name already says a lot about what we will discuss, and I will also share some cool insights about &lt;strong&gt;interfaces&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The idea of an interface appeared at the end of the eighties, after languages like &lt;a href="https://pt.wikipedia.org/wiki/Simula" rel="noopener noreferrer"&gt;Simula&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Smalltalk" rel="noopener noreferrer"&gt;Smalltalk&lt;/a&gt; had already introduced most of the basics we know today as &lt;strong&gt;object-oriented programming&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bertrand Meyer&lt;/strong&gt; formally presented the interface concept in his book &lt;em&gt;Object Oriented Software Construction&lt;/em&gt;, published in 1988. In that book, he defined the concept of contracts between software components in the &lt;strong&gt;Eiffel&lt;/strong&gt; language. Since then, these techniques have been adopted in many other languages, such as Java, C#, and Ruby.&lt;/p&gt;

&lt;p&gt;The goal of creating a contract (interface) is to show that a certain module has common behaviour that can be reused in different contexts. Classic examples are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Interaction with a database&lt;/li&gt;
&lt;li&gt;Interaction with cache&lt;/li&gt;
&lt;li&gt;Interaction with a message broker&lt;/li&gt;
&lt;li&gt;Interaction with subtypes (inheritance)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All those situations share two ideas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;There is a base behaviour that repeats in all or almost all cases.&lt;/li&gt;
&lt;li&gt;Each implementation will be used in many places in your code.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Interface Segregation Principle says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;No client should be forced to depend on methods it does not use.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So an interface should define behaviour for a specific area of your software, making the code more cohesive and less coupled.&lt;/p&gt;

&lt;h2&gt;
  
  
  Examples
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Printer&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;PrintColorFull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;Fax&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;BasicPrinter&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BasicPrinter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Printing..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;In this case, the other methods are missing, so it breaks ISP.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A better approach is to create specific interfaces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Printable&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;PrintableColor&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;PrintColorFull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Scannable&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Faxable&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Fax&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;BasicPrinter&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BasicPrinter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Printing..."&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;Now, ISP is respected. In short, we have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All &lt;strong&gt;interfaces&lt;/strong&gt; defined&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;struct&lt;/strong&gt; called &lt;code&gt;BasicPrinter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Implementation of &lt;code&gt;Printable&lt;/code&gt; in &lt;code&gt;BasicPrinter&lt;/code&gt; by adding the &lt;code&gt;Print()&lt;/code&gt; method&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; In Go, these links are implicit.&lt;/p&gt;

&lt;p&gt;Below is a similar example in &lt;strong&gt;Elixir&lt;/strong&gt;. The language allows generic return types, so you can implement the behaviour in other modules without returning the same data type.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Elixir&lt;/strong&gt; an “interface” is called a &lt;strong&gt;behavior&lt;/strong&gt; or &lt;strong&gt;callback&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MultiFunctionDevice&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@callback&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nv"&gt;@callback&lt;/span&gt; &lt;span class="n"&gt;fax&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nv"&gt;@callback&lt;/span&gt; &lt;span class="n"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;SimplePrinter&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@behaviour&lt;/span&gt; &lt;span class="no"&gt;MultiFunctionDevice&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Printing"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;fax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="ss"&gt;:not_implemented&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="ss"&gt;:not_implemented&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same idea applies here. Even though the function exists, returning &lt;code&gt;:not_implemented&lt;/code&gt; or leaving empty functions shows that the interface is poorly designed and still breaks the principle.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;PrinterOnly&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@callback&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Same strategy: split the interface into smaller ones.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Interfaces have no mystery. ISP pushes us to split big interfaces into smaller cohesive contexts, which helps in many cases like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inheritance between objects&lt;/li&gt;
&lt;li&gt;Interaction with external services (cache, message broker, database)&lt;/li&gt;
&lt;li&gt;Structured error handling&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What we get:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Less coupling&lt;/li&gt;
&lt;li&gt;More cohesive code&lt;/li&gt;
&lt;li&gt;Code that adapts better to change&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Reference code
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Elixir examples: &lt;a href="https://github.com/rafael-hs/solid_elixir_examples" rel="noopener noreferrer"&gt;solid_elixir_examples&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Go examples: &lt;a href="https://github.com/rafael-hs/solid-go-examples" rel="noopener noreferrer"&gt;solid-go-examples&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope the concepts are clear. If you still have questions, feel free to leave a comment.&lt;/p&gt;

</description>
      <category>solidprinciples</category>
      <category>isp</category>
      <category>cleancode</category>
      <category>programming</category>
    </item>
    <item>
      <title>Entendendo SOLID de uma vez por todas | Parte 04 - (ISP)</title>
      <dc:creator>Rafael Honório</dc:creator>
      <pubDate>Wed, 06 Aug 2025 02:32:08 +0000</pubDate>
      <link>https://forem.com/rafahs/entendendo-solid-de-uma-vez-por-todas-parte-04-isp-2o2b</link>
      <guid>https://forem.com/rafahs/entendendo-solid-de-uma-vez-por-todas-parte-04-isp-2o2b</guid>
      <description>&lt;p&gt;Hey pessoal, continuando a série sobre SOLID, hoje vamos falar sobre o &lt;strong&gt;Interface Segregation Principle (ISP)&lt;/strong&gt;. Esse é, na minha opinião, o conceito mais tranquilo dos cinco princípios. O próprio nome já entrega bastante sobre o que vamos conversar, e ainda vou aproveitar para trazer alguns &lt;strong&gt;insights&lt;/strong&gt; interessantes sobre &lt;strong&gt;interfaces&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resumo
&lt;/h2&gt;

&lt;p&gt;O conceito de interface surgiu no final da década de 80, após as linguagens &lt;a href="https://pt.wikipedia.org/wiki/Simula" rel="noopener noreferrer"&gt;Simula&lt;/a&gt; e &lt;a href="https://en.wikipedia.org/wiki/Smalltalk" rel="noopener noreferrer"&gt;Smalltalk&lt;/a&gt; já terem introduzido boa parte dos fundamentos que a gente entende hoje como &lt;strong&gt;orientação a objetos&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Foi o &lt;strong&gt;Bertrand Meyer&lt;/strong&gt; quem apresentou formalmente o conceito de &lt;strong&gt;interface&lt;/strong&gt; em seu livro &lt;em&gt;Object-Oriented Software Construction&lt;/em&gt;, publicado em 1988. Nele, Meyer definiu a ideia de contratos entre componentes de software na linguagem &lt;strong&gt;Eiffel&lt;/strong&gt;, e desde então essas técnicas e conceitos passaram a ser aplicados amplamente em outras linguagens como Java, C#, Ruby, entre outras.&lt;/p&gt;

&lt;p&gt;A intenção de criar um contrato (interface) parte da ideia de que determinado módulo do software possui características comuns que podem ser reaproveitadas em vários contextos diferentes. Exemplos clássicos disso seriam:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Interação com banco de dados&lt;/li&gt;
&lt;li&gt;Interação com cache&lt;/li&gt;
&lt;li&gt;Interação com message broker&lt;/li&gt;
&lt;li&gt;Interação com subtipos (herança)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Todas essas situações tem em comum dois pontos em comum;&lt;br&gt;
1 - Existe uma base de comportamento que vai se repetir em todas, ou quase todas as vezes. &lt;br&gt;
2 - Cada implementação vai ser usada em vários pontos do seu código.&lt;/p&gt;

&lt;p&gt;A definição de Interface Segregation Principle (IPS) é:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nenhum cliente deve ser forçado a depender de métodos que não utiliza.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ou seja, a tendência é que interface defina comportamentos de uma determinada área do seu software com intuíto de criar mais coesão e desacoplamento entre os módulos.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Vamos aos exemplos&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Printer&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;PrintColorFull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;Fax&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="n"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;BasicPrinter&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BasicPrinter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Printing..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;nesse caso não existe implementação dos outros métodos, isso viola o ISP.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;O correto seria ter interfaces específicas para esse caso&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Printable&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;PrintableColor&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;PrintColorFull&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Scannable&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Scan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Faxable&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Fax&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;BasicPrinter&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BasicPrinter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Printing..."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora não infringe o ISP, talvez fique um pouco complicado de entender para quem não familiaridade com Golang mas o que aconteceu nesse código foi:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Definição de todas &lt;strong&gt;interfaces&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Definição de uma &lt;strong&gt;struct&lt;/strong&gt; chamada &lt;code&gt;BasicPrinter&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Implementação da interface &lt;code&gt;Printable&lt;/code&gt; na struct &lt;code&gt;BasicPrinter&lt;/code&gt; ao criar a &lt;code&gt;func&lt;/code&gt; que é um método &lt;code&gt;Print()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Obs:&lt;/strong&gt; Esses vínculos acontecem de forma implícita em Go.&lt;/p&gt;

&lt;p&gt;A seguir, apresento outro exemplo em &lt;strong&gt;Elixir&lt;/strong&gt; que reproduz a mesma ideia. A diferença é que a linguagem permite retornar tipos genéricos, o que implica implementar esses comportamentos em outros módulos sem necessariamente devolver o mesmo tipo de dado.&lt;/p&gt;

&lt;p&gt;Em &lt;strong&gt;Elixir&lt;/strong&gt;, a implementação de uma “interface” recebe o nome de &lt;strong&gt;behavior&lt;/strong&gt; ou &lt;strong&gt;callback&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MultiFunctionDevice&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@callback&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nv"&gt;@callback&lt;/span&gt; &lt;span class="n"&gt;fax&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nv"&gt;@callback&lt;/span&gt; &lt;span class="n"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;SimplePrinter&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@behaviour&lt;/span&gt; &lt;span class="no"&gt;MultiFunctionDevice&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Printing"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;fax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="ss"&gt;:not_implemented&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="ss"&gt;:not_implemented&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A mesma ideia se aplica aqui. Mesmo que a função seja implementada, o retorno é &lt;code&gt;:not_implemented&lt;/code&gt;. Devolver &lt;code&gt;:not_implemented&lt;/code&gt; ou criar funções vazias é um baita sinal de que a interface foi mal pensada e está quebrando o princípio, mesmo respeitando a assinatura das funções da interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;PrinterOnly&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@callback&lt;/span&gt; &lt;span class="n"&gt;print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;::&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;A abordagem é a mesma, dividir a interface outras específicas.&lt;/p&gt;
&lt;/blockquote&gt;




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

&lt;p&gt;Não existe mistério quando falamos de interfaces. O ISP defende a divisão de grandes interfaces em contextos menores e mais coesos, algo que vale em várias situações como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Herança entre objetos&lt;/li&gt;
&lt;li&gt;Interações com contextos externos (cache, message broker, banco de dados)&lt;/li&gt;
&lt;li&gt;Erro handling estruturado&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Com isso a gente ganha:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Redução no acoplamento&lt;/li&gt;
&lt;li&gt;Código mais coeso&lt;/li&gt;
&lt;li&gt;Código mais flexível a mudanças&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Código de Referência
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Exemplos em Elixir: &lt;a href="https://github.com/rafael-hs/solid_elixir_examples" rel="noopener noreferrer"&gt;solid_elixir_examples&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Exemplos em Go: &lt;a href="https://github.com/rafael-hs/solid-go-examples" rel="noopener noreferrer"&gt;solid-go-examples&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Espero que tenha ficado claro os conceitos, se caso ficou alguma dúvida, fique a vontade para deixar um comentário.&lt;/p&gt;

</description>
      <category>solidprinciples</category>
      <category>isp</category>
      <category>interfacesegregation</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>Understanding SOLID once and for all | Part 03 - (LSP)</title>
      <dc:creator>Rafael Honório</dc:creator>
      <pubDate>Tue, 22 Jul 2025 02:50:05 +0000</pubDate>
      <link>https://forem.com/rafahs/understanding-solid-once-and-for-all-part-03-lsp-4hml</link>
      <guid>https://forem.com/rafahs/understanding-solid-once-and-for-all-part-03-lsp-4hml</guid>
      <description>&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;Hey everyone, how’s it going? This is the third post of the series where I’m sharing my experience with SOLID. In this article, we’re going to understand a bit more about the Liskov Substitution Principle (LSP) and see some examples.&lt;/p&gt;

&lt;p&gt;This might be the hardest concept to understand, but I’ll try to explain it in a simple way to make everything clear.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;This concept was created by Barbara Liskov and Jeannette Wingin 1994 in a paper called "A Behavioral Notion of Subtyping" and the definition says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Subtypes must be replaceable for their base types without affecting the correctness of the program.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In short, you should be able to replace a base type with its subtype, since the subtype has all the characteristics of the base type, and this shouldn't break the current flow.&lt;/p&gt;




&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;Imagine the following situation: we have two classes. A parent class with some properties and methods, and a child class that extends it. If we try to replace the parent class with the child class somewhere in the code, everything should work fine. Here's an example in the image:&lt;/p&gt;

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

&lt;p&gt;The example shows a function that saves the information. In theory, it works because the type substitution doesn’t affect how the code behaves. It respects the contract, whether we’re using inheritance or interface.&lt;/p&gt;

&lt;p&gt;LSP says that objects of the child class should be usable in place of objects of the parent class without changing the correct behavior of the program. Let’s check that in the example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Parent Class Contract:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The parent class defines properties &lt;code&gt;xpto_01&lt;/code&gt; and &lt;code&gt;xpto_02&lt;/code&gt;. The function &lt;code&gt;save_parent()&lt;/code&gt; depends on these methods to work correctly.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Child Class Behavior:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The child class inherits &lt;code&gt;xpto_01&lt;/code&gt; and &lt;code&gt;xpto_02&lt;/code&gt; and adds a new one: &lt;code&gt;xpto_03&lt;/code&gt;. If the &lt;code&gt;save_parent()&lt;/code&gt; function doesn’t use &lt;code&gt;xpto_03&lt;/code&gt;, and the other two properties are implemented in the same way, then it’s all good.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Substitution in Function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;save_parent()&lt;/code&gt; only uses &lt;code&gt;xpto_01&lt;/code&gt; and &lt;code&gt;xpto_02&lt;/code&gt;, and the child class implements them correctly, the substitution works. The new method &lt;code&gt;xpto_03&lt;/code&gt; doesn’t affect the contract.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  LSP in practice
&lt;/h2&gt;

&lt;p&gt;Now let’s look at a Go example with the same idea:&lt;/p&gt;

&lt;p&gt;In this case, we have an interface called &lt;code&gt;Salvable&lt;/code&gt; that defines a contract for saving data. A struct &lt;code&gt;User&lt;/code&gt; (like the parent class) and a struct &lt;code&gt;PremiumUser&lt;/code&gt; (like the child class) both implement this interface. The child struct has an extra field.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="c"&gt;// Salvable interface defines the base contract&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Salvable&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Save&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="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Age&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// User implements the Salvable interface&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&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;Save&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Saving user: Name=%s, Age=%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&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;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// PremiumUser extends User behavior&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;PremiumUser&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;User&lt;/span&gt;
    &lt;span class="n"&gt;PremiumLevel&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pu&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;PremiumUser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Save&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="c"&gt;// Keeps the contract, adding extra info&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Saving premium user: Name=%s, Age=%d, PremiumLevel=%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pu&lt;/span&gt;&lt;span class="o"&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;pu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PremiumLevel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Function that uses the Salvable interface&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;SaveProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;Salvable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&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="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Jonas"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Age&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;premiumUser&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;PremiumUser&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&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="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Mary"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Age&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;25&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;PremiumLevel&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processing User:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;SaveProcess&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;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processing PremiumUser:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;SaveProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;premiumUser&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;Expected output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Processing User:
Saving user: Name=Jonas, Age=30
Processing PremiumUser:
Saving premium user: Name=Mary, Idade=25, PremiumLevel=3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But what happens if we break the LSP?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Salvable&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Save&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="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Age&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&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;Save&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Saving user: Name=%s, Age=%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&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;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;PremiumUser&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;User&lt;/span&gt;
    &lt;span class="n"&gt;PremiumLevel&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pu&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;PremiumUser&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Save&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="c"&gt;// Restriction: only save if PremiumLevel &amp;gt; 0&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;pu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PremiumLevel&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Error: Invalid PremiumLevel"&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;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Saving premium user: Name=%s, Age=%d, PremiumLevel=%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pu&lt;/span&gt;&lt;span class="o"&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;pu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PremiumLevel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;SaveProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;Salvable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&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="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Jonas"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Age&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;premiumUser&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;PremiumUser&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="o"&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="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Mary"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Age&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;25&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;PremiumLevel&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processing User:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;SaveProcess&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;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processing PremiumUser:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;SaveProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;premiumUser&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;Expected output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Processing User:
Saving user: Name=Jonas, Age=30
Processing PremiumUser:
Error:: Invalid PremiumLevel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;In this case, we have some problems&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;PremiumUser&lt;/code&gt; class adds a restriction (&lt;code&gt;PremiumLevel &amp;gt; 0&lt;/code&gt;) that doesn’t exist in &lt;code&gt;Salvable&lt;/code&gt; or in &lt;code&gt;User&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;SaveProcess&lt;/code&gt; function expects &lt;code&gt;Save()&lt;/code&gt; to always return a success message, but now it can return an error.&lt;/li&gt;
&lt;li&gt;This breaks the LSP because replacing &lt;code&gt;Salvable&lt;/code&gt; with &lt;code&gt;PremiumUser&lt;/code&gt; changes the expected behavior by adding a condition that doesn’t exist in the contract.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In general, this principle helps us reflect on how modules implement behaviors like &lt;strong&gt;methods&lt;/strong&gt;, &lt;strong&gt;callbacks&lt;/strong&gt;, or &lt;strong&gt;interfaces&lt;/strong&gt;. If you need to “force” an implementation just to respect a contract, or change how a method behaves in a subtype, or if replacing types breaks your system, that’s a strong sign the LSP is being violated.&lt;/p&gt;

&lt;p&gt;That’s it for now! If you have any questions, leave them in the comments. See you in the next one!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Elixir examples: &lt;a href="https://github.com/rafael-hs/solid_elixir_examples" rel="noopener noreferrer"&gt;solid_elixir_examples&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Go examples: &lt;a href="https://github.com/rafael-hs/solid-go-examples" rel="noopener noreferrer"&gt;solid-go-examples&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>solidprinciples</category>
      <category>programming</category>
      <category>lsp</category>
      <category>liskov</category>
    </item>
    <item>
      <title>Entendendo SOLID de uma vez por todas | Parte 03 - (LSP)</title>
      <dc:creator>Rafael Honório</dc:creator>
      <pubDate>Mon, 21 Jul 2025 23:57:33 +0000</pubDate>
      <link>https://forem.com/rafahs/entendendo-solid-de-uma-vez-por-todas-parte-03-lsp-31fb</link>
      <guid>https://forem.com/rafahs/entendendo-solid-de-uma-vez-por-todas-parte-03-lsp-31fb</guid>
      <description>&lt;h2&gt;
  
  
  Motivação
&lt;/h2&gt;

&lt;p&gt;Fala pessoal de boas? esse é o terceito texto da série que estou compartilhando minha experiência com &lt;strong&gt;SOLID&lt;/strong&gt;. neste artigo, vamos entender um pouco melhor &lt;strong&gt;Liskov Substitution Principle (LSP)&lt;/strong&gt; e ver alguns exemplos.&lt;/p&gt;

&lt;p&gt;Talvez esse seja o conceito mais difícil de entender, mas vou tentar exemplificar da forma mais simples possível para não deixar dúvidas de quanto a aplicação.&lt;/p&gt;




&lt;h2&gt;
  
  
  Breve resumo
&lt;/h2&gt;

&lt;p&gt;Esse conceito foi cunhado pela Barbara Liskov e Jeannette Wing em 94 em um artigo chamado "A Behavioral Notion of Subtyping" e a definição diz:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Subtipos devem poder ser usados no lugar de seus tipos base, sem alterar a correção do programa.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Em tese, você deve conseguir substituir um &lt;strong&gt;tipo base&lt;/strong&gt; pelo &lt;strong&gt;subtipo&lt;/strong&gt; dado que, o &lt;strong&gt;subtipo&lt;/strong&gt; contêm todas as caracteristicas do &lt;strong&gt;tipo base&lt;/strong&gt;, e isso não deve quebrar o fluxo atual.&lt;/p&gt;




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

&lt;p&gt;Imagine a seguinte situção, existem duas classes, uma classe pai que tem propriedades e metódos, a classe filha implementa a classe pai, se caso a gente fosse substituir a classe pai pela filha em alguma implementacão, nosso código não deveria quebrar, segue o exemplo em imagem:&lt;/p&gt;

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

&lt;p&gt;No exemplo mostra uma função que salva essas informações e em tese, a função funcionaria por que a substituição dos tipos não influenciaria no comportamento interno visto que respeita o contrato se considerar a herança ou interface.&lt;/p&gt;

&lt;p&gt;O LSP exige que objetos da classe filha possam substituir objetos da classe pai sem alterar o comportamento correto do programa. Vamos verificar se isso é válido no exemplo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Contrato da Classe Pai&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;A classe pai define as propriedades  &lt;code&gt;xpto_01&lt;/code&gt; e &lt;code&gt;xpto_02&lt;/code&gt;. A função &lt;code&gt;save_pai()&lt;/code&gt; depende desses métodos ou atributos para funcionar corretamente.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Comportamento da Classe Filha&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;A classe filha herda &lt;code&gt;xpto_01&lt;/code&gt; e &lt;code&gt;xpto_02&lt;/code&gt; e adiciona &lt;strong&gt;xpto_03&lt;/strong&gt;. Se &lt;strong&gt;xpto_03&lt;/strong&gt; não for chamado pela função &lt;code&gt;save_pai()&lt;/code&gt; (ou seja, a função só usa &lt;code&gt;xpto_01&lt;/code&gt; e &lt;code&gt;xpto_02&lt;/code&gt;), a substituição da classe pai pela filha não deve causar problemas, desde que a implementação de &lt;code&gt;xpto_01&lt;/code&gt; e &lt;code&gt;xpto_02&lt;/code&gt; na filha seja consistente com a do pai.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Substituição na Função&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Se &lt;code&gt;save_pai()&lt;/code&gt; for projetada para trabalhar apenas com os atributos ou métodos da classe pai (&lt;code&gt;xpto_01&lt;/code&gt; e &lt;code&gt;xpto_02&lt;/code&gt;), e a classe filha os implementa da mesma forma, a substituição funciona. A adição de &lt;code&gt;xpto_03&lt;/code&gt; não afeta o contrato, pois a função não depende dele.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  LSP na prática
&lt;/h2&gt;

&lt;p&gt;Vamos seguir para um exemplo em Golang seguindo a mesma linha de raciocinio:&lt;/p&gt;

&lt;p&gt;Neste exemplo, temos umas interface &lt;code&gt;Salvavel&lt;/code&gt; que define um contrato para salvar dados. Umas struct &lt;code&gt;Usuario&lt;/code&gt; (equivalente à classe pai) e uma struct &lt;code&gt;UsuarioPremium&lt;/code&gt; (equivalente à classe filha) implementam essa interface, adicionando uma propriedade extra na filha.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="c"&gt;// Interface Salvavel define o contrato base&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Salvavel&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Salvar&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="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Usuario&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Nome&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Idade&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Usuario implementa a interface Salvavel&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Usuario&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Salvar&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Salvando usuario: Nome=%s, Idade=%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Nome&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Idade&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// UsuarioPremium estende o comportamento do Usuario&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;UsuarioPremium&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Usuario&lt;/span&gt;
    &lt;span class="n"&gt;NivelPremium&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;UsuarioPremium&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Salvar&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="c"&gt;// Mantém o contrato da interface, adicionando informações extras&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Salvando usuario premium: Nome=%s, Idade=%d, NivelPremium=%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Nome&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Idade&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NivelPremium&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Função que usa a interface Salvavel (equivalente à "save_pai")&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;ProcessarSalvar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;Salvavel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;resultado&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Salvar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&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;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Instâncias&lt;/span&gt;
    &lt;span class="n"&gt;usuario&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Usuario&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Nome&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"João"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Idade&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;usuarioPremium&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;UsuarioPremium&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Usuario&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Usuario&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Nome&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Maria"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Idade&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;25&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;NivelPremium&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Testando substituição&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processando Usuario:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ProcessarSalvar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;usuario&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Funciona como esperado&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processando UsuarioPremium:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ProcessarSalvar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;usuarioPremium&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Também funciona, respeitando o LSP&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;saída esperada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Processando Usuario:
Salvando usuario: Nome=João, Idade=30
Processando UsuarioPremium:
Salvando usuario premium: Nome=Maria, Idade=25, NivelPremium=3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;e se caso a gente violasse o LSP?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="c"&gt;// Interface Salvavel define o contrato base&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Salvavel&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Salvar&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="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Usuario&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Nome&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Idade&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Usuario implementa a interface Salvavel&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Usuario&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Salvar&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Salvando usuario: Nome=%s, Idade=%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Nome&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Idade&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// UsuarioPremium com restrição&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;UsuarioPremium&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Usuario&lt;/span&gt;
    &lt;span class="n"&gt;NivelPremium&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;UsuarioPremium&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Salvar&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="c"&gt;// Restrição: só salva se NivelPremium &amp;gt; 0&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NivelPremium&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"Erro: NivelPremium inválido"&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;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Salvando usuario premium: Nome=%s, Idade=%d, NivelPremium=%d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Nome&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Idade&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NivelPremium&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Função que usa a interface Salvavel&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;ProcessarSalvar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;Salvavel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;resultado&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Salvar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&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;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;usuario&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Usuario&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Nome&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"João"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Idade&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;usuarioPremium&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;UsuarioPremium&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Usuario&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Usuario&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Nome&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Maria"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Idade&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;25&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;NivelPremium&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processando Usuario:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ProcessarSalvar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;usuario&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Funciona: "Salvando usuario: Nome=João, Idade=30"&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processando UsuarioPremium:"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ProcessarSalvar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;usuarioPremium&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Quebra o comportamento esperado: "Erro: NivelPremium inválido"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;saída esperada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Processando Usuario:
Salvando usuario: Nome=João, Idade=30
Processando UsuarioPremium:
Erro: NivelPremium inválido
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Nesse caso acontece algumas situações não tão legais&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A classe &lt;code&gt;UsuarioPremium&lt;/code&gt; adiciona uma restrição (&lt;code&gt;NivelPremium &amp;gt; 0&lt;/code&gt;) que não existe na interface Salvavel nem em um Usuario.&lt;/li&gt;
&lt;li&gt;A função &lt;code&gt;ProcessarSalvar&lt;/code&gt; espera que &lt;code&gt;Salvar()&lt;/code&gt; sempre retorne uma string de sucesso (com dados salvos), mas &lt;code&gt;UsuarioPremium&lt;/code&gt; pode retornar um erro, quebrando o contrato implícito.&lt;/li&gt;
&lt;li&gt;Isso viola o LSP porque a substituição de &lt;code&gt;Salvavel&lt;/code&gt; por &lt;code&gt;UsuarioPremium&lt;/code&gt; altera o comportamento esperado, introduzindo uma pré-condição que a interface não define.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;No geral, esse princípio nos faz refletir sobre como os módulos estão implementando comportamentos, como &lt;strong&gt;métodos&lt;/strong&gt;, &lt;strong&gt;callbacks&lt;/strong&gt; e &lt;strong&gt;behaviors&lt;/strong&gt;. Se for preciso "forçar" alguma implementação apenas para cumprir um contrato, alterar o retorno do contrato no subtipo, ou se a substituição de tipos acaba quebrando o funcionamento do sistema, é um sinal claro de que o LSP está sendo violado.&lt;/p&gt;

&lt;p&gt;No mais é isso, qualquer dúvida deixe nos comentários, nos vemos na próxima!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exemplos em Elixir: &lt;a href="https://github.com/rafael-hs/solid_elixir_examples" rel="noopener noreferrer"&gt;solid_elixir_examples&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Exemplos em Go: &lt;a href="https://github.com/rafael-hs/solid-go-examples" rel="noopener noreferrer"&gt;solid-go-examples&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>solidprinciples</category>
      <category>programming</category>
      <category>lsp</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>Understanding SOLID once and for all | Part 02 - (OCP)</title>
      <dc:creator>Rafael Honório</dc:creator>
      <pubDate>Wed, 16 Jul 2025 22:17:11 +0000</pubDate>
      <link>https://forem.com/rafahs/understanding-solid-once-and-for-all-part-02-ocp-1llc</link>
      <guid>https://forem.com/rafahs/understanding-solid-once-and-for-all-part-02-ocp-1llc</guid>
      <description>&lt;h2&gt;
  
  
  Motivation
&lt;/h2&gt;

&lt;p&gt;Hey folks, how’s it going?&lt;/p&gt;

&lt;p&gt;This is the second post in the series where I’m sharing my real-world experience with &lt;strong&gt;SOLID&lt;/strong&gt; principles in a straightforward and down-to-earth way. In the &lt;a href="https://dev.to/rafahs/understanding-solid-once-and-for-all-part-01-2bab"&gt;first post&lt;/a&gt;, I talked about SRP and showed how small violations can make code maintenance harder. If you haven’t seen it yet, go check it out!&lt;/p&gt;

&lt;p&gt;Today, we’re taking a step further with the Open–Closed Principle (OCP), the pillar that teaches us how to extend behavior without modifying what's already working.&lt;/p&gt;




&lt;h2&gt;
  
  
  Brief Overview
&lt;/h2&gt;

&lt;p&gt;This term was coined by &lt;strong&gt;Bertrand Meyer&lt;/strong&gt; in 1988 and popularized by &lt;strong&gt;Robert C. Martin&lt;/strong&gt; (Uncle Bob). OCP is usually summarized by the phrase:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Software entities should be open for extension, but closed for modification.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At first glance, it seems paradoxical how something can be open for extension and closed for modification at the same time? The secret lies in one word: &lt;strong&gt;abstractions&lt;/strong&gt; (interfaces, behaviours, callbacks).&lt;/p&gt;

&lt;p&gt;As systems grow larger, both in file size and complexity, it becomes essential to use abstractions to expand behavior without changing the core implementation. In other words, the base code “never changes.”&lt;/p&gt;

&lt;h3&gt;
  
  
  Example – &lt;strong&gt;A function that calculates tax on a product&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Can the calculation change? Yes, but it's unlikely.&lt;/li&gt;
&lt;li&gt;What are the variables? &lt;strong&gt;Product value&lt;/strong&gt; + &lt;strong&gt;Tax rate&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Which of these might change? &lt;strong&gt;Tax rate&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are the types of questions I ask myself to identify &lt;strong&gt;variation points&lt;/strong&gt; in the implementation. In this case, the &lt;em&gt;how to calculate&lt;/em&gt; is unlikely to change, but the tax rate might.&lt;/p&gt;

&lt;p&gt;Here's a typical implementation of such a calculation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function calculate(price), do:
  price * @tax_rate or 0.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The pseudo-code above is a simple and direct implementation. However, it has a downside: every time the tax rate changes, we have to modify the function, which can cause unintended issues elsewhere in the system.&lt;/p&gt;

&lt;p&gt;Now, imagine we did this instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function calculate_tax(price, tax_function), do:
  tax_function(price)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, we don’t need to change the core logic when requirements change. We pass a function as a parameter to calculate the new value. This allows us to implement new features through new modules or classes without touching already-tested code, thus expanding functionality safely.&lt;/p&gt;




&lt;h2&gt;
  
  
  OCP in Practice
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Discount Strategy in Go
&lt;/h3&gt;

&lt;p&gt;Excerpt from the &lt;code&gt;solid-go-examples&lt;/code&gt; repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Interface that defines the variation point&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Discount&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// No discount implementation&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;NoDiscount&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NoDiscount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt; &lt;span class="p"&gt;{&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="c"&gt;// Percentage discount implementation&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;PercentageDiscount&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PercentageDiscount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;float64&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;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Core function that doesn’t change when new discounts are added&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;CalculatePrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="n"&gt;Discount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;float64&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;price&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Apply&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usage in &lt;code&gt;main.go&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;noDisc&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;NoDiscount&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="n"&gt;percentageDisc&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;PercentageDiscount&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CalculatePrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;noDisc&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c"&gt;// 100&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CalculatePrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;percentageDisc&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c"&gt;// 90&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why does this follow OCP?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CalculatePrice&lt;/code&gt; is &lt;strong&gt;closed&lt;/strong&gt; for modification—we didn’t touch it to add &lt;code&gt;PercentageDiscount&lt;/code&gt;. At the same time, the system is &lt;strong&gt;open&lt;/strong&gt; for extension because we can add new types that implement &lt;code&gt;Discount&lt;/code&gt; (e.g., &lt;em&gt;BlackFridayDiscount&lt;/em&gt;) at any time.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Payment Processor in Elixir
&lt;/h3&gt;

&lt;p&gt;File: &lt;code&gt;02_open_closed_principle.ex&lt;/code&gt; from the &lt;a href="https://github.com/rafael-hs/solid_elixir_examples" rel="noopener noreferrer"&gt;&lt;code&gt;solid_elixir_examples&lt;/code&gt;&lt;/a&gt; repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;PaymentProcessor&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;process&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;tax_calculator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;tax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tax_calculator&lt;/span&gt;&lt;span class="o"&gt;.&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;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;tax&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;order:&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;tax:&lt;/span&gt; &lt;span class="n"&gt;tax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;total:&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Different tax rules without changing the module&lt;/span&gt;
&lt;span class="no"&gt;PaymentProcessor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;amount:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;PaymentProcessor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;amount:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt; &lt;span class="k"&gt;end&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;Why does this follow OCP?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;PaymentProcessor&lt;/code&gt; delegates tax calculation to a &lt;em&gt;function&lt;/em&gt; received as a parameter. When a new regulation appears, we just create another function (or module) and pass it in—no need to touch the processing logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tips for Adopting OCP
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Changing Situation&lt;/th&gt;
&lt;th&gt;OCP-Friendly Approach&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;New payment methods&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Define a &lt;code&gt;PaymentGateway&lt;/code&gt; interface and implement new adapters without altering existing ones.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;New pricing rules&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Use &lt;em&gt;callback functions&lt;/em&gt; or the &lt;em&gt;strategy pattern&lt;/em&gt; to encapsulate logic—this improves maintainability and testability.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;New reports&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Apply the &lt;em&gt;Template Method&lt;/em&gt; pattern or use &lt;em&gt;plug-ins&lt;/em&gt; to generate reports instead of editing the base class.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Golden tip:&lt;/strong&gt; Find the variation point in your code—this is usually the part that needs to be encapsulated.&lt;/p&gt;

&lt;h3&gt;
  
  
  Signs of OCP Violation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Growing &lt;code&gt;switch/case&lt;/code&gt; blocks whenever new data types appear.&lt;/li&gt;
&lt;li&gt;Tests breaking in a cascade when only one requirement changes.&lt;/li&gt;
&lt;li&gt;Constant changes in the core domain (more internal rule changes = greater need for OCP).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Applying the Open–Closed Principle isn’t about “never touching code again.” It’s about &lt;strong&gt;minimizing high-risk changes&lt;/strong&gt; and &lt;strong&gt;isolating variability&lt;/strong&gt;. The clearer the boundary between &lt;em&gt;core&lt;/em&gt; and &lt;em&gt;extensions&lt;/em&gt;, the safer and faster it will be to evolve the system.&lt;/p&gt;

&lt;p&gt;In the next article, we’ll explore the &lt;strong&gt;Liskov Substitution Principle (LSP)&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
Meanwhile, check out the full repositories with examples in &lt;strong&gt;Elixir&lt;/strong&gt; and &lt;strong&gt;Go&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Elixir Example: &lt;a href="https://github.com/rafael-hs/solid_elixir_examples" rel="noopener noreferrer"&gt;solid_elixir_examples&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Go Example: &lt;a href="https://github.com/rafael-hs/solid-go-examples" rel="noopener noreferrer"&gt;solid-go-examples&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Still have questions? Or maybe you disagree with something? Drop a comment!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>solidprinciples</category>
      <category>cleancode</category>
      <category>ocp</category>
    </item>
    <item>
      <title>Entendendo SOLID de uma vez por todas | Parte 02 - (OCP)</title>
      <dc:creator>Rafael Honório</dc:creator>
      <pubDate>Wed, 16 Jul 2025 21:57:11 +0000</pubDate>
      <link>https://forem.com/rafahs/entendendo-solid-de-uma-vez-por-todas-pt-02-ocp-2el</link>
      <guid>https://forem.com/rafahs/entendendo-solid-de-uma-vez-por-todas-pt-02-ocp-2el</guid>
      <description>&lt;h2&gt;
  
  
  Motivação
&lt;/h2&gt;

&lt;p&gt;Fala pessoal tranquilo? esse é o segundo texto da série que estou compartilhando minha experiência de forma direta e “pé-no-chão” sobre &lt;strong&gt;SOLID&lt;/strong&gt;. No &lt;a href="https://dev.to/rafahs/entendendo-solid-de-uma-vez-por-todas-pt-01-3pi"&gt;primeiro texto&lt;/a&gt; eu falei sobre SRP e mostrei como pequenas violações atrapalham a manutenção do código, se caso não viu, da uma passada lá! &lt;/p&gt;

&lt;p&gt;Hoje vamos dar um passo adiante com o Open–Closed Principle (OCP), o pilar que nos ensina a estender comportamentos sem modificar o que já está funcionando.&lt;/p&gt;




&lt;h2&gt;
  
  
  Breve resumo
&lt;/h2&gt;

&lt;p&gt;Esse termo foi cunhado por &lt;strong&gt;Bertrand Meyer&lt;/strong&gt; em 1988 e popularizado por &lt;strong&gt;Robert C. Martin&lt;/strong&gt; (Uncle Bob), o OCP é geralmente resumido na frase:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Entidades de software devem ser abertas para extensão e fechadas para modificação.” &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A ideia parece paradoxal, como algo pode ser aberto para extensões e fechado para modificações? O segredo é uma palavrinha: &lt;strong&gt;abstrações&lt;/strong&gt; (interfaces, behaviours, callbacks).&lt;/p&gt;

&lt;p&gt;Conforme os sistemas se tornaram maiores em termos de tamanho dos arquivos, numero de arquivos e relação entre eles, se faz necessário utilizar abstrações para expandir os contextos a ponto de que, não é preciso mexer na implementação raiz para adicionar uma modificação, em outras palavras, "ela nunca muda".&lt;/p&gt;

&lt;p&gt;Por exemplo - &lt;strong&gt;Uma função que calcula um determinado imposto sobre um produto&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O cálculo pode mudar? sim, mas é improvável que mude &lt;/li&gt;
&lt;li&gt;Quais são as variáveis? valor do &lt;strong&gt;produto&lt;/strong&gt; + &lt;strong&gt;alíquota&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Quais são as variáveis que podem mudar? &lt;strong&gt;alíquota&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;São exemplos de perguntas que eu me faço para descobrir o &lt;strong&gt;ponto de variação&lt;/strong&gt; da implementação, nesse caso é improvável que o "como fazer" mude, mas é provável que alíquota mude com o tempo.&lt;/p&gt;

&lt;p&gt;Pensando em como normalmente se implementaria um calculo assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;função fazer_calculo(valor_do_produto), faça:
  valor_do_produto * @aliquota_imposto ou 0.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O pseudocódigo acima mostra uma implementação simples e direta de como fazer esse processo, porém existe um problema que é, toda vez que o imposto mudar a gente vai precisar modificar essa função e isso pode gerar problemas em outras pontas do software.&lt;/p&gt;

&lt;p&gt;Se invês do código acima, fizessemos isso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;função calcular_aliquota(valor_do_produto, calculo_imposto), faça:
  calculo_imposto(valor_do_produto)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nesse caso não seria necessário modificar essa implementação quando algo mudasse, visto que, estamos passando uma outra função como parâmetro para calcular o novo valor, assim quando adicionarmos novos recursos implementando classes/módulos, não precisamos alterar os contextos já testados no passado, dessa forma expandindo as implementações.&lt;/p&gt;

&lt;h2&gt;
  
  
  OCP na prática
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Estratégia de desconto em Go.
&lt;/h3&gt;

&lt;p&gt;Trecho retirado do repositório solid-go-examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// interface que define o ponto de variação&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Discount&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// implementação sem desconto&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;NoDiscount&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NoDiscount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt; &lt;span class="p"&gt;{&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="c"&gt;// implementação com desconto percentual&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;PercentageDiscount&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PercentageDiscount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;float64&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;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;0.1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Função de domínio que não muda quando surgem novos descontos&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;CalculatePrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="n"&gt;Discount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;float64&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;price&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Apply&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uso no main.go:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;noDisc&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;NoDiscount&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="n"&gt;percentageDisc&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;PercentageDiscount&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CalculatePrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;noDisc&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c"&gt;// 100&lt;/span&gt;
&lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CalculatePrice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;percentageDisc&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c"&gt;// 90&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Por que segue o OCP?&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;&lt;code&gt;CalculatePrice&lt;/code&gt; é &lt;strong&gt;fechada&lt;/strong&gt; para modificação: não precisei tocar nela para incluir &lt;code&gt;PercentageDiscount&lt;/code&gt;. Ao mesmo tempo, o sistema está &lt;strong&gt;aberto&lt;/strong&gt; para extensão, pois novos tipos que implementem &lt;code&gt;Discount&lt;/code&gt; podem ser criados a qualquer momento (ex: &lt;em&gt;BlackFridayDiscount&lt;/em&gt;).&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Processador de pagamento em Elixir.
&lt;/h3&gt;

&lt;p&gt;Arquivo &lt;code&gt;02_open_closed_principle.ex&lt;/code&gt; do repo &lt;a href="https://github.com/rafael-hs/solid_elixir_examples" rel="noopener noreferrer"&gt;&lt;code&gt;solid_elixir_examples&lt;/code&gt;&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;PaymentProcessor&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;process&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;tax_calculator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;tax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tax_calculator&lt;/span&gt;&lt;span class="o"&gt;.&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;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;tax&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;order:&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;tax:&lt;/span&gt; &lt;span class="n"&gt;tax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;total:&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# diferentes regras fiscais sem alterar o módulo&lt;/span&gt;
&lt;span class="no"&gt;PaymentProcessor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;amount:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;PaymentProcessor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;&lt;span class="ss"&gt;amount:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt; &lt;span class="k"&gt;end&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;Por que segue o OCP?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;PaymentProcessor&lt;/code&gt; delega o cálculo de imposto para uma &lt;em&gt;função&lt;/em&gt; recebida por parâmetro. Quando surge uma nova legislação, criamos outra função (ou módulo) e passamos como argumento, sem tocar na lógica central de processamento.&lt;/p&gt;




&lt;h2&gt;
  
  
  Dicas para adotar o OCP
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situação de mudança&lt;/th&gt;
&lt;th&gt;Abordagem que respeita o OCP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Novos meios de pagamento&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Defina uma interface &lt;code&gt;PaymentGateway&lt;/code&gt; e implemente novos adaptadores sem alterar o que já existe.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Novas regras de tarifação&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Use funções de &lt;em&gt;callback&lt;/em&gt; ou &lt;em&gt;strategy pattern&lt;/em&gt; para encapsular regras isso vai ajudar na manutenibilidade do código e testes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Novos relatórios&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Aplique o pattern &lt;em&gt;Template Method&lt;/em&gt; ou gere relatórios via &lt;em&gt;plug-ins&lt;/em&gt; em vez de editar a classe base.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Dica de ouro:&lt;/strong&gt; encontre o ponto de variação do código, provávelmente esse é o ponto que precisa ser encapsulado.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sinais de violação
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;switch/case&lt;/code&gt; crescendo sempre que aparece um novo tipo de dado.&lt;/li&gt;
&lt;li&gt;Testes que quebram em cascata quando apenas um requisito mudou.&lt;/li&gt;
&lt;li&gt;Mudança constante no domínio interno (quanto mais mudanças em regras internamente tiver mais se faz necessário aplicar esse conceito).&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Aplicar o Open–Closed Principle não é sobre “nunca mais mexer” no código, mas sim sobre &lt;strong&gt;minimizar mudanças de alto risco&lt;/strong&gt; e &lt;strong&gt;isolar variabilidade&lt;/strong&gt;. Quanto mais clara for a fronteira entre &lt;em&gt;núcleo&lt;/em&gt; e &lt;em&gt;extensões&lt;/em&gt;, mais rápido e seguro será evoluir o sistema.&lt;/p&gt;

&lt;p&gt;No próximo artigo vamos explorar o &lt;strong&gt;Liskov Substitution Principle (LSP)&lt;/strong&gt;. Enquanto isso, confira os repositórios completos com exemplos em &lt;strong&gt;Elixir&lt;/strong&gt; e &lt;strong&gt;Go&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exemplo em Elixir: &lt;a href="https://github.com/rafael-hs/solid_elixir_examples" rel="noopener noreferrer"&gt;solid_elixir_examples&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Exemplo em Go: &lt;a href="https://github.com/rafael-hs/solid-go-examples" rel="noopener noreferrer"&gt;solid-go-examples&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se ainda houver dúvidas ou se você discordar de algo, deixe um comentário!&lt;/p&gt;

</description>
      <category>solidprinciples</category>
      <category>programming</category>
      <category>ocp</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>Entendendo SOLID de uma vez por todas | Parte 01 - (SRP)</title>
      <dc:creator>Rafael Honório</dc:creator>
      <pubDate>Sun, 29 Jun 2025 21:57:50 +0000</pubDate>
      <link>https://forem.com/rafahs/entendendo-solid-de-uma-vez-por-todas-pt-01-3pi</link>
      <guid>https://forem.com/rafahs/entendendo-solid-de-uma-vez-por-todas-pt-01-3pi</guid>
      <description>&lt;h1&gt;
  
  
  Motivação
&lt;/h1&gt;

&lt;p&gt;Este é o primeiro texto de uma série onde explicarei, de maneira clara e lúdica, cada um dos conceitos do SOLID. Em vez de replicar conteúdos já disponíveis pela internet, pretendo fazer um dump das minhas experiências pessoais e do meu entendimento sobre o tema. Hoje, iniciaremos com o princípio SRP (Single Responsibility Principle).&lt;/p&gt;

&lt;h1&gt;
  
  
  Breve resumo
&lt;/h1&gt;

&lt;p&gt;Os conceitos que formam o acrônimo SOLID já são bem conhecidos há pelo menos 20 anos e são frequentemente abordados em entrevistas técnicas. Mais do que isso, entender profundamente cada princípio melhorará significativamente a qualidade do seu código. A intenção destes textos é esclarecer definitivamente cada conceito para que você consiga aplicá-los independentemente da linguagem que utilizar.&lt;/p&gt;

&lt;p&gt;Obs.: No final do texto, vou deixar dois repositórios com exemplos práticos implementando cada conceito em Elixir e Golang, contudo, o mais importante é compreender o fundamento para que você consiga adaptá-lo à sua realidade.&lt;/p&gt;

&lt;h1&gt;
  
  
  SRP - Single Responsibility Principle
&lt;/h1&gt;

&lt;p&gt;Esse termo foi cunhado por Robert Martin (Uncle Bob) em 2000, no livro Design Principles and Design Patterns. Porém, esse é um problema clássico da programação, que surgiu após os anos 80 com o aumento da complexidade das aplicações. Com a complexidade crescendo, tornou-se necessário organizar melhor o código, o que impulsionou a implementação de &lt;a href="https://pt.wikipedia.org/wiki/Programa%C3%A7%C3%A3o_orientada_a_objetos" rel="noopener noreferrer"&gt;POO&lt;/a&gt; no mercado, visto que já existia pelo menos há 20 anos na década de 80/90.&lt;/p&gt;

&lt;p&gt;Segundo o livro Clean Code, o conceito de SRP pode ser resumido da seguinte maneira:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Uma classe ou módulo deve ter um, e apenas um, motivo para mudar." (&lt;em&gt;Clean Code&lt;/em&gt;, pág. 138)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Mas, afinal, o que isso significa? Dentro de uma estrutura, seja ela um módulo, pacote ou classe, qualquer interação que fuja da sua responsabilidade original provavelmente violará o SRP.&lt;/p&gt;

&lt;p&gt;Veja estes dois exemplos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Situação 01: Dentro de uma estrutura de usuário, existem propriedades e métodos que devem sempre refletir ações e características diretamente relacionadas ao usuário. Exemplo:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt;     &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Age&lt;/span&gt;      &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;Document&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="c"&gt;// outras propriedades&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Em Go, este trecho "(u *User)" indica que esta função é um método da struct User.&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&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;IsAdult&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// lógica aqui&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&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;ValidateDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;document&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// lógica aqui&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Porém, se adicionarmos algo como:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&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;SaveUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// lógica aqui&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Claramente estaremos quebrando o SRP, já que salvar o usuário não deveria ser responsabilidade direta da estrutura de domínio &lt;code&gt;User&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Situação 02: Também é possível violar esse princípio em outras camadas da aplicação. Veja o exemplo abaixo em Elixir:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;
&lt;span class="c1"&gt;# Código com violação do SRP&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;define&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="n"&gt;dulo&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;define&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;fun&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert!&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;insere&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;banco&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;dados&lt;/span&gt;
    &lt;span class="no"&gt;Email&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_welcome&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="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;envia&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="n"&gt;para&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="n"&gt;cliente&lt;/span&gt; 
    &lt;span class="no"&gt;Logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"User created: \&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;loga&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;a&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;user&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;retorna&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="n"&gt;usu&lt;/span&gt;&lt;span class="err"&gt;á&lt;/span&gt;&lt;span class="n"&gt;rio&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Código seguindo o SRP&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;UserCreator&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;Repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert!&lt;/span&gt;&lt;span class="p"&gt;(%&lt;/span&gt;&lt;span class="no"&gt;UserStruct&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;WelcomeNotifier&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;send_welcome_email&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;do&lt;/span&gt;
    &lt;span class="no"&gt;Email&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_welcome&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;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Neste exemplo em Elixir, fica claro como é fácil misturar responsabilidades. No código inicial, temos criação de usuário, envio de e-mail e log em uma única função, o que fere o SRP. O código corrigido separa claramente as responsabilidades.&lt;/p&gt;

&lt;p&gt;Com esses exemplos, fica mais fácil entender como devemos pensar ao escrever código. Lembre-se de sempre avaliar se cada componente possui apenas uma única razão para mudar, caso haja mais de uma, com certeza o princípio SRP está quebrado nesse contexto. &lt;/p&gt;

&lt;p&gt;Repositórios com exemplos práticos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/rafael-hs/solid_elixir_examples/tree/main" rel="noopener noreferrer"&gt;Exemplo em Elixir&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/rafael-hs/solid-go-examples/tree/main" rel="noopener noreferrer"&gt;Exemplo em Golang&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se ainda houver dúvidas ou se você discordar de algo, deixe um comentário, até mais!&lt;/p&gt;

</description>
      <category>solidprinciples</category>
      <category>programming</category>
      <category>singleresponsibility</category>
      <category>srp</category>
    </item>
    <item>
      <title>Understanding SOLID once and for all | Part 01 - (SRP)</title>
      <dc:creator>Rafael Honório</dc:creator>
      <pubDate>Sun, 29 Jun 2025 21:57:42 +0000</pubDate>
      <link>https://forem.com/rafahs/understanding-solid-once-and-for-all-part-01-2bab</link>
      <guid>https://forem.com/rafahs/understanding-solid-once-and-for-all-part-01-2bab</guid>
      <description>&lt;h1&gt;
  
  
  Motivation
&lt;/h1&gt;

&lt;p&gt;This is the first post in a series where I’ll explain each SOLID concept clearly and engagingly. Instead of repeating content widely available online, I intend to provide a personal &lt;em&gt;dump&lt;/em&gt; of my experiences and understanding of these principles. Today, we'll begin with the Single Responsibility Principle (SRP).&lt;/p&gt;

&lt;h1&gt;
  
  
  Brief Summary
&lt;/h1&gt;

&lt;p&gt;The concepts forming the SOLID acronym have been well-known for at least 20 years and frequently appear in technical interviews. More importantly, deeply understanding these principles significantly improves your code quality. The purpose of these posts is to definitively clarify each concept so you can apply it independently of the programming language you use.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; At the end of the post, I’ll include two repositories with practical examples implementing each concept in Elixir and Golang. However, the essential aspect is grasping the underlying principles so you can adapt them to your specific context.&lt;/p&gt;

&lt;h1&gt;
  
  
  SRP - Single Responsibility Principle
&lt;/h1&gt;

&lt;p&gt;This term was coined by &lt;strong&gt;Robert Martin&lt;/strong&gt; (Uncle Bob) in 2000, in the book &lt;em&gt;Design Principles and Design Patterns&lt;/em&gt;. However, this classic programming challenge emerged during the 1980s as application complexity grew significantly. This increased complexity necessitated better code organization, promoting the adoption of &lt;a href="https://en.wikipedia.org/wiki/Object-oriented_programming" rel="noopener noreferrer"&gt;Object-Oriented Programming (OOP)&lt;/a&gt;, which already existed for around two decades by the 80s and 90s.&lt;/p&gt;

&lt;p&gt;According to the book &lt;em&gt;Clean Code&lt;/em&gt;, the SRP can be summarized as follows:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"A class or module should have one, and only one, reason to change." (&lt;em&gt;Clean Code&lt;/em&gt;, p. 138)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But what does that mean in practice? Within a structure, be it a module, package, or class, any interaction that deviates from its original purpose probably violates SRP.&lt;/p&gt;

&lt;p&gt;Consider these two examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scenario 01:&lt;/strong&gt; Within a user structure, properties and methods should always directly reflect user actions and characteristics. For example:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt;     &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Age&lt;/span&gt;      &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;Document&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="c"&gt;// other properties&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// In Go, this "(u *User)" indicates the function is a method of the User struct.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&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;IsAdult&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// logic here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&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;ValidateDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;document&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// logic here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, if we add something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="o"&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;SaveUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// logic here&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We clearly violate SRP, as saving the user should not be the direct responsibility of the domain structure &lt;code&gt;User&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scenario 02:&lt;/strong&gt; It's also possible to violate this principle in other application layers. Consider this Elixir example:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Code violating SRP&lt;/span&gt;
&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert!&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="no"&gt;Email&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_welcome&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="no"&gt;Logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"User created: \&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Code adhering to SRP&lt;/span&gt;
&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;UserCreator&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;Repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;insert!&lt;/span&gt;&lt;span class="p"&gt;(%&lt;/span&gt;&lt;span class="no"&gt;UserStruct&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;WelcomeNotifier&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;send_welcome_email&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;do&lt;/span&gt;
    &lt;span class="no"&gt;Email&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send_welcome&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;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This Elixir example clearly illustrates how easy it is to mix responsibilities. The initial code combines user creation, email sending, and logging into one function, violating SRP. The corrected code clearly separates responsibilities.&lt;/p&gt;

&lt;p&gt;With these examples, it becomes easier to understand how we should approach writing code. Always evaluate whether each component has only one reason to change—if there's more than one reason, SRP is likely being violated in that context.&lt;/p&gt;

&lt;p&gt;If you have any doubts or disagree with anything, feel free to comment!&lt;/p&gt;

&lt;p&gt;Repositories with practical examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/rafael-hs/solid_elixir_examples/tree/main" rel="noopener noreferrer"&gt;Example in Elixir&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rafael-hs/solid-go-examples/tree/main" rel="noopener noreferrer"&gt;Example in Golang&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ll write about the other principles soon and link them here once published. See you next time!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>solidprinciples</category>
      <category>srp</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>Is AI Going to Take Our Jobs? A Software Engineer’s Experience with LLMs</title>
      <dc:creator>Rafael Honório</dc:creator>
      <pubDate>Wed, 28 May 2025 22:24:40 +0000</pubDate>
      <link>https://forem.com/rafahs/is-ai-going-to-take-our-jobs-a-software-engineers-experience-with-llms-2k5k</link>
      <guid>https://forem.com/rafahs/is-ai-going-to-take-our-jobs-a-software-engineers-experience-with-llms-2k5k</guid>
      <description>&lt;p&gt;Over the past few years, there has been considerable discussion about how AI might replace all our jobs. For a long time, I completely ignored the topic; most of it sounded like pure &lt;strong&gt;bu11SH1T&lt;/strong&gt;. I had already studied neural networks and understood the basics of LLMs, Machine Learning, Deep Learning, Natural Language Processing, and Expert Systems. I had even tested a few generative AI tools, but none of them impressed me; they were buggy, full of hallucinations, and constrained.&lt;/p&gt;

&lt;p&gt;Last year (2024), I revisited the subject with more focus. A lot has changed, major improvements were made, but still, nothing close to replacing a real &lt;strong&gt;Software Engineer&lt;/strong&gt;, despite what many headlines suggested at the time.&lt;/p&gt;

&lt;p&gt;Since then, I’ve been following the field closely, running experiments and trying to understand how this tech could impact our daily work. That’s how this experiment came to life: I decided to use AI alone to redesign the &lt;strong&gt;visual theme&lt;/strong&gt; of my website (&lt;a href="https://rafaelhs-tech.com" rel="noopener noreferrer"&gt;rafaelhs-tech.com&lt;/a&gt;). The idea was simple: change only the look and feel of the site. Here’s how it went.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;p&gt;I originally built my site in 2021 using Angular (version 7 or 8, can’t remember exactly). It was pretty basic, just a few components with a space-themed design.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Original Version
&lt;/h2&gt;

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

&lt;p&gt;This was the original version. The journey with AI agents began using Claude 3.7. My first prompt went something like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“This is an Angular XX application, and I want to change the style to something with a cyberpunk theme. The folders are organized by components, and each component represents a page.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude scanned the project, found the &lt;strong&gt;SASS&lt;/strong&gt; files, and started generating new code… but then it began to hallucinate: it created &lt;strong&gt;React&lt;/strong&gt; files inside an &lt;strong&gt;Angular&lt;/strong&gt; project.&lt;/p&gt;

&lt;p&gt;I tried correcting it, but it kept going off track, breaking the app, mixing files, outputting React code again and again. So, I scrapped everything and started over.&lt;/p&gt;

&lt;p&gt;This time, I was more specific: I mentioned the Angular version, outlined the folder structure, highlighted key files, and gave a full project overview. The result? Slightly better visually, but still a broken UI. Misaligned pages, inconsistent styles, and worst of all: the code was a mess.&lt;/p&gt;




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

&lt;p&gt;This kind of output was common. For those unfamiliar, &lt;strong&gt;mixing HTML, CSS, and JS like this is bad practice&lt;/strong&gt; in modern web development.&lt;/p&gt;

&lt;p&gt;It wasn’t exactly surprising, but it reinforced a key point: these agents still lack a real understanding of good development practices. I kept using Claude 3.7 for a while, but it got frustrating. I’d ask for one thing, and it would return something completely different. After more than 15 prompts just to align a single button, I realized it would’ve been faster to just fix it manually, but I was committed to simulating a non-technical user experience.&lt;/p&gt;

&lt;p&gt;I also tested &lt;a href="https://codellm.abacus.ai/" rel="noopener noreferrer"&gt;CodeLLM&lt;/a&gt;, but it had another issue: it doesn’t retain long-term memory. If the prompt fails or reaches the token limit, continuing in a new thread resets everything, with no memory of past context. That became really annoying.&lt;/p&gt;




&lt;h3&gt;
  
  
  Common Hallucinations with Claude 3.7:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Generated things I didn’t ask for
&lt;/li&gt;
&lt;li&gt;Couldn’t revert changes
&lt;/li&gt;
&lt;li&gt;Deleted everything and regenerated the code in loops
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I switched to &lt;strong&gt;Claude 3.5&lt;/strong&gt;, which behaved more reliably. It followed instructions with better accuracy. I continued tweaking things and eventually got this result:&lt;/p&gt;




&lt;h2&gt;
  
  
  The Final Version
&lt;/h2&gt;

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

&lt;p&gt;After about 40 prompts, I reached a decent visual result. But the code was still messy: &lt;strong&gt;CSS mixed with SASS&lt;/strong&gt;, &lt;strong&gt;JS inline with HTML&lt;/strong&gt;, &lt;strong&gt;weird file names&lt;/strong&gt;, &lt;strong&gt;useless comments&lt;/strong&gt;... nothing reusable. I decided to try other LLMs like &lt;strong&gt;Gemini 2.5&lt;/strong&gt;, &lt;strong&gt;GPT o1&lt;/strong&gt;, and &lt;strong&gt;GPT o4mini&lt;/strong&gt;. The outcome was the same, frustrating, and each run produced noticeably different results (as expected).&lt;/p&gt;




&lt;h2&gt;
  
  
  Reflections
&lt;/h2&gt;

&lt;p&gt;There’s no doubt AI is changing how we code, learn, and approach problem-solving. But &lt;strong&gt;replacing a software engineer? We’re still far from that&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Some notes from this experiment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I didn’t manually edit any code, even though I knew exactly what to change. That alone made a huge difference.
&lt;/li&gt;
&lt;li&gt;The project was based on &lt;strong&gt;TS&lt;/strong&gt;, &lt;strong&gt;SASS&lt;/strong&gt;, and &lt;strong&gt;HTML&lt;/strong&gt;, a well-documented and widely used stack, and it still hallucinated a lot. Imagine this with &lt;strong&gt;Elixir&lt;/strong&gt;, &lt;strong&gt;Clojure&lt;/strong&gt;, or &lt;strong&gt;Crystal&lt;/strong&gt;, I’ve tried it. It doesn’t work well.
&lt;/li&gt;
&lt;li&gt;Code quality was poor. It "worked", but required major rework.
&lt;/li&gt;
&lt;li&gt;Vague prompts result in vague answers, obvious in theory, but problematic for non-technical users.
&lt;/li&gt;
&lt;li&gt;The total cost was around &lt;strong&gt;$14&lt;/strong&gt;, mainly from long conversations and resets. If I hadn’t started over several times, it would’ve been around &lt;strong&gt;$8 or 9&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;After all this, I can confidently say: &lt;strong&gt;we’re far from singularity&lt;/strong&gt;. LLMs are, at their core, &lt;strong&gt;text input → text output&lt;/strong&gt;. Sure, there’s complex stuff in the middle, but no actual "intelligence" is happening.&lt;/p&gt;

&lt;p&gt;If you repeat the same prompt, results may vary. That’s because LLMs are &lt;strong&gt;non-deterministic&lt;/strong&gt;, they generate responses based on probabilities. Techniques like &lt;a href="https://redis.io/docs/latest/develop/data-types/probabilistic/top-k/" rel="noopener noreferrer"&gt;top-k sampling&lt;/a&gt; and &lt;a href="https://community.openai.com/t/a-better-explanation-of-top-p/2426" rel="noopener noreferrer"&gt;top-p sampling&lt;/a&gt; can influence the outcome, but randomness is part of the deal.&lt;/p&gt;

&lt;p&gt;Yes, this raises the bar for simpler tasks, and that might affect junior devs, but everything depends on context.&lt;/p&gt;

&lt;p&gt;Now imagine a real-world complex system with backend logic, BFF, Terraform, CI/CD pipelines, or microservices, where a small UI tweak could have unexpected side effects elsewhere. That’s a mess waiting to happen. I spoke with some friends in mobile development, and their experience was even worse. Honestly, web development might be the "least bad" scenario.&lt;/p&gt;

&lt;p&gt;It’s up to us to adapt. I use AI tools every day now, for studying, writing docs, building PRDs, MRDs, diagrams, etc. But we’re still far from AI solving software engineering on its own.&lt;/p&gt;




&lt;p&gt;If you enjoyed this reflection, leave a comment and share your own experience using LLMs.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Until next time!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>frontend</category>
      <category>jobs</category>
      <category>webdev</category>
    </item>
    <item>
      <title>IA vai tirar nossos empregos? A experiência de um engenheiro de software no Frontend com LLMs</title>
      <dc:creator>Rafael Honório</dc:creator>
      <pubDate>Wed, 28 May 2025 21:28:08 +0000</pubDate>
      <link>https://forem.com/rafahs/ia-vai-tirar-nossos-empregos-a-experiencia-de-um-engenheiro-de-software-no-frontend-com-llms-47lh</link>
      <guid>https://forem.com/rafahs/ia-vai-tirar-nossos-empregos-a-experiencia-de-um-engenheiro-de-software-no-frontend-com-llms-47lh</guid>
      <description>&lt;p&gt;Nos últimos anos, muito se tem discutido sobre como a IA pode acabar com nossos empregos. Por um bom tempo, ignorei esse papo, a maior parte parecia puro &lt;strong&gt;bu11SH1T&lt;/strong&gt;. Eu já tinha estudado redes neurais e conhecia o básico sobre LLMs, Machine Learning, Deep Learning, Processamento de Linguagem Natural e Sistemas Especialistas. Já tinha testado algumas ferramentas de IA generativa, mas nada me impressionava: eram bugadas, cheias de "delírios" e bem limitadas.&lt;/p&gt;

&lt;p&gt;No ano passado (2024), voltei a estudar o tema com mais atenção. Muita coisa evoluiu, houve avanços relevantes, mas ainda assim, nada que indicasse uma substituição real de um &lt;strong&gt;Software Engineer&lt;/strong&gt;, como várias manchetes sugeriam na época.&lt;/p&gt;

&lt;p&gt;Desde então, venho acompanhando de perto, fazendo testes e experimentos, tentando entender melhor como essa tecnologia pode impactar nosso dia a dia. E foi assim que surgiu a ideia deste experimento: utilizar 100% IA para modificar o visual do meu site pessoal (&lt;a href="https://rafaelhs-tech.com" rel="noopener noreferrer"&gt;rafaelhs-tech.com&lt;/a&gt;). O objetivo era simples: mudar apenas o tema visual do site, vamos ao caso.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stack
&lt;/h2&gt;

&lt;p&gt;Criei meu site pessoal em 2021 usando Angular (versão 7 ou 8, não lembro ao certo). A estrutura era básica, com a interface separada em componentes e uma pegada visual meio “espaço sideral”.&lt;/p&gt;




&lt;h2&gt;
  
  
  Como era
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs7u32s4ysglm5o85yt22.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs7u32s4ysglm5o85yt22.png" alt="Versão antiga" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Essa era a versão original. A jornada com os agentes de IA começou com o Claude 3.7. Meu primeiro prompt foi algo assim:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Essa é uma aplicação Angular XX e quero alterar o estilo visual com uma temática cyberpunk. As pastas estão organizadas por componentes, e cada componente representa uma página.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Claude analisou as páginas, identificou os arquivos &lt;strong&gt;SASS&lt;/strong&gt;, começou a sugerir mudanças... mas aí começou a delirar: criou arquivos em &lt;strong&gt;React&lt;/strong&gt; dentro de um projeto &lt;strong&gt;Angular&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Tentei corrigir, mas ele insistia. Sempre surgia algo quebrado, arquivos fora do padrão, ou partes em React. Resultado: joguei tudo fora e recomecei do zero.&lt;/p&gt;

&lt;p&gt;Dessa vez, fui mais específico: informei a versão do Angular, a estrutura de pastas, arquivos relevantes, etc. O resultado? Visualmente um pouco melhor, mas o site estava todo quebrado. Páginas desalinhadas, estilizações inconsistentes... e o pior: o código estava uma bagunça.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgl85g94r716j7d7ewarc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgl85g94r716j7d7ewarc.png" alt="Código ruim" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esse tipo de resultado era recorrente. Para quem não percebeu: hoje em dia, &lt;strong&gt;misturar HTML, CSS e JS desse jeito é má prática&lt;/strong&gt; em projetos modernos.&lt;/p&gt;

&lt;p&gt;Não foi exatamente uma surpresa, mas reforçou uma verdade: esses agentes não têm noção real de boas práticas. Continuei com Claude 3.7 por mais um tempo, mas comecei a me irritar. Pedia uma coisa, ele fazia outra. Foram mais de 15 prompts para alinhar um botão. Chegou um ponto em que seria mais fácil eu mesmo resolver, mas eu queria simular a experiência de um usuário sem conhecimento técnico.&lt;/p&gt;

&lt;p&gt;Também testei com o CodeLLM, mas surgiu outro problema: ele não mantém histórico muito longo. A cada nova tentativa, se o prompt quebrava, era necessário recomeçar do zero, sem memória do progresso anterior.&lt;/p&gt;




&lt;h3&gt;
  
  
  Delírios comuns que enfrentei com Claude 3.7:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Criava coisas que eu não pedi
&lt;/li&gt;
&lt;li&gt;Não conseguia desfazer alterações
&lt;/li&gt;
&lt;li&gt;Deletava tudo e começava do zero em loop
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Troquei então para o &lt;strong&gt;Claude 3.5&lt;/strong&gt;, e o comportamento foi mais estável. A IA seguiu os comandos com mais precisão. Continuei criando prompts, ajustando o layout e cheguei neste resultado:&lt;/p&gt;




&lt;h2&gt;
  
  
  Como ficou
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8z2rv6qyym5s57fm8e42.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8z2rv6qyym5s57fm8e42.png" alt="Versão final" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Após cerca de 40 prompts, cheguei a um visual legal. Mas o código continuava problemático: &lt;strong&gt;mistura de CSS com SASS&lt;/strong&gt;, &lt;strong&gt;JS no meio do HTML&lt;/strong&gt;, &lt;strong&gt;nomes de arquivos esquisitos&lt;/strong&gt;, &lt;strong&gt;comentários inúteis&lt;/strong&gt;... nada muito aproveitável. Decidi então testar outras LLMs: &lt;strong&gt;Gemini 2.5&lt;/strong&gt;, &lt;strong&gt;GPT o1&lt;/strong&gt;, &lt;strong&gt;GPT o4mini&lt;/strong&gt;. O resultado foi o mesmo: frustração, e me gerou um resultado bem diferente cada tentativa, que era esperado também.&lt;/p&gt;




&lt;h2&gt;
  
  
  Reflexões
&lt;/h2&gt;

&lt;p&gt;Sem dúvida, a IA está mudando a forma como programamos, estudamos e até pensamos em soluções. Mas &lt;strong&gt;substituir um engenheiro de software? Ainda estamos bem longe disso&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Vejo manchetes tratando as LLMs como se fossem o “nirvana do desenvolvimento”, mas, na prática, não é bem assim. Algumas observações:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Em nenhum momento editei o código manualmente, mesmo sabendo como corrigir. Isso faz diferença.
&lt;/li&gt;
&lt;li&gt;O projeto era em &lt;strong&gt;TS&lt;/strong&gt;, &lt;strong&gt;SASS&lt;/strong&gt; e &lt;strong&gt;HTML&lt;/strong&gt;, um cenário comum e bem documentado. Mesmo assim, a IA cometeu muitos erros. Imagine isso num backend com &lt;strong&gt;Elixir&lt;/strong&gt;, &lt;strong&gt;Clojure&lt;/strong&gt; ou &lt;strong&gt;Crystal&lt;/strong&gt;, não funciona muito bem, eu já tentei.&lt;/li&gt;
&lt;li&gt;A qualidade do código gerado é baixa. Funciona, mas exige bastante retrabalho.&lt;/li&gt;
&lt;li&gt;Prompts vagos geram respostas vagas, parece óbvio, mas um usuário comum não vai saber ser tão específico.
&lt;/li&gt;
&lt;li&gt;O custo final ficou em torno de &lt;strong&gt;US$ 14&lt;/strong&gt;. Se eu não tivesse refeito do zero algumas vezes, cairia para uns &lt;strong&gt;US$ 8 ou 9&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Depois dessa experiência, posso afirmar: &lt;strong&gt;a singularidade está longe&lt;/strong&gt;. LLMs são, no fim das contas, &lt;strong&gt;input de texto → output de texto&lt;/strong&gt;. Claro, há muito acontecendo entre esses dois pontos, mas não existe “inteligência” real envolvida.&lt;/p&gt;

&lt;p&gt;Se você repetir o mesmo prompt, os resultados podem mudar (Não deterministico), as LLMs não escolhem sempre a palavra mais provável é uma base probabilistica, algumas outras ténicas de &lt;a href="https://redis.io/docs/latest/develop/data-types/probabilistic/top-k/" rel="noopener noreferrer"&gt;top-k&lt;/a&gt; ou &lt;a href="https://community.openai.com/t/a-better-explanation-of-top-p/2426" rel="noopener noreferrer"&gt;top-p&lt;/a&gt; podem mudar o resultado, mas sim, isso &lt;strong&gt;eleva a régua para tarefas simples&lt;/strong&gt;, o que pode impactar profissionais mais iniciantes, mas tudo depende do contexto.&lt;/p&gt;

&lt;p&gt;Fico imaginando um cenário com backend, BFF, Terraform, CI/CD... ou mesmo microserviços onde uma mudança gera efeitos colaterais em outros pontos. A chance de virar uma bagunça é alta. Conversei com amigos da área de mobile, e eles confirmaram: lá, a situação é ainda pior, acredito que no contexto web é onde funciona melhor.&lt;/p&gt;

&lt;p&gt;Cabe a nós acompanhar essa transição e adaptar nosso workflow. Eu, por exemplo, uso IA todos os dias, para estudar, escrever documentos, criar PRDs, MRDs, diagramas e etc. Mas ainda está longe de resolver muitas questões sozinho.&lt;/p&gt;




&lt;p&gt;Se você curtiu essa reflexão, comenta aí e compartilha sua experiência com LLMs.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Do mais, até mais!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>empregos</category>
      <category>softwareengineering</category>
      <category>ai</category>
    </item>
    <item>
      <title>RabbitMQ — Primeiros passos (repost de 2018)</title>
      <dc:creator>Rafael Honório</dc:creator>
      <pubDate>Tue, 20 May 2025 15:44:25 +0000</pubDate>
      <link>https://forem.com/rafahs/rabbitmq-primeiros-passos-repost-de-2018-3bp</link>
      <guid>https://forem.com/rafahs/rabbitmq-primeiros-passos-repost-de-2018-3bp</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fblfcpyb7tkjzibqhej0b.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fblfcpyb7tkjzibqhej0b.jpg" alt="How does it work?" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Hey oh!&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Olá! Quero compartilhar um pouco da minha experiência com o &lt;a href="https://www.rabbitmq.com/" rel="noopener noreferrer"&gt;RabbitMQ&lt;/a&gt; nos últimos meses. A ideia é criar uma espécie de &lt;strong&gt;guia introdutório&lt;/strong&gt; para quem está começando.&lt;/p&gt;

&lt;p&gt;Como a maior parte do conteúdo (inclusive a documentação) está em inglês, resolvi escrever este mini artigo/tutorial para a galera da comunidade que, assim como eu, está melhorando no inglês.&lt;/p&gt;

&lt;p&gt;Se você chegou até aqui, provavelmente já sabe o que é um &lt;a href="https://en.wikipedia.org/wiki/Message_broker" rel="noopener noreferrer"&gt;message broker&lt;/a&gt;. Mas caso tenha caído de paraquedas, dá uma olhada nesse artigo da Wikipédia e usa o bom e velho &lt;strong&gt;Google Tradutor&lt;/strong&gt;, ele ajuda bastante!&lt;/p&gt;

&lt;p&gt;Entre as opções de mercado como Kafka, ActiveMQ, SQS, entre outros, o RabbitMQ é uma excelente escolha. E o melhor: é &lt;strong&gt;open source&lt;/strong&gt;, ao contrário de algumas alternativas citadas. No geral, é uma ferramenta bem completa.&lt;/p&gt;

&lt;p&gt;O RabbitMQ tem suporte oficial para várias linguagens: C#, Java, PHP, Python, Ruby, Go, Elixir e por aí vai, as mais utilizadas atualmente.&lt;/p&gt;

&lt;p&gt;Neste artigo, divido o conteúdo em três partes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cenários de aplicação
&lt;/li&gt;
&lt;li&gt;Conceitos
&lt;/li&gt;
&lt;li&gt;Mão na massa&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  &lt;strong&gt;Cenários de aplicação&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Gosto de resumir o uso do RabbitMQ em dois cenários comuns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quando uma aplicação distribuída precisa se comunicar com várias outras (&lt;strong&gt;fanout&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;Quando você precisa executar um processo de forma assíncrona, por exemplo: é bem comum em e-commerce dentro do processo de compra, ter várias etapas para finalizar uma compra, carrinho, pagamento, processamento, envio e por ai vai...(&lt;strong&gt;topic&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4f76g81s9tdhyn98hvo2.png" alt="Image description" width="800" height="623"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;cenário bem comum&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A maioria dos casos de uso vai acabar derivando dessas duas situações.&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;strong&gt;Conceitos&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Aqui vão alguns conceitos importantes do RabbitMQ. (Não se preocupe se parecer muita coisa, eu também me perdi nos primeiros dias lendo a documentação.)&lt;/p&gt;

&lt;p&gt;A forma mais básica de usar um message broker é: um app envia uma informação para outro app.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjzzp8v4rk6qfy5gw9ibx.png" alt="app-to-app" width="440" height="90"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Cenário mais simples&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://www.rabbitmq.com/tutorials/tutorial-three-dotnet.html" rel="noopener noreferrer"&gt;Produtor&lt;/a&gt; envia uma informação para uma fila (queue) e um consumidor pega essa informação, conceito simples, não é mesmo?&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk28j2b4i0ol3878ep5ll.jpg" alt="app-to-app-detail" width="700" height="328"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;Um pouco mais detalhado&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Claro que existem alguns poréns no processo, mas vamos direto ao ponto. Aqui vão os principais conceitos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.rabbitmq.com/queues.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Queue&lt;/strong&gt;&lt;/a&gt;: É a fila dentro do servidor RabbitMQ. As filas têm propriedades como &lt;code&gt;exchange&lt;/code&gt;, &lt;code&gt;binds&lt;/code&gt;, &lt;code&gt;headers&lt;/code&gt; e &lt;code&gt;content&lt;/code&gt;, que explico a seguir.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.rabbitmq.com/tutorials/amqp-concepts.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Exchange&lt;/strong&gt;&lt;/a&gt;: É o “roteador” das mensagens. Ele decide como e para onde as mensagens serão enviadas. Existem quatro tipos: &lt;code&gt;Direct&lt;/code&gt;, &lt;code&gt;Fanout&lt;/code&gt;, &lt;code&gt;Topic&lt;/code&gt; e &lt;code&gt;Headers&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bind&lt;/strong&gt; ou &lt;strong&gt;RoutingKey&lt;/strong&gt;: É o identificador que conecta uma queue a uma exchange. Ele define o caminho que a mensagem vai seguir.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.rabbitmq.com/tutorials/tutorial-three-dotnet.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Producer / Publisher&lt;/strong&gt;&lt;/a&gt;: A aplicação que produz e envia a mensagem para o RabbitMQ.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.rabbitmq.com/tutorials/tutorial-three-dotnet.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Consumer / Subscriber&lt;/strong&gt;&lt;/a&gt;: A aplicação que consome a mensagem da fila.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.rabbitmq.com/vhosts.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Virtual host&lt;/strong&gt;&lt;/a&gt;: O RabbitMQ é multi-tenant, ou seja, permite múltiplos ambientes lógicos. Cada vhost separa conexões, filas, binds, exchanges, policies e usuários. Se você já trabalhou com virtual hosts no Apache ou blocos de servidores no Nginx, a ideia é parecida, mas no RabbitMQ, esses hosts são criados via &lt;code&gt;rabbitmqctl&lt;/code&gt; ou pela API.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Com esses conceitos em mente, fica muito mais fácil entender o restante. Tentei manter o texto leve e informal pra facilitar :D&lt;/p&gt;




&lt;h1&gt;
  
  
  &lt;strong&gt;Mão na massa&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Agora vamos configurar o servidor e começar a codar!&lt;/p&gt;

&lt;p&gt;Vou usar um servidor Linux (Debian) e a linguagem &lt;strong&gt;C#&lt;/strong&gt;, mas o conceito se aplica a qualquer linguagem com suporte a RabbitMQ.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Passo 1 – Instalar o Erlang&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Execute os seguintes comandos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb
&lt;span class="nb"&gt;sudo &lt;/span&gt;dpkg &lt;span class="nt"&gt;-i&lt;/span&gt; erlang-solutions_1.0_all.deb
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;erlang erlang-nox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Passo 2 – Instalar o RabbitMQ Server&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;add-apt-repository &lt;span class="s1"&gt;'deb http://www.rabbitmq.com/debian/ testing main'&lt;/span&gt;
wget &lt;span class="nt"&gt;-O-&lt;/span&gt; https://www.rabbitmq.com/rabbitmq-release-signing-key.asc | &lt;span class="nb"&gt;sudo &lt;/span&gt;apt-key add -
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;rabbitmq-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inicie e habilite o serviço:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;rabbitmq-server
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start rabbitmq-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pare o servidor (temporariamente):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl stop rabbitmq-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Criar usuário para o Web Management&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;rabbitmqctl add_user admin password 
&lt;span class="nb"&gt;sudo &lt;/span&gt;rabbitmqctl set_user_tags admin administrator
&lt;span class="nb"&gt;sudo &lt;/span&gt;rabbitmqctl set_permissions &lt;span class="nt"&gt;-p&lt;/span&gt; / admin &lt;span class="s2"&gt;".*"&lt;/span&gt; &lt;span class="s2"&gt;".*"&lt;/span&gt; &lt;span class="s2"&gt;".*"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Habilite o plugin de administração:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;rabbitmq-plugins &lt;span class="nb"&gt;enable &lt;/span&gt;rabbitmq_management
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inicie o servido novamente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start rabbitmq-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Acesse o painel web em &lt;code&gt;http://localhost:15672&lt;/code&gt;&lt;br&gt;
(Usuário: admin / Senha: password)&lt;/p&gt;

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

&lt;p&gt;Liberar portas no firewall (se necessário)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;firewall-cmd &lt;span class="nt"&gt;--add-port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;15672/tcp &lt;span class="nt"&gt;--permanent&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;firewall-cmd &lt;span class="nt"&gt;--add-port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5672/tcp &lt;span class="nt"&gt;--permanent&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;firewall-cmd &lt;span class="nt"&gt;--add-port&lt;/span&gt;&lt;span class="o"&gt;={&lt;/span&gt;4369/tcp,25672/tcp&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--permanent&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;firewall-cmd &lt;span class="nt"&gt;--reload&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;firewall-cmd &lt;span class="nt"&gt;--list-all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Desta forma o servidor já está configurado, vou mostrar um exemplo criando uma fila e enviando uma informação e consumir em outra app. Existem várias abordagens para trabalhar com rabbitmq, criando uma API http, cronjob, background job e por ai vai.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Passo 3 – Criar uma aplicação para interagir com o RabbitMQ&lt;/strong&gt;*
&lt;/h3&gt;

&lt;p&gt;Crie uma Console App e adicione a dependência do RabbitMQ client.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package RabbitMQ.Client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ou&lt;/p&gt;

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

&lt;p&gt;Crie uma classe para envio de mensagens:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk73l0zkoz7pd2mefkszu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk73l0zkoz7pd2mefkszu.png" alt="Image description" width="800" height="429"&gt;&lt;/a&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;using&lt;/span&gt; &lt;span class="nn"&gt;RabbitMQ.Client&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&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.Text&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;NewTask&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;NewTask&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&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="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;ConnectionFactory&lt;/span&gt; &lt;span class="n"&gt;factory&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;ConnectionFactory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;HostName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Protocols&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DefaultProtocol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DefaultPort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;UserName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Password&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;VirtualHost&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="n"&gt;RequestedHeartbeat&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;60&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;

            &lt;span class="k"&gt;using&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;connection&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateConnection&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;using&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;channel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateModel&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExchangeDeclare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"MediumExchange"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ExchangeType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Topic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;autoDelete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;
                    &lt;span class="p"&gt;);&lt;/span&gt;

                    &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;QueueDeclare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"queueMediumTeste"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;durable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;exclusive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;autoDelete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
                    &lt;span class="p"&gt;);&lt;/span&gt;

                    &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;QueueBind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"queueMediumTeste"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"MediumExchange"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;routingKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"MediumBind"&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;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Olá Medium"&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;body&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Encoding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UTF8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetBytes&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;properties&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBasicProperties&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                    &lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Persistent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

                    &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BasicPublish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"MediumExchange"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;routingKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"MediumBind"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;basicProperties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;body&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;" [x] Sent {0}"&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="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;"Press [enter] to exit."&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;ReadLine&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Esse código realiza os seguintes passos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cria uma Exchange&lt;/li&gt;
&lt;li&gt;Cria uma Queue&lt;/li&gt;
&lt;li&gt;Cria um Bind&lt;/li&gt;
&lt;li&gt;Envia a mensagem (convertida em bytes)&lt;/li&gt;
&lt;li&gt;Define se ela deve ser persistida&lt;/li&gt;
&lt;li&gt;Publica a mensagem&lt;/li&gt;
&lt;li&gt;Mostra no console&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqz8xgn07h9a9bwr1h34f.png" alt="Image description" width="800" height="416"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;a mensagem enviada para o servidor&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;Agora, crie outro arquivo para consumir a mensagem da fila:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ui7desbpoya4ykmf1pk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ui7desbpoya4ykmf1pk.png" alt="Image description" width="800" height="384"&gt;&lt;/a&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;using&lt;/span&gt; &lt;span class="nn"&gt;RabbitMQ.Client&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;RabbitMQ.Client.Events&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&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.Text&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;ConsumerPublishSub&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&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="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;ConnectionFactory&lt;/span&gt; &lt;span class="n"&gt;factory&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;ConnectionFactory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;HostName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Protocols&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DefaultProtocol&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DefaultPort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;UserName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Password&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"admin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;VirtualHost&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="n"&gt;RequestedHeartbeat&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;60&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;

            &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IConnection&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateConnection&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IModel&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateModel&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;"Waiting for logs."&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;consumer&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;EventingBasicConsumer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Received&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ea&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;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;body&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ea&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&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;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Encoding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UTF8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToArray&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;" [x] Received {0}"&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="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BasicConsume&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"QueueMediumTeste"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;autoAck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;consumer&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;" Press [enter] to exit."&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;ReadLine&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

                    &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;A mensagem esperada será:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7mahd2qb59f0q99drxx5.png" alt="Image description" width="800" height="419"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;o resultado esperado&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Esse é o básico para começar a usar RabbitMQ com .NET.&lt;br&gt;
No site oficial há um Get Started completo para várias linguagens.&lt;/p&gt;

&lt;p&gt;No futuro, quero escrever sobre clusters com RabbitMQ, estou criando uma lib para facilitar essas interações, e em breve compartilho aqui.&lt;/p&gt;

&lt;p&gt;Curtiu? Me chama!&lt;br&gt;
Se tiver dúvidas ou quiser trocar ideia:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.linkedin.com/in/rafael-hs/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/rafael-hs" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rafaelhs-tech.com/" rel="noopener noreferrer"&gt;Website&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OBS: esse texto foi escrito em 2018, transferi o artigo para o dev.to por que o medium ficou uma merda, valeu!&lt;/p&gt;

</description>
      <category>eventdriven</category>
      <category>pubsub</category>
      <category>messagebroker</category>
      <category>rabbitmq</category>
    </item>
    <item>
      <title>Xiaomi RedmiBook: How to Fix Wi-Fi Issues on Linux (Debian distros)</title>
      <dc:creator>Rafael Honório</dc:creator>
      <pubDate>Tue, 20 May 2025 12:52:59 +0000</pubDate>
      <link>https://forem.com/rafahs/xiaomi-redmibook-how-to-fix-wi-fi-issues-on-linux-debian-distros-ka7</link>
      <guid>https://forem.com/rafahs/xiaomi-redmibook-how-to-fix-wi-fi-issues-on-linux-debian-distros-ka7</guid>
      <description>&lt;p&gt;Hey folks 👋&lt;/p&gt;

&lt;p&gt;Recently, I bought a &lt;strong&gt;Xiaomi RedmiBook 16&lt;/strong&gt; to get more mobility and separate my work environment. Everything was going great, until I booted into Linux and realized the &lt;strong&gt;Wi-Fi wasn’t working at all&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;After some digging, I found out the issue was related to the &lt;strong&gt;Qualcomm Atheros QCA6174 802.11ac Wireless Network Adapter&lt;/strong&gt;. It turns out that after installing the OS or updating the kernel, &lt;strong&gt;the firmware breaks&lt;/strong&gt;. Don’t ask me why, but several logs showed the adapter crashing on boot.&lt;/p&gt;

&lt;p&gt;If you’re facing the same issue, here’s a simple workaround that worked for me on Ubuntu. It should also help on other Debian-based distros like &lt;strong&gt;Kali, Mint, Deepin, Xubuntu and etc&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s the problem?
&lt;/h2&gt;

&lt;p&gt;When the kernel loads, the adapter crashes due to incompatible or missing firmware. You’ll likely see something like this in &lt;code&gt;dmesg&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ath10k_pci 0000:01:00.0: failed to fetch board data &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="nv"&gt;bus&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;pci…
ath10k_pci 0000:01:00.0: failed to load board file…
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To fix this, you need to manually replace the firmware files on your system.&lt;/p&gt;

&lt;p&gt;If you try searching online, you’ll find several tutorials recommending replacing the main firmware binary. The problem is, most of them point to the same source, and unfortunately, killernetworking.com has been offline for years.&lt;/p&gt;

&lt;p&gt;Luckily, I downloaded that binary back then and saved it to a personal drive, since this issue kept happening. I figured it might disappear one day... and it did. So I created a GitHub repository with a .deb package to make things easier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step-by-step fix
&lt;/h2&gt;

&lt;p&gt;1 - Clone this repository with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/rafael-hs/qualcomm-atheros-qca6174-firmware-adapter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2 - Enter the directory and install the .deb&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install ./surface-go-wifi_0.0.5_amd64.deb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3 - Then reboot your system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;reboot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! After these steps, your Wi-Fi should be up and running.&lt;/p&gt;

&lt;h2&gt;
  
  
  Did it work?
&lt;/h2&gt;

&lt;p&gt;It worked perfectly on my Ubuntu install, and I’ve seen others confirm it on similar distros. If you run into any issues or have another solution, drop a comment. It might help someone else!&lt;/p&gt;

&lt;p&gt;Thanks for reading and good luck! 🚀&lt;/p&gt;

</description>
      <category>linux</category>
      <category>wifi</category>
      <category>ubuntu</category>
      <category>redmibook</category>
    </item>
  </channel>
</rss>
