<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Leonardo Bonetti</title>
    <description>The latest articles on DEV Community by Leonardo Bonetti (@leonardbonetti).</description>
    <link>https://dev.to/leonardbonetti</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%2F507195%2F52304ac7-8758-479a-aac4-85d02e71d2e0.jpg</url>
      <title>DEV Community: Leonardo Bonetti</title>
      <link>https://dev.to/leonardbonetti</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/leonardbonetti"/>
    <language>en</language>
    <item>
      <title>SOLID com Typescript: O resumo completo com exercícios</title>
      <dc:creator>Leonardo Bonetti</dc:creator>
      <pubDate>Tue, 01 Nov 2022 13:28:26 +0000</pubDate>
      <link>https://dev.to/leonardbonetti/solid-com-typescript-o-resumo-completo-com-exercicios-58n8</link>
      <guid>https://dev.to/leonardbonetti/solid-com-typescript-o-resumo-completo-com-exercicios-58n8</guid>
      <description>&lt;h2&gt;
  
  
  O que aprenderemos hoje?
&lt;/h2&gt;

&lt;p&gt;Neste artigo, você conhecerá um conjunto de 5 princípios (S.O.L.I.D) fundamentais para o desenvolvimento de um sistema de fácil manutenção, extensão, incorporação e principalmente, compreensão.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requisitos necessários
&lt;/h2&gt;

&lt;p&gt;Para total aproveitamento do conteúdo a seguir, é indicado que você conheça o paradigma de programação orientado a objetos e tenha noções de herança e polimorfismo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Antes de começarmos...
&lt;/h2&gt;

&lt;p&gt;É muito importante entendermos primeiramente o que é Arquitetura de software, para isso, gosto de fazer um paralelo com a Arquitetura Civil, já que está em nosso dia a dia desde sempre e podemos identificar de forma rápida ao entrarmos em um ambiente bem-planejado que este foi projetado por um arquiteto, nos impressionamos com cada canto bem aproveitado, a disposição das luzes e elementos pelas paredes, assim como a conveniência de diversos recursos como pontos de energia e iluminação em cada lugar que podem se apresentar necessários. Ao viver em um ambiente como o descrito, percebemos que acima da beleza, o valor de sua obra está em sua utilidade; O mesmo acontece com sistemas computacionais, se você vai passar meses ou anos trabalhando em um determinado sistema, você vai querer que ele tenha sido em primeiro lugar bem projetado e como um bom desenvolvedor, seu papel é mantê-lo assim, independentemente do quanto ele cresça.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Como qualquer metáfora, descrever software  por meio das lentes da arquitetura pode esconder tanto quanto pode revelar, pode prometer mais do que entregar e entregar mais do que o prometido.&lt;br&gt;
O apelo óbvio da arquitetura é a estrutura, que domina os paradigmas e discussões sobre o desenvolvimento de software - Componentes, classes, funções, módulos, camadas e serviços, micro ou macro. No entanto, muitas vezes, é difícil confirmar ou compreender a estrutura bruta de vários sistemas de software - esquemas corporativos ao estilo soviético em vias de se tornarem legado, improváveis torres de equilíbrio se estendendo em direção a nuvem, camadas arqueológicas enterradas em um slide que parece uma imensa bola de lama. Pelo jeito, a estrutura de um software não é tão intuitiva quanto a de um prédio.&lt;br&gt;
(MARTIN, R.C. Arquitetura limpa: O guia do artesão para a estrutura e design de software. [S.l.]: ALTA BOOKS, 2019.)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Na arquitetura civil existem limitações físicas que impedem os profissionais de realizarem certas ações, porém no mundo virtual os limites podem não ser tão claros, assim como Robert C. Martin descreve no trecho acima. Os paradigmas de programação vêm então com mais uma proposta do que não devemos fazer do que o que devemos fazer, escolher um paradigma é escolher os limites que o mesmo impõe, se você escolher o paradigma orientado a objetos, o SOLID é uma adição muito bem-vinda a esses limites.&lt;/p&gt;

&lt;h1&gt;
  
  
  Vamos aos SOLID
&lt;/h1&gt;

&lt;p&gt;O SOLID foi apresentado por Robert C. Martin em um artigo dos anos 2000 com o título "Postulados de Projeto e Padrões de Projeto", mas onde ele realmente brilhou foi em seu livro "Arquitetura Limpa", por isso será citado diversas vezes neste conteúdo.&lt;/p&gt;

&lt;h2&gt;
  
  
  SRP (Single Responsibility Principle)
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Um corolário ativo da lei de Conway: A melhor estrutura para um sistema de software deve ser altamente influenciada pela estrutura social da organização que o utiliza, de modo que cada módulo de software tenha uma, e apenas uma, razão para mudar.&lt;br&gt;
(MARTIN, Arquitetura limpa. página 102)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Você está desenvolvendo um sistema de lembretes para a Apple e se depara com a seguinte classe:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Reminder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getTags&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para olhos mal treinados, pode não ter nada de errado aqui, nossa classe de lembrete tem uma funcionalidade para salvar em um banco de dados e outra para retornar as hashtags do content.&lt;br&gt;
Retornar as tags é uma responsabilidade única e exclusiva dos lembretes, mas salvar um conteúdo em um banco de dados não é.&lt;br&gt;
Aqui temos o caso clássico de que &lt;em&gt;se existe uma ação disponível a uma entidade, essa entidade deve implementar essa ação&lt;/em&gt;, isso esta completamente &lt;em&gt;errado&lt;/em&gt;, pois dezenas de outras entidades podem precisar salvar seus conteúdos no banco de dados e se por algum motivo nossa implementação do banco mudar da função CREATE para SET, por exemplo, teríamos de alterar todas essas entidades, então para corrigir isso, vamos ver o exemplo abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Reminder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getTags&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Storage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;storeReminder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Reminder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora temos uma nova classe chamada Storage, ela é a responsável por salvar objetos no banco, caso dezenas de classes precisem utilizar este recurso é a classe Storage quem vai lidar com isso, assim, o único motivo para Storage mudar é se mudarmos a implementação do banco de dados e o único para Reminders mudar é se mudarmos as regras de tags.&lt;/p&gt;

&lt;p&gt;Existe uma confusão muito comum quando falamos do princípio da responsabilidade única, que muitos desenvolvedores acreditam que uma classe deve fazer apenas uma única coisa e isso também está completamente errado, uma classe deve ter apenas um motivo para mudar e isso significa que deve atender a uma única regra de um determinado ator (ator é quem interage com o sistema, podendo ser um usuário, administrador, outro sistema, stakeholder ou até mesmo outras classes.)&lt;/p&gt;

&lt;h3&gt;
  
  
  Sintomas do descumprimento SRP
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Duplicação Acidental
&lt;/h4&gt;

&lt;p&gt;Digamos que a Apple te pediu para fazer um sistema de cálculo de horários, onde o RH e o financeiro serão os clientes, então você escreve o seguinte código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Admin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;calculateWorkHours&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RH&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Admin&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Financial&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Admin&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depois de pronto, o sistema começa a dar problemas, por que o RH considera horas trabalhadas o horário que o funcionário entrou e saiu da empresa, enquanto o financeiro considera apenas o horário que ele ficou no computador, desconsiderando as pausas, se você alterar a classe admin, um dos dois times será afetado. Para resolver esta questão você precisa reimplementar as funções da seguinte forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Admin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RH&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Admin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;calculateWorkHours&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Financial&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Admin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;calculateWorkHours&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;Nesse caso, fizemos o oposto da classe de lembretes, já que o cálculo de horas é de responsabilidade única de cada um dos atores &lt;/p&gt;

&lt;h4&gt;
  
  
  Fusões
&lt;/h4&gt;

&lt;p&gt;Sabe quando você trabalhou dias em uma determinada funcionalidade para seu sistema e com o trabalho pronto, finalmente abre um pull request para anexá-lo a branch principal, mas recebe aquela mensagem super desagradável de um conflito que o impede? &lt;br&gt;
Pois é, na maioria dos casos isso acontece quando o SRP não é respeitado, sendo assim existe uma classe que atende a mais de um ator do sistema, e são eles quem definem as tarefas, ou seja, mais de um desenvolvedor pode ser solicitado a realizar alterações/adições nesse módulo, e quando isso acontece, na hora de anexar a atividade, se depara com este conflito.&lt;/p&gt;

&lt;p&gt;O Princípio da Responsabilidade Única visa simplesmente reduzir ao máximo a necessidade de alterar uma determinada classe e que alterações em terceiros não reflitam em outras classes.&lt;/p&gt;
&lt;h2&gt;
  
  
  OCP (Open-Close Principle)
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Bertrand Meyer popularizou este princípio na década de 1980. Em essência, para que os sistemas de software sejam fáceis de mudar, eles devem ser projetados de modo a permitirem que o comportamento desses sistemas mude pela adição de um novo código em vez da alteração do código existente. (MARTIN, Arquitetura limpa. página 103)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Vamos utilizar a resolução do SRP com a classe Reminder e Storage e adicionando uma nova classe para entendermos melhor esse conceito.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// Nova classe&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Note&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Reminder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getTags&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Storage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;storeReminder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Reminder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Alteração necessária&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;storeNote&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Note&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A Apple pediu que você adicionasse uma nova funcionalidade ao sistema de Lembretes, agora os usuários podem criar notas que podem ser incrementadas a qualquer momento, por isso, a mesma possui uma função chamada Increment, assim como Reminder, o conteúdo da classe Note também pode ser armazenado no banco de dados, por isso, criamos mais uma função na classe Storage para fazer tal tarefa.&lt;br&gt;
Aqui criamos uma funcionalidade para nosso sistema (class Notes) e alteramos uma já existente (class Storage), vamos ver o que Martin tem a dizer sobre isso:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Um artefato de software deve ser aberto para extensão, mas fechado para a modificação. Em outras palavras, o comportamento de um atefato de software deve ser extensível sem isso modificar esse artefato. (MARTIN, Arquitetura limpa. Página 114)&lt;br&gt;
Bom, agora está claro que o problema está na classe Storage, porque toda a vez que incrementarmos nosso sistema para alguma entidade que precise ser armazenada em um banco de dados, vamos precisar alterar o storage, e isso mostra a importância desse princípio, você já deve ter visto ou ouvido falar de sistemas tão grandes e legados, que quanto mais ele cresce, mais os desenvolvedores demoram para implementar novas funcionalidades.&lt;br&gt;
Evidentemente, essa é a principal razão de estudarmos arquitetura de software. De forma clara, quando extensões simples nos requisitos forçam mudanças massivas no software, os arquitetos desse sistema de software estão em meio a um fracasso espetacular. (MARTIN, Arquitetura limpa. Página 115)&lt;br&gt;
Vamos tentar resolver esse problema:&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Nova interface&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CanStore&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Note&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;CanStore&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Reminder&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;CanStore&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getTags&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Storage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CanStore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContent&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;Criamos então uma interface que tem de ser respeitada por qualquer entidade que queira armazenar seus dados no banco (interface CanStore) - em muitas literaturas sobre SOLID você vai se deparar com o autor falando que pedaços de software têm de assumir um contrato, e por contrato no typescript estamos falando de interfaces e assumir o mesmo, estamos nos referindo a implementá-las - que possui uma única função chamada &lt;strong&gt;getContent&lt;/strong&gt; com um retorno definido por um conteúdo que é uma &lt;strong&gt;string&lt;/strong&gt;, um identificador único que é um &lt;strong&gt;ID&lt;/strong&gt; e uma data que é um &lt;strong&gt;Date&lt;/strong&gt;, assim qualquer classe que queira ser compatível com &lt;strong&gt;Storage&lt;/strong&gt; precisa apenas implementar essa interface e criar a função de  forma que o retorno seja compatível com o esperado, assim, qualquer nova implementação no sistema não precisará alterar a classe &lt;strong&gt;Storage&lt;/strong&gt; e pode crescer de maneira simples sem necessidade de alterações em outros módulos.&lt;br&gt;
Vamos ver se isso realmente funciona com mais um exemplo:&lt;br&gt;
A Apple agora pediu para você criar uma funcionalidade onde o usuário pode adicionar links com comentários, então criamos a seguite funcionalidade:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CanStore&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Nova funcionalidade&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Links&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;CanStore&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;coment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;coment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Note&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;CanStore&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Increment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Reminder&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;CanStore&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getTags&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Storage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CanStore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContent&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;Percebam que adicionamos apenas a classe &lt;strong&gt;Links&lt;/strong&gt; e formatamos o retorno da função &lt;strong&gt;getStorage&lt;/strong&gt;, sem precisar mexer em mais nenhum lugar do sistema!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;O OCP é uma das forças motrizes por trás da arquitetura de sistemas. Seu objetivo consiste em fazer com que o sistema seja fácil de estender sem que a mudança cause um alto impacto. Para concretizar esse objetivo, particionamos o sistema em componentes e organizamos esses componentes em uma hierarquia de dependência que proteja os componentes de nível mais alto das mudanças em componentes de nível mais baixo. (MARTIN, Arquitetura limpa. Página 115)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Adicionar a função &lt;strong&gt;getContent&lt;/strong&gt; em todas as classes não fere o princípio SRP (de responsábildiade única)?&lt;br&gt;
Não, pois armazenar o dado no banco continua sendo tarefa única e exclusiva da classe &lt;strong&gt;Storage&lt;/strong&gt;, mas a formatação dos dados para ir até o &lt;strong&gt;Storage&lt;/strong&gt; é de responsábilidade de cada classe que implementa &lt;strong&gt;CanStore&lt;/strong&gt;, afinal de contas, cada uma terá um tipo de dado diferente que será traduzido para o formato de &lt;strong&gt;getContent&lt;/strong&gt;, como a tradução será feita é responsabilidade de cada classe.&lt;/p&gt;

&lt;p&gt;O princípio do OCP visa simplesmente prevenir a criação de sistemas super dependentes onde no inicio é muito simples implementar uma feature, mas com o passar do tempo, por mais simples que seja, novas funcionalidades se tornam uma baita dor de cabeça.&lt;/p&gt;
&lt;h3&gt;
  
  
  Sintomas do descumprimento
&lt;/h3&gt;

&lt;p&gt;O principal sintoma do descumprimento do OCP são sistemas de difícil manutenção e evolução, é uma regra tão comumente ignorada que não é raro encontrarmos empresas que sofrem com o orçamento e o tempo para evoluírem seus sistemas, isso cria uma necessidade constante de refatoração.&lt;/p&gt;

&lt;p&gt;Um sistema que precisa ter módulos refatorados não é necessariamente um sistema com uma arquitetura ruim, mas se essa necessidade se torna constante, temos uma prova de que um dos principais princípios do SOLID foi ignorado.&lt;/p&gt;

&lt;p&gt;Os resultados disso no ponto de vista comercial são terríveis, pois o dinamismo do mercado é alto, sendo assim, a direção do negócio precisa ter um prazo ótimo para acompanhar suas mudanças e aproveitar oportunidades, se o cerne da empresa é a tecnologia, essa carga é passada diretamente a seus desenvolvedores e sem uma boa arquitetura fica cada vez mais inviável realizar as implementações necessárias, até que a empresa colapsa por conta de o orçamento ter de ser constantemente expandido até o momento em que se torna mais caro realizar implementações no sistema do que o retorno que as mesmas trazem.&lt;/p&gt;

&lt;p&gt;Para qualquer empresa que dependa de tecnologia, a arquitetura de sistemas é um tópico que pode colocá-la a frente de sua concorrência ou até mesmo acabar com elas, e como dito por Robert C. Martin "O OCP é uma das forças motrizes por trás da arquitetura de sistemas".&lt;/p&gt;
&lt;h2&gt;
  
  
  LSP (Liskov Substitution Principle)
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Para cada objeto o1 de tipo S, houver um objeto o2 de tipo T, de modo que, para todos os programas P definidos em termos de T, o comportamento de P não seja modificado quando o1 for substituído por o2, então S é um subtipo de T. (MARTIN, Arquitetura limpa. Página 123)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Essa definição do LSP feita por sua criadora, Barbara Liskov, pode muitas vezes confundir mais do que esclarecer, então vamos tentar repensar da seguinte forma:&lt;br&gt;
"Classes que herdam funcionalidades de outras classes de nível mais baixo, devem conseguir utilizarem as funcionalidades da de nível inferior sem necessariamente conhecer ou alterar seu comportamento."&lt;/p&gt;

&lt;p&gt;Para entendermos a definição anterior, vamos olhar novamente nossa classe de contagem de horas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Admin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RH&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Admin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;calculateWorkHours&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Financial&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Admin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;calculateWorkHours&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;As classes de &lt;strong&gt;RH&lt;/strong&gt; e &lt;strong&gt;Financial&lt;/strong&gt; tem suas próprias funções para calcular as horas de trabalho de cada funcionário e isso está certo pelo princípio de Liskov, mas vamos imaginar que para solucionar aquele problema do cálculo diferir do RH para o Financeiro, o desenvolvedor responsável decide fazer a seguinte implementação&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Admin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="nf"&gt;calculateWorkHours&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RH&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Admin&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Financial&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Admin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;calculateWorkHours&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No caso, o método original definido na classe Admin atendia ao RH, mas quando foi necessário que o financeiro fizesse uma conta diferente, ele simplesmente herdou a classe Admin e reescreveu a função de calcular horas, fazendo o famoso &lt;em&gt;overriding super class method&lt;/em&gt;. Isso fere a definição acima, pois a classe Financial está estendendo Admin e não utilizando o único método útil para ele (calculateWorkHours), então literalmente não faz sentido estender Admin, pois estamos alterando sua lógica.&lt;br&gt;
Voltando a nossa definição, o caso correto de se estender Admin está na classe RH, pois ela não precisa conhecer a lógica usada em calculateWorkHours do Admin, ela simplesmente sabe que o método retorna um número e isso é suficiente para ela, ou seja, &lt;strong&gt;RH é um subtipo correto de Admin&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Então segundo o princípio de Liskov, sempre está errado sobrescrever um método da classe que você estende?&lt;br&gt;
Não, pois se Financial estivesse utilizando mais de um método de Admin da forma correta e o único caso que ele precise mudar está na função calculateWorkHours, então, tudo bem segundo Liskov, mas isso vai ferir outro princípio (ISP) que veremos a seguir.&lt;/p&gt;
&lt;h3&gt;
  
  
  Sintomas do descumprimento
&lt;/h3&gt;

&lt;p&gt;Para entendermos ainda melhor o princípio de Liskov, vamos a um exemplo um pouco mais próximo ao que Robert C. Martin propõe:&lt;/p&gt;

&lt;p&gt;Digamos que você criou um gateway de pagamentos sensacional, onde qualquer um que tenha um sistema que necessite receber notificações sobre transações em sua conta realiza o cadastro em seu sistema e adiciona um link para receber as notificações de movimentação em sua conta, como um WebHook.&lt;br&gt;
Um dia, um investidor da sua empresa chamado Alan contrata uma equipe de desenvolvedores para criar um sistema que se integra ao seu. Após finalizada a integração eles alegam que o sistema não funciona e explorando melhor o caso, você percebe que não leram sua documentação e o sistema do cliente espera receber campos na requisição com nomes diferentes do que o seu sistema está programado.&lt;/p&gt;

&lt;p&gt;Para ajudar, você decide criar uma classe especial apenas para disparar requisições a esse cliente em específico:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A classe &lt;em&gt;Dispatch&lt;/em&gt; que faz as requisições&lt;/li&gt;
&lt;li&gt;Você cria uma classe &lt;em&gt;DispatchToAlan&lt;/em&gt; que é um subtipo de &lt;em&gt;Dispatch&lt;/em&gt; porem altera o nome dos campos de envio.
Bom, isso se resolve facilmente com um &lt;em&gt;if&lt;/em&gt; certo? Sim, se resolve apenas com uma simples condicional, mas imagine que sua empresa comece a atrair cada vez mais investidores e de novo esse problema se repete, como você abriu um precedente com o desenvolvedor anterior, começa a criar cada vez mais subtipos de &lt;em&gt;Dispatch&lt;/em&gt; para atender as necessidades de novos clientes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aqui podemos tirar algumas conclusões, a primeira é que sua documentação deve estar horrível para que ninguém entenda e programe os campos com os nomes corretos para o recebimento, mas pior ainda, é que nenhum dos Subtipos de &lt;em&gt;Dispatch&lt;/em&gt; que você está criando é válido, pois todos eles precisam alterar a lógica da classe original para atender aos clientes.&lt;/p&gt;

&lt;p&gt;Isso fere gravemente o princípio do OCP, pois como esses subtipos de Dispatch alteram sua lógica em algum nível, se Dispatch for alterado por alguma razão, você pode precisar alterar todos esses subtipos, o que também fere o SRP, pois essas classes passam a ter mais de uma razão para mudar (Sendo elas a primeira que é válida, caso o seu cliente mude o tipo de recebimento e a segunda inválida, caso você mude o comportamento da classe original).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;O LSP pode, e deve ser estendido ao nível da arquitetura. Uma simples violação da capacidade de substituição pode contaminar a arquitetura do sistema com uma quantidade significante de mecanismos extras. (MARTIN, Arquitetura limpa. Página 123)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  ISP (Interface Segregation Principle)
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Este princípio orienta que os projetistas de software evitem depender de coisas que não usam. (MARTIN, Arquitetura limpa. Página 103)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sempre é melhor criarmos várias interfaces para diferentes implementações do que apenas uma generalista.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Admin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;payEmployees&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
    &lt;span class="nf"&gt;updateInfo&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
    &lt;span class="nf"&gt;getLatestPayments&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Payments&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="nf"&gt;calculateWorkHours&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RH&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Admin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;payEmployees&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Function not available for this actor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;updateInfo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// realiza a tarefa&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;getLatestPayments&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Function not available for this actor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;calculateWorkHours&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// realiza a tarefa&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Financial&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Admin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;payEmployees&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// realiza a tarefa&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;updateInfo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Function not available for this actor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;getLatestPayments&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// realiza a tarefa&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;calculateWorkHours&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// realiza a tarefa&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O que era nossa classe Admin se tornou uma interface a ser implementada, e essa interface declara que Administradores podem pagar funcionários, atualizar suas informações, buscar os últimos pagamentos e calcular suas horas de trabalho.&lt;br&gt;
O problema aqui é que nem todos os Administradores podem realizar todas as tarefas, então no caso do RH, que não pode pagar funcionários ou buscar os últimos pagamentos, temos que disparar um erro caso a função seja chamada, o mesmo para o Financeiro que não pode atualizar as informações do profissional.&lt;br&gt;
É sempre muito prejudicial depender de módulos que contenham mais do que você precisa, isso pode ocasionar bugs sérios em seus sistemas por uma falta de atenção de algum desenvolvedor que não sobrescreveu, além de problemas de segurança e muitas vezes ferir principalmente os princípios do OCP e SRP, por que, afinal de contas, se mais classes implementam Admin e você precisa alterar o Admin, vai precisar alterar as classes (que fere o OCP), ter muita coisa embarcada no Admin vai fazer com que ele tenha mais de um motivo para ser alterado (Já que vários atores o implementam e isso fere o SRP).&lt;/p&gt;

&lt;p&gt;A solução para isso é a Segregação de interfaces, como diz o próprio nome do princípio:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CanPay&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;payEmployees&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CanUpdate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;updateInfo&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CanSearchPayments&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;getLatestPayments&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Payments&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CanCalculate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;calculateWorkHours&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RH&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;CanUpdate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CanCalculate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;updateInfo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// realiza a tarefa&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;calculateWorkHours&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// realiza a tarefa&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Financial&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;CanPay&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CanSearchPayments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;CanCalculate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;payEmployees&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// realiza a tarefa&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;getLatestPayments&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// realiza a tarefa&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;calculateWorkHours&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// realiza a tarefa&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;Observem que dessa forma cada classe implementa apenas o que convém a ela, e além de tornar nosso código muito mais legível e intuitivo, o torna mais seguro, previne erros inesperados e que quebremos os princípios de OCP (não temos de alterar protocolos ou classes a cada nova implementação), SRP (cada classe implementa apenas o que é de sua única responsabilidade), e LSP (por não termos de sobrescrever funcionalidades).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Depender de algo que contém itens desnecessários pode causar problemas inesperados.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Sintomas do descumprimento
&lt;/h3&gt;

&lt;p&gt;A dificuldade de compreensão de um sistema é um grave problema, pois o tempo de evolução do mesmo se torna muito maior e a curva de aprendizagem de novos desenvolvedores cresce com a complexidade desnecessária.&lt;br&gt;
Depender de modulos desnecessários abre uma brexa de segurança muito grave, como podemos ver na citação abaixo:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Considere um arquiteto que está trabalhando em um sistema chamado S, em que deseja incluir o framework F. Agora, suponha que os próprios autores ligaram F a um banco de dados D específico. Então S depende de F que depende de D.&lt;br&gt;
Agora, suponha que D contenha recursos que F não usa e que, portanto, não são essenciais a S. Qualquer mudança nesses recursos de D pode muito bem forçar a reimplantação de F e, por extensão, a reimplantação de S.&lt;br&gt;
Pior ainda, uma falha em um dos recursos de D pode causar falhas em F e S. (MARTIN, Arquitetura limpa. Página 132)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  DIP (Dependency Inversion Principle)
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Segundo o princípio da inversão de dependência DIP, os sistemas mais flexíveis são aqueles em que as dependências de código-fonte se referem apenas a abstrações e não a itens concretos (MARTIN, Arquitetura limpa. Página 135)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Acredito que a definição de Martin para este princípio seja a mais direta e compreensível de todas, ainda mais para nós que trabalhamos com Typescript, e dado que já conhecemos todos os outros princípios, este será mais fácil, vamos ver o exemplo a seguir:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;
    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Storage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;seq&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Sequelize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CanStore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seq&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContent&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/.%2Fassets%2FDIP-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/.%2Fassets%2FDIP-1.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Aqui vemos que Storage é inicializado com Sequelize, que por sua vez é uma implementação concreta de interações com o banco de dados, que não está em nosso controle mudar, ou prevenir que a mesma mude.&lt;br&gt;
Storage está em nossa regra de negócio (Domain), e o Sequelize está em nossa Infraestrutura (Infra), percebam que a Infra está apontando para Domain, e isso significa que nossa regra de negócio depende da nossa infraestrutura, isso é terrível, pois, a Domain é definido pelo cliente do sistema, é nossa regra base, se a tecnologia que usamos influencia nisso, então quer dizer que mudanças nessa tecnologia podem mudar nosso negócio, idealmente é nosso negócio que deve determinar as tecnologias a serem usadas e não depender delas.&lt;br&gt;
O DIP nos ajuda a solucionar esse problema da seguinte forma:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/.%2Fassets%2FDIP-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/.%2Fassets%2FDIP-2.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Veja a codificação da figura acima:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;
    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DatabaseAdapter&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Database&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;seq&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Sequelize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// insere dados no banco&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DbReturn&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// busca dado pelo id&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Database&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DbReturn&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Storage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CanStore&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getContent&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;Percebam que agora temos um protocolo (Interface Database) para como devemos lidar com o banco de dados em si, e nossa classe &lt;strong&gt;Storage&lt;/strong&gt; aponta para este protocolo, a qual é uma abstração, também criamos a classe &lt;strong&gt;DatabaseAdapter&lt;/strong&gt; que implementa este protocolo, isso tudo significa que caso seja necessário trocar o ORM que estamos utilizando, quem deve fazer isso é a classe DatabaseAdapter que respeita o contrato definido em &lt;strong&gt;Database&lt;/strong&gt;, mas nenhuma alteração será necessária em Storage.&lt;/p&gt;

&lt;p&gt;Ah, mas se a tecnologia de banco de dados mudar, vamos precisar alterar a classe DatabaseAdapter, e isso fere o princípio OCP, não?&lt;br&gt;
Não, por conta do SRP, pois a classe DatabaseAdapter só tem uma única razão para mudar, o banco de dados que estamos utilizando.&lt;/p&gt;

&lt;p&gt;Extra:&lt;br&gt;
Para sistemas que aderem ao DIP, é muito comum vermos Factories para construir as classes, do tipo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;makeStorage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Storage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DatabaseAdapter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Sequelize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Storage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E ao ter muitas classes que dependem de vários adaptadores, pode ficar muito chato montar essas factories, por isso recomendo que você de uma olhada no &lt;a href="https://inversify.io" rel="noopener noreferrer"&gt;Inversify&lt;/a&gt;, existe uma curva de aprendizado para usar a ferramenta, mas com o conhecimento que você adquiriu durante este conteúdo, pode ser uma ótima adição a sua Stack.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sintomas do descumprimento
&lt;/h3&gt;

&lt;p&gt;Alterações em modulos não essenciais necessitam de alterações em módulos essenciais.&lt;br&gt;
O que quero dizer é que seu negócio se torna dependente de suas ferramentas, sobre o seu negócio você tem controle, sobre as ferramentas que você utiliza, não, então depender delas é literalmente um tiro no pé.&lt;/p&gt;

&lt;p&gt;Finalmente terminamos de ver todos os princípios do SOLID, e agora no final fica claro como os mesmos se complementam, mas para realmente fixarmos esse conhecimento, vamos praticar um pouco.&lt;/p&gt;
&lt;h1&gt;
  
  
  Exercícios
&lt;/h1&gt;

&lt;p&gt;1) Um novo departamento é criado dentro da Apple e dois desenvolvedores são encarregados de criar funcionalidades que atendam a este novo departamento. As demandas dependem da integração de um banco de dados não relacional e do sistema de autenticação que já existe, então eles criam uma interface que define as funcionalidades desse novo elemento na infraestrutura, programam uma classe que atenda essa interface, então criam a classe que atende, de fato, o novo departamento, esta,  é inicializada com a classe abstrata do novo banco de dados.&lt;br&gt;
Eles percebem que vão precisar alterar a classe de autenticação para que possam utilizar seus recursos junto a classe do novo departamento.&lt;br&gt;
Os desenvolvedores estão enfrentando este problema por que algum principio do SOLID foi ignorado, qual foi?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SRP&lt;/li&gt;
&lt;li&gt;OCP&lt;/li&gt;
&lt;li&gt;LSP&lt;/li&gt;
&lt;li&gt;ISP&lt;/li&gt;
&lt;li&gt;DIP

Ver resposta
OCP
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;2) Uma empresa percebe que está gastando muito com uma ferramenta que faz buscas em seu banco de dados não relacional, então decidem mudar para outra mais barata, porém, os desenvolvedores informam que vão precisar reestruturar a regra de negócio do sistema por causa disso, qual princípio do SOLID foi violado nesse caso?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SRP&lt;/li&gt;
&lt;li&gt;OCP&lt;/li&gt;
&lt;li&gt;LSP&lt;/li&gt;
&lt;li&gt;ISP&lt;/li&gt;
&lt;li&gt;DIP&lt;/li&gt;
&lt;/ul&gt;


    Ver resposta
    DIP


&lt;p&gt;3) Um hacker invadiu o sistema da Apple conseguindo acesso a uma conta de RH. Ele fez movimentações financeiras que não deveriam ser permitidas ao RH, isso só foi possivel porque um desenvolvedor extendeu a classe Administrativa que permitia essas operações e não sobrescreveu as funcionalidades de movimentação financeira para o RH, deixando a brecha que resultou nesse prejuizo, qual princípio do SOLID teria prevenido o ocorrido?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SRP&lt;/li&gt;
&lt;li&gt;OCP&lt;/li&gt;
&lt;li&gt;LSP&lt;/li&gt;
&lt;li&gt;ISP&lt;/li&gt;
&lt;li&gt;DIP &lt;/li&gt;
&lt;/ul&gt;


    Ver resposta
    ISP


&lt;p&gt;4) Você está passando por uma terrível dor de cabeça, pois toda vez que uma nova demanda de funcionalidade é destinada ao sistema em que trabalha é necessário mudar a classe responsável por registrar os logs do sistema, isso acontece por que a classe de Logs não está respeitando qual princípio?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SRP&lt;/li&gt;
&lt;li&gt;OCP&lt;/li&gt;
&lt;li&gt;LSP&lt;/li&gt;
&lt;li&gt;ISP &lt;/li&gt;
&lt;li&gt;DIP &lt;/li&gt;
&lt;/ul&gt;


    Ver resposta
    SRP


&lt;p&gt;5) Sobrescrever todas as funcionalidades de uma classe que você está estendendo não faz sentido, mas isso acontece em diversos sistemas onde os arquitetos não fazem um bom trabalho na hora de relacionar suas entidades, para estes arquitetos, qual principio do SOLID está sendo violado?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SRP&lt;/li&gt;
&lt;li&gt;OCP&lt;/li&gt;
&lt;li&gt;LSP&lt;/li&gt;
&lt;li&gt;ISP &lt;/li&gt;
&lt;li&gt;DIP &lt;/li&gt;
&lt;/ul&gt;


    Ver resposta
    LSP



&lt;h1&gt;
  
  
  SOLID na prática
&lt;/h1&gt;

&lt;p&gt;Conhecer os princípios do SOLID é o primeiro passo para se tornar um bom arquiteto de sistemas, mas para o total aproveitamento destes fundamentos, você deve conseguir identificar suas aplicações de forma rápida e intuitiva, para que isso aconteça, precisamos praticar.&lt;br&gt;
Aqui proponho uma linha de raciocínio que pode facilitar muito seu trabalho.&lt;/p&gt;
&lt;h2&gt;
  
  
  Defina seus Atores
&lt;/h2&gt;

&lt;p&gt;Como vimos durante o SRP, os atores são as chaves da nossa construção, o sistema é desenvolvido para eles e os módulos de alto nível que desenvolvermos devem ter a propriedade de só serem modificados mediante a necessidade de um e apenas um destes atores.&lt;br&gt;
Ou seja, nunca comece a desenvolver um sistema perguntando o que ele vai fazer, mas sim &lt;strong&gt;quem vai utilizá-lo&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Vamos então imaginar o desenvolvimento de um sistema para um e-commerce.&lt;/p&gt;

&lt;p&gt;Quem vai utilizá-lo?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consumidor&lt;/li&gt;
&lt;li&gt;Operador&lt;/li&gt;
&lt;li&gt;Gerente&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nesse cenário, quais são as atribuições de cada um destes atores?&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Consumidor&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Quer acessar o sistema para olhar catálogos e comprar itens.&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Operador&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Insere novos produtos no sistema e pode atualizar seus preços e informações.&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Gerente&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Existe para controlar as propriedades do sistema, pode adicionar novos operadores ou removê-los e alterar as taxas globais para compra de produtos.&lt;/p&gt;

&lt;p&gt;Dessa forma, já estabelecemos nossas entidades mais primitivas e o que podem fazer em nosso sistema, traduzindo para o código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Customer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Products&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nf"&gt;buy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Operator&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;addProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nf"&gt;updateProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Manager&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;addOperator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nf"&gt;removeOperator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nf"&gt;changeFees&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui começamos a rascunhar o sistema e como ele deve se comportar, mas ainda faltam requisitos, principalmente os de caso base, por exemplo, como cadastrar um gerente na plataforma? Já que dependemos dele para cadastrar operadores e os clientes dependem dos operadores para ter produtos a serem visualizados e comprados.&lt;/p&gt;

&lt;p&gt;Uma coisa podemos dizer que os 3 atores tem em comum, todos são usuários, que precisam se cadastrar, trocar suas senhas, caso necessário, verificarem seus perfis, etc.&lt;br&gt;
Vamos desenhar uma interface para usuário:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nf"&gt;changePassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newPassword&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Estaria correto dizer que Customer, Operator e Manager são subtipos válidos de User?&lt;/p&gt;

&lt;p&gt;Isso quem nos responde é Barbara Liskov com o LSP, pois o comportamento de User não depende de maneira alguma do comportamento de nenhum dos 3 atores, o que significa que os mesmos não precisam sobrescrevê-los e sim, são subtipos válidos.&lt;/p&gt;

&lt;p&gt;Agora temos então 4 módulos de sistema que respeitam o SRP, pois para o caso dos 3 atores apenas eles podem alterar seus comportamentos e para o caso do User, o comportamento só seria alterado se e apenas se a regra de usuários geral do sistema fosse alterada.&lt;/p&gt;

&lt;p&gt;Ainda falta uma pergunta, se adicionarmos mais um Ator a este sistema, como um Coordenador, por exemplo, algum outro módulo teria de ser alterado para que o mesmo fosse feito? Ou se alterassemos o User, seria necessária uma alteração de seus subtipos?&lt;br&gt;
Não, um Coordenador estenderia o User, e para todos os Atores que até o momento implementam User, não precisam sobrescrevê-lo, então estamos respeitando o OCP até o momento.&lt;/p&gt;

&lt;p&gt;Apenas nesse pequeno exercício já resolvemos 3 princípios: SRP, OCP e LSP.&lt;/p&gt;
&lt;h2&gt;
  
  
  Entenda suas dependências
&lt;/h2&gt;

&lt;p&gt;Cuidado com essa etapa, entender as dependências de um sistema não é escolher as ferramentas dele, mas sim o que essas ferramentas precisam ter para nos atender.&lt;/p&gt;

&lt;p&gt;A dependência mais intuitiva que podemos ver aqui é um lugar para registrarmos nossos dados, então precisamos criar um tipo para definir o que utilizaremos de um banco de dados, vamos analisar ator por ator e entender suas necessidades:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Customer: Leitura e Escrita (Afinal de contas, a compra tem de ser registrada em algum lugar)&lt;/li&gt;
&lt;li&gt;Operator: Escrita e Atualização&lt;/li&gt;
&lt;li&gt;Manager: Escrita e Atualização&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ou seja, as funcionalidades necessárias de nosso banco são: Leitura, Escrita e Atualização. Percebam que não precisamos deletar dados em nenhum momento com nossas entidades, assim, partir do pré-suposto de que um CRUD é o mínimo necessário para uma implementação de banco de dados está errado.&lt;/p&gt;

&lt;p&gt;Vamos escrever nossas interfaces para essa dependência:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CanWrite&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CanChange&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CanRead&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;startAt&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para respeitar o ISP, tivemos de criar um protocolo para cada necessidade, pois o Customer precisa Ler e Escrever, o Operator e o Manager precisam Atualizar e Escrever, ou seja, se tivéssemos unido a função Update e Create em uma mesma interface, o Customer que só precisa Escrever teria a dependência da Atualização também, o que vai contra nosso princípio e já falamos anteriormente sobre os sérios problemas disso.&lt;/p&gt;

&lt;p&gt;Nosso sistema também precisa ser exposto de alguma forma, seja como uma biblioteca ou aplicativo, mas aqui vamos escolher uma API, então vamos fazer o mesmo exercício do banco de dados para essa dependência.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Customer: GET e POST&lt;/li&gt;
&lt;li&gt;Operator: POST e PUT&lt;/li&gt;
&lt;li&gt;Manager: POST e PUT&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Viram como caímos no exato mesmo modelo do banco de dados? Vamos criar as interfaces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CanGet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;func&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Controller&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CanPost&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;func&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Controller&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CanPut&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;func&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Controller&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E pronto, temos nossas dependências estabelecidas, respeitando o ISP e finalmente vamos às ferramentas:&lt;/p&gt;

&lt;h2&gt;
  
  
  Defina suas ferramentas
&lt;/h2&gt;

&lt;p&gt;Já sabemos o que precisamos de nossas ferramentas, então para o banco de dados, vamos escolher o Sequelize como nosso ORM (Dica: sempre tente tirar o máximo proveito que puder do typescript, escolha ferramentas que tenham tipos declarados ou que possuam alguma lib para tal, como no caso do Firestore (Google) que não possui as tipagens de modelo, mas temos o &lt;a href="https://www.npmjs.com/package/firestore-wrapper" rel="noopener noreferrer"&gt;firestore-wrapper&lt;/a&gt; que lhe auxilia em tal tarefa) e o Express como o runtime de nossa aplicação.&lt;/p&gt;

&lt;p&gt;A interface dos nossos adaptadores nós já temos, basta agora codificar suas classes com a ferramenta escolhida:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReadAdapter&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;CanRead&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;constructor &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;seq&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Sequelize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;startAt&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// lógica da função&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como os módulos de nosso sistema estarão apontando para interfaces abstratas que são posteriormente implementadas por adaptadores que serão injetados nos módulos, estamos aqui respeitando o último princípio DIP.&lt;/p&gt;

&lt;p&gt;Bom, até aqui acredito que você já tenha entendido a linha de raciocínio para se planejar um sistema com os princípios do SOLID em mente, que tal realmente colocarmos a mão na massa e criar um sistema simples com todas essas implementações e testes para cada um de nossos módulos a fim de garantirmos o comportamento esperado?&lt;br&gt;
Isso vai ficar para o próximo artigo, enquanto isso, vamos praticar mais um pouco.&lt;/p&gt;
&lt;h1&gt;
  
  
  Exercícios
&lt;/h1&gt;

&lt;p&gt; 1) Analise o programa definido a seguir:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;
    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Circle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Rectangle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CalculateArea&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;circleCalculator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;circle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Circle&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PI&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;circle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;circle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;rectangleCalculator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rectangle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Rectangle&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;rectangle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;rectangle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&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;Aqui temos um caso clássico de uma classe que calcula a área de diferentes &lt;strong&gt;Formas&lt;/strong&gt;, temos o &lt;strong&gt;Círculo&lt;/strong&gt; e o &lt;strong&gt;Retângulo&lt;/strong&gt;, porém, este programa está violando um princípio, qual é este princípio?&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Dica
Tente adicionar mais uma forma, como o Triângulo, por exemplo.



Ver resposta
OCP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;1.1) Escreva um programa que corrija essa falha.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ver resposta

interface Shape {
    calculateArea(): number;
}

class Circle implements Shape {
    constructor(public readonly radius: number) {}

    public calculateArea() {
        return Math.PI * (this.radius * this.radius);
    }
}

class Rectangle implements Shape {
    constructor(public readonly width: number, public readonly height: number) {}

    public calculateArea() {
        return this.width * this.height;
    }
}

class CalculateArea {
    public calculate(shape: Shape): number {
        return shape.calculateArea();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;2) Continuando com nosso programa que calcula formas geométricas, vamos replicar um caso definido por Martin sobre um dos princípios, analise o código a seguir:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;
    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Rectangle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Square&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Rectangle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;side&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;side&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;side&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;Qual princípio do SOLID está sendo violado? Por quê?&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Dica
Square está alterando o comportamento de Rectangle



Ver resposta
LSP, pois a classe Square está estendendo Rectangle, mas os lados de um quadrado devem ter sempre o mesmo valor, enquanto o retangulo pode ter altura e largura indpendentes, tornando-se assim, um subtipo incoerente.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt; 2.1) Escreva um programa que corrija essa falha.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ver resposta

class Rectangle {
    constructor(public readonly width: number, public readonly height: number) {}
}

class Square {
    constructor(public readonly side: number) {}
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;3) Considere o programa abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;    &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ShapeOperations&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;calculateArea&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
        &lt;span class="nf"&gt;countVertex&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
        &lt;span class="nf"&gt;calcDiameter&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Square&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;ShapeOperations&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;side&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="nf"&gt;calculateArea&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;side&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;side&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;countVertex&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;calcDiameter&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;side&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Circle&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;ShapeOperations&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="nf"&gt;calculateArea&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PI&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;countVertex&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Circle has no vertex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;calcDiameter&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;radius&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&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;Qual princípio do SOLID está sendo violado? Por quê?&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Dica
Circle não pode implementar um contador de vértices



Ver resposta
ISP, se o circulo não pode implementar um contador de vértices, ele não deveria estender essa interface
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;3.1) Escreva um programa que corrija essa falha.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ver resposta

interface HasArea {
    calculateArea(): number
}

interface HasVertex {
    countVertex(): number
}

interface HasDiameter {
    calcDiameter(): number
}

class Square implements HasArea, HasVertex, HasDiameter {
    constructor(public readonly side: number) {}
    calculateArea(): number {
        return this.side * this.side;
    }
    countVertex(): number {
        return 4
    }
    calcDiameter(): number {
        return this.side * Math.sqrt(2);
    }
}

class Circle implements HasArea, HasDiameter {
    constructor(public readonly radius: number) {}
    calculateArea(): number {
        return Math.PI * (this.radius * this.radius);
    }

    calcDiameter(): number {
        return this.radius * 2;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;h1&gt;
  
  
  Próximos passos
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Leia o livro base para a construção desse conteúdo: Arquitetura Limpa por Robert C. Martin.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Com os conhecimento adquiridos nesse conteúdo, o livro do famoso Uncle Bob será muito mais palatável, mas não substitui a leitura do mesmo, que vai te apresentar outros exemplos com abordagens diferentes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tenha meios de planejar seus sistemas fora a escrita de interfaces.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;UML é uma ferramenta muito poderosa para te ajudar no processo de planejamento, nesse conteúdo não falamos sobre isso, pois o foco aqui é o SOLID com Typescript, porém os diagramas são uma forma muito mais eficiente de entender como e o que será construido do que sair definindo interfaces, eles nos ajudam principalmente a entendermos como serão as relações entre nossas classes e entidades, quais comportamentos são esperados de cada uma e principalmente, nos ajudam a identificar os erros e incoerências dos programas antes de colocarmos a mão na massa. Um bom programador passa mais tempo no papel que no código.&lt;/p&gt;

&lt;p&gt;Existem muitos artigos sobre o tema, como &lt;a href="http://www.univasf.edu.br/~marcelo.linder/arquivos_pooC4/aulas/aula4.pdf" rel="noopener noreferrer"&gt;O do professor Marcelo Linder&lt;/a&gt;, que de uma forma simples te apresenta os conceitos básicos, mas se você quiser um conteúdo mais completo, minha recomendação é o livro &lt;a href="https://www.google.com.br/books/edition/UML_2_Uma_Abordagem_Pr%C3%A1tica/mJxMDwAAQBAJ?hl=pt-BR&amp;amp;gbpv=1&amp;amp;printsec=frontcover" rel="noopener noreferrer"&gt;UML 2 - Uma Abordagem Prática&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Estude DDD.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Neste conteúdo eu propus uma linha de raciocionio para você começar a formular seus sistemas, porém, é importante que você entenda sobre os processos mais aceitos de design de software.&lt;br&gt;
Proposto por Eric Evans em seu livro &lt;a href="https://www.amazon.com.br/Domain-Driven-Design-Eric-Evans/dp/8550800651/ref=sr_1_1?__mk_pt_BR=%C3%85M%C3%85%C5%BD%C3%95%C3%91&amp;amp;crid=1X1113FEZIAG8&amp;amp;keywords=Domain-Driven+Design%3A+Atacando+as+complexidades+no+cora%C3%A7%C3%A3o+do+software&amp;amp;qid=1666016237&amp;amp;qu=eyJxc2MiOiIwLjUxIiwicXNhIjoiMC4wMCIsInFzcCI6IjAuMDAifQ%3D%3D&amp;amp;sprefix=domain-driven+design+atacando+as+complexidades+no+cora%C3%A7%C3%A3o+do+software%2Caps%2C174&amp;amp;sr=8-1" rel="noopener noreferrer"&gt;Domain-Driven Design: Atacando as complexidades no coração do software&lt;/a&gt; em 2003, o DDD é fundamental para que engenheiros de software consigam se comunicar bem com os experts do negócio e traduzir as necessidades de maneira efetiva para o sistema.&lt;br&gt;
O livro é minha principal recomendação, mas caso queira uma introdução um pouco mais direta, o &lt;a href="https://fullcycle.com.br/domain-driven-design/" rel="noopener noreferrer"&gt;artigo da FullCycle sobre o assunto&lt;/a&gt; é bem interessante.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Saiba trabalhar em equipe.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Depois de se tornar um especialista em arquitetura de sistemas, precisa trabalhar com outros desenvolvedores de maneira eficiente, para que depois de tudo bem planejado, cada um ataque um domínio do sistema a ser desenvolvido, e para que vocês não caiam no famoso ditado: O que um desenvolvedor faz em uma semana, dois fazem em duas.&lt;/p&gt;

&lt;p&gt;Com um sistema bem desenhado e planejado, esse trabalho se torna algo muito fácil e para ajudar ainda mais, recomendo que estude sobre &lt;a href="https://blog.betrybe.com/git/git-flow/" rel="noopener noreferrer"&gt;GitFlow&lt;/a&gt; e utilize sempre o &lt;a href="https://www.conventionalcommits.org/en/v1.0.0/" rel="noopener noreferrer"&gt;Conventional Commits&lt;/a&gt; para ajudar seus colegas a entenderem o que você está fazendo.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>architecture</category>
      <category>tutorial</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Why should you consider adding Rust to your stack?</title>
      <dc:creator>Leonardo Bonetti</dc:creator>
      <pubDate>Wed, 17 Aug 2022 17:45:30 +0000</pubDate>
      <link>https://dev.to/leonardbonetti/why-should-you-consider-adding-rust-to-your-stack-4hil</link>
      <guid>https://dev.to/leonardbonetti/why-should-you-consider-adding-rust-to-your-stack-4hil</guid>
      <description>&lt;p&gt;Rust is a high-level language with low-level performance, which brings us to our first ready:&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;Unlike languages like C or C++, developing in rust is extremely fast and particularly satisfying, with the compiler extremely efficient in pointing out problems in the code, it becomes your friend and not your enemy (As I particularly felt developing applications in C around mid-2012 ).&lt;br&gt;
It's a memory-safe language, forget the problems with null pointers and etc, garbage collector doesn't exist here because of the Ownership strategy.&lt;br&gt;
Everything in the language is aimed at giving you the necessary possibilities to create the most performative systems possible with the practicality of interpreted languages like JS&lt;/p&gt;

&lt;h2&gt;
  
  
  Expand your technical vision
&lt;/h2&gt;

&lt;p&gt;The market demands more and more speed of delivery from developers and languages ​​like JS/TS help us a lot at this point, it has gigantic communities and many ready-made solutions, which hardly a JS developer will worry about concurrency problems, thread starving, efficiency in memory allocation, etc.&lt;br&gt;
Each technology has its place and will better serve different situations, in terms of productivity, JS/TS is undoubtedly the best possible solution, depending on the needs of the system, it guarantees a fast and concise delivery, the problem starts when we tend to use the same technology for EVERYTHING.&lt;br&gt;
Chances are, if you decide to learn RUST, you won't use it on your entire system, but rather create services to meet very specific demands that require extraordinary performance and security (You can even do everything in Rust, but as I said, each technology has its place and it would not be smart to do so in most situations).&lt;br&gt;
I will exemplify with my work case, my company builds systems for financial solutions, in the case of a brokerage firm, 80% of the system is CRUDs, and for these 80% nothing better than a super productive language, but the 20% that is the order book used in trading and user balance control where atomicity and performance have to be guaranteed, that's where Rust shines, it gives you options that in the comfort of working so long with interpreted languages, you end up forgetting that exist, it brings you closer to the most basic fundamentals of building a computational system, giving you possibilities and a security that no other interpreted language will provide you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Opportunities
&lt;/h2&gt;

&lt;p&gt;The Rust ecosystem is infinitely smaller compared to JS/TS, although I've been a language lover since 2019, I'm just now feeling full security in bringing it to my company's stack, as it's getting more and more mature, but far from being extremely comprehensive, this means a fertile environment for growth opportunities, the reasons mentioned above make Rust a very desired language, but there is a great shortage of professionals and tools to help development.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>rust</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Por que você deveria considerar adicionar Rust a sua stack?</title>
      <dc:creator>Leonardo Bonetti</dc:creator>
      <pubDate>Wed, 17 Aug 2022 17:25:59 +0000</pubDate>
      <link>https://dev.to/leonardbonetti/por-que-voce-deveria-considerar-adicionar-rust-a-sua-stack-15jg</link>
      <guid>https://dev.to/leonardbonetti/por-que-voce-deveria-considerar-adicionar-rust-a-sua-stack-15jg</guid>
      <description>&lt;p&gt;Rust é uma linguagem de alto nível com performance de uma de baixo nível, isso já nos leva ao nosso primeiro pronto:&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance
&lt;/h2&gt;

&lt;p&gt;Diferente de linguagens como C ou C++, desenvolver em rust é extremamente rápido e particularmente satisfatório, com compilador extremamente eficiente em apontar problemas no código, ele se torna seu amigo e não seu inimigo (Como particularmente me sentia desenvolvendo aplicações em C por meados de 2012).&lt;br&gt;
É uma linguagem memory-safe, esqueça os problemas com null pointers e etc, garbage collector não existe aqui por conta da estratégia do &lt;a href="https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html"&gt;Ownership&lt;/a&gt;.&lt;br&gt;
Tudo na linguagem é voltado a te dar as possibilidades necessárias para criar os sistemas mais performáticos possíveis com a praticidade de linguagens interpretadas como JS&lt;/p&gt;

&lt;h2&gt;
  
  
  Ampliar sua visão técnica
&lt;/h2&gt;

&lt;p&gt;O mercado demanda cada vez mais velocidade de entrega dos desenvolvedores e linguagens como JS/TS nos ajudam demais nesse ponto, tem comunidades gigantescas e muitas soluções prontas, que dificilmente um desenvolvedor JS vai se preocupar com problemas de concorrência, starving de threads, eficiência em alocação de memória e etc.&lt;br&gt;
Cada tecnologia tem seu lugar e vai atender melhor a diferentes situações, em ponto de produtividade, JS/TS é sem dúvida a melhor solução possível, dependendo da necessidade do sistema, ela te garante uma entrega rápida e concisa, o problema começa quando tendemos a usar a mesma tecnologia para TUDO.&lt;br&gt;
Provavelmente, se você decidir aprender RUST, não vai usá-lo em todo o seu sistema, mas sim criar serviços para atender a demandas muito específicas que exigem uma performance e segurança extraordinária (Você até pode fazer tudo em Rust, mas como já dito, cada tecnologia tem seu lugar e não seria inteligente fazer isso na maioria das situações).&lt;br&gt;
Vou exemplificar com meu caso de trabalho, minha empresa constrói sistemas para soluções financeiras, no caso de uma corretora, 80% do sistema são CRUDs, e para esses 80% nada melhor do que uma linguagem super produtiva, mas os 20% que é o livro de ordens usado em negociações e o controle de saldo dos usuários onde a atomicidade e performance tem de ser garantidas, é ai que o Rust brilha, ele te dá opções que no conforto de se trabalhar tanto tempo com linguagens interpretadas, você acaba esquecendo que existem, ele te aproxima dos fundamentos mais básicos da construção de um sistema computacional, te dando possibilidades e uma segurança que nenhuma outra linguagem interpretada vai te proporcionar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Oportunidades
&lt;/h2&gt;

&lt;p&gt;O ecossistema do Rust é infinitamente menor comparado ao JS/TS, apesar de eu ser um amante da linguagem desde 2019, só agora estou sentindo segurança plena em trazer ela para a stack da minha empresa, pois está cada vez mais madura, mas longe de ser extremamente abrangente, isso significa um ambiente fértil de oportunidades de crescimento, os motivos citados acima tornam Rust uma linguagem muito desejada, mas existe uma grande escassez de profissionais e ferramentas para o auxílio do desenvolvimento.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>javascript</category>
      <category>rust</category>
      <category>programming</category>
    </item>
    <item>
      <title>Arquitetura orientada ao Ator</title>
      <dc:creator>Leonardo Bonetti</dc:creator>
      <pubDate>Wed, 22 Dec 2021 14:17:55 +0000</pubDate>
      <link>https://dev.to/leonardbonetti/arquitetura-orientada-ao-ator-1k55</link>
      <guid>https://dev.to/leonardbonetti/arquitetura-orientada-ao-ator-1k55</guid>
      <description>&lt;p&gt;Propor um modelo de arquitetura de software que orienta o sistema a seus utilizadores.&lt;/p&gt;

&lt;p&gt;Apesar de parecer redundante dizer que um sistema deve ser desenvolvido a partir da orientação de seus utilizadores, um dos maiores problemas do processo de desenvolvimento é que os programadores tendem a criar mecânicas que façam sentido no ponto de vista de quem desenvolve, mas não necessariamente no ponto de vista de quem o utiliza, essa prática leva ao processo comum de utilizadores não se adaptarem a mecânicas que parecem ser simples e intuitivas.&lt;/p&gt;

&lt;p&gt;O modelo descrito a seguir extende os conceitos definidos por Robert C. Martin em &lt;em&gt;Clean Architecture&lt;/em&gt;: &lt;em&gt;A Craftsman’s Guide to Software Structure&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Atores
&lt;/h2&gt;

&lt;p&gt;Atores são basicamente quem stabelece quais regras o sistema deve cumprir e qual comportamento esperado, antes de começarmos a pensar em desenvolver nossa aplicação, temos de estabelecer quem são seus atores, eles podem ser usuários tradicionais ou outros sistemas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Atores são todos que interagem com a aplicação.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Para desenvolvermos esse raciocinio, vamos propor um sistema que iremos construir ao decorrer deste artigo, a aplicação escolhida é um simples sistema de loja.&lt;/p&gt;

&lt;p&gt;Normalmente quando iniciamos a produção de um sistema, nos questionamos sobre as funcionalidades que ele terá, no modelo A.O.A, vamos começar com uma pergunta diferente:&lt;br&gt;
&lt;strong&gt;Quem vai utilizar esse sistema?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consumidor comum&lt;/li&gt;
&lt;li&gt;Gerente&lt;/li&gt;
&lt;li&gt;Operador&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aqui já estabelecemos a quem o sistema interessa, agora &lt;strong&gt;Por que o sistema interessa a esses atores?&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Consumidor Comum (Costumer)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ele quer acessar o sistema para olhar os catálogos e comprar itens, podemos dizer que ele é nosso ator mais importante, é o motivo do sistema existir.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Operador (Operator)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ele preenche nosso sistema com as informações que serão disponibilizadas ao &lt;em&gt;Costumer,&lt;/em&gt; adiciona produtos e atualiza preços.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gerente (Manager)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ele é a entidade que existe para controlar as propriedades do sistema, ele adiciona novos operadores e pode alterar as taxas impostas por compras.&lt;/p&gt;




&lt;p&gt;O processo de se estabelecer os atores do sistema é com certeza o mais demorado e de certa forma caótico deste modelo de arquitetura, pois todo o resto do sistema será orientado a isso, então tenha certeza de gastar um bom tempo com o P.O do projeto ou seu cliente diretamente para entender todas essas peculiaridades da aplicação, atores definem as funções assim como normalmente &lt;strong&gt;contradizem&lt;/strong&gt; elas.&lt;/p&gt;

&lt;p&gt;Imaginem que o recebemos as seguintes definições:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O gerente pode alterar a taxa de compra de todos os consumidores&lt;/li&gt;
&lt;li&gt;O operador pode alterar a taxa de compra de consumidores específicos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Temos aqui duas solicitações conflitantes de atores diferentes, pois se o gerente pode alterar todas as taxas ele tem o poder completo sobre o conjunto, mas o operador tem o poder sobre um elemento do conjunto, dessa forma que descrevi podemos interpretar que o maior poder é o gerente então em caso de conflito, ele teria a prioridade, mas se pensarmos que o poder não vem de quem tem o controle sobre o todo e sim a maior precisão, então em caso de conflito o operador que venceria.&lt;/p&gt;

&lt;p&gt;Existem diversas formar de se resolver o problema acima, mas todas elas exigem que o arquiteto crie regras de negócios e a não ser que você seja o arquiteto do sistema e o dono do negocio, não se deve fazer isso para resolver um problema técnico.&lt;/p&gt;

&lt;p&gt;Sendo assim, esse problema deve ser identificado pelo arquiteto, mas devolvido ao P.O para que se crie uma regra que resolva a disputa, geralmente o melhor jeito de se resolver esse tipo de disputa é não deixar com que dois atores interagem da mesma forma com uma mesma &lt;strong&gt;entidade&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Entidades
&lt;/h2&gt;

&lt;p&gt;Entidades são os elementos internos de seus sistemas, seus modelos de dados.&lt;/p&gt;

&lt;p&gt;Agora que já sabemos quem são nossos atores, podemos definir quem são nossas entidades a partir das funções que os atores precisam realizar em nosso sistema.&lt;/p&gt;

&lt;p&gt;Vamos fazer uma análise de nosso primeiro ator e o quais entidades ele precisa:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Costumer&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tem acesso ao catálogo de produtos&lt;/li&gt;
&lt;li&gt;Adiciona itens a seu carrinho de compras&lt;/li&gt;
&lt;li&gt;Compra um produto&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A primeira funcionalidade é uma visualização, e a entidade necessária para realizar a mesma está em sua citação:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Produto&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Já a segunda funcionalidade nos descreve uma entidade também em sua citação:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Carrinho de compras&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Porem um carrinho de compras naturalmente precisa estar atrelado a algo, normalmente a um usuário, e assim chegamos a conclusão de uma entidade ainda mais primitiva, a representação do Ator dentro do sistema, o Costumer se torna um usuário.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Atenção:&lt;/strong&gt; O exemplo acima não estabelece que todos os atores tem uma entidade apenas para sí no sistema, apenas que esse ator em especifico precisa de uma representação, mas que também pode ser a representação de outros atores.&lt;/p&gt;

&lt;p&gt;A terceira funcionalidade pode ser resolvida com as entidades já presentes?&lt;/p&gt;

&lt;p&gt;Vamos analisar o caso, temos então três entidades:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Produto&lt;/li&gt;
&lt;li&gt;Carrinho de compras&lt;/li&gt;
&lt;li&gt;Usuário&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Uma compra pode ser descrita como produtos em um carrinho de compras pertencentes a um usuário que realiza um pagamento mediante ao valor somado dos produtos.&lt;/p&gt;

&lt;p&gt;Analisando a citação, temos uma ação e exatamente três objetos que são nossas entidades.&lt;/p&gt;

&lt;p&gt;A ação ainda não era conhecida, mas agora sabemos que pagar é uma funcionalidade do Ator Costumer, então podemos adicionar a nossa lista de funcionalidades desse ator.&lt;/p&gt;

&lt;p&gt;Vamos analisar o caso do Operador&lt;/p&gt;

&lt;p&gt;Ele pode:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cadastrar novos produtos&lt;/li&gt;
&lt;li&gt;Alterar o valor dos produtos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ja temos a entidade de produto, mas é necessário saber quem é o operador para permitirmos as operações, e também já temos uma entidade primitiva que pode servir a esse propósito, a entidade Usuário.&lt;/p&gt;

&lt;p&gt;Ou seja, não é necessário criar mais nenhuma entidade para o operador.&lt;/p&gt;

&lt;p&gt;O Gerente pode:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adicionar novos operadores&lt;/li&gt;
&lt;li&gt;Mudar taxas de compras&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para a primeira funcionalidade, já sabemos que o operador é representado pela entidade usuário, sendo assim o gerente vai interagir com ela para adicionar novos operadores.&lt;/p&gt;

&lt;p&gt;Para alterar as taxas de compras vamos precisar de um entidade que defina esses valores, podemos por enquanto defini-la como propriedades do sistema.&lt;/p&gt;

&lt;p&gt;No final estabelecemos as seguintes entidades:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Usuário&lt;/li&gt;
&lt;li&gt;Carrinho de compras&lt;/li&gt;
&lt;li&gt;Produtos&lt;/li&gt;
&lt;li&gt;Propriedades do sistema&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Domain
&lt;/h2&gt;

&lt;p&gt;Já entendemos quem são nossos atores e entidades, vamos agora colocar isso em nosso sistema e essa definição é feito na primeira camada chamada Domain.&lt;/p&gt;

&lt;p&gt;A proposta dessa camada é criar as definições em níveis de código que será estendidas a outras camadas que atendam as mesmas, para este artigo não vou colocar trechos de códigos, pois a proposta é que uma arquitetura de software não dependa do ambiente ou tecnologia para ser aplicada, sendo assim, sinta-se livre para adaptar os exemplos em sua linguagem de preferência.&lt;/p&gt;

&lt;p&gt;A estrutura de arquivos de domain ficaria da seguinte forma:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Domain

&lt;ul&gt;
&lt;li&gt;Entities

&lt;ul&gt;
&lt;li&gt;User&lt;/li&gt;
&lt;li&gt;Shop Cart&lt;/li&gt;
&lt;li&gt;Product&lt;/li&gt;
&lt;li&gt;SystemProperties&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Actor

&lt;ul&gt;
&lt;li&gt;Costumer

&lt;ul&gt;
&lt;li&gt;Get catalog&lt;/li&gt;
&lt;li&gt;Add product to cart&lt;/li&gt;
&lt;li&gt;Remove product from cart&lt;/li&gt;
&lt;li&gt;Buy&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Operator

&lt;ul&gt;
&lt;li&gt;Add product&lt;/li&gt;
&lt;li&gt;Change product&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Manager

&lt;ul&gt;
&lt;li&gt;Add Operator&lt;/li&gt;
&lt;li&gt;Change fees&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;É importante ressaltar que dentro de domain não temos nenhum processo lógico, apenas interfaces que terão de ser respeitadas por outras funções que as implementem.&lt;/p&gt;

&lt;p&gt;Dessa forma, qualquer desenvolvedor pode pode compreender as responsabilidades de cada usuário do sistema e como as mesmas se comportam, mas onde estariam os processos lógicos para fazer as funções do domain funcionarem?&lt;/p&gt;

&lt;h2&gt;
  
  
  Composer
&lt;/h2&gt;

&lt;p&gt;A camada de composição é onde implementaremos as interfaces descritas acima e iremos compor a lógica de nossas funções.&lt;/p&gt;

&lt;p&gt;Essas funções tem diversas sub-responsabilidades, como em Costumer → Add product to cart, temos de:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Buscar o produto&lt;/li&gt;
&lt;li&gt;Validar as quantidades disponíveis dos mesmos&lt;/li&gt;
&lt;li&gt;Adicionar ao carrinho&lt;/li&gt;
&lt;li&gt;Atualizar valor total do carrinho&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Por isso essa camada se chama Composer, ela faz a composição dos módulos do sistema e ao mesmo tempo também declara como esses módulos devem se comportar, pensando nisso, alem de criarmos os usecases das funções relativas aos atores, temos de criar os protocolos (interfaces) das funções relativas aos módulos nesta camada, a estrutura de composer seria:&lt;/p&gt;

&lt;p&gt;Composer&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Protocols

&lt;ul&gt;
&lt;li&gt;Get product&lt;/li&gt;
&lt;li&gt;Check product amount&lt;/li&gt;
&lt;li&gt;Add to cart&lt;/li&gt;
&lt;li&gt;Update cart price&lt;/li&gt;
&lt;li&gt;... (Todas as interfaces dos módulos necessários pelos compositores)&lt;/li&gt;
&lt;/ul&gt;


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

&lt;p&gt;Costumer&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get catalog&lt;/li&gt;
&lt;li&gt;Add product to cart&lt;/li&gt;
&lt;li&gt;Remove product from cart&lt;/li&gt;
&lt;li&gt;Buy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;... (Continuar replicando os casos de uso de cada ator)&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agora devemos criar os módulos que atendam a necessidade de nossos compositores, já temos suas interfaces e sua lógica deve ser descrita na próxima camada&lt;/p&gt;

&lt;h2&gt;
  
  
  Modules
&lt;/h2&gt;

&lt;p&gt;Um módulo é a menor parte executável de um sistema, geralmente caracterizado por um processo que pode ser utilizado por mais de um compositor, pegando o mesmo exemplo do Get product, isso é uma função que pode ser reutilizada em casos de uso pertencentes ao Usuário comum ou ao operador.&lt;/p&gt;

&lt;p&gt;Diferentes módulos não devem implementar a mesma interface, digamos que tanto o Usuário comum quanto o Operador dependam de um modulo de buscar produto, porem o operador deve buscar esse produto da base de dados A e o Usuário comum deve buscar o produto da base de dados B, nesse caso o ideal é criarmos dois protocolos a mais em Composer, lá já temos estabelecido o protocolo de buscar produto e devemos estende-lo a interface &lt;em&gt;Buscar produto de A&lt;/em&gt; e &lt;em&gt;Buscar produto de B.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Tecnicamente não é problema dois módulos diferentes utilizarem a mesma interface, porem a diferenciação teria de ser feito nas &lt;strong&gt;Factories dos compositores&lt;/strong&gt;, e uma boa arquitetura de software visa minimizar as possibilidades de erros, clarear o entendimento do sistema por seus desenvolvedores e facilitar a adaptação do sistema a mudanças. Não diferenciar a interface de dois módulos prejudica tanto a compreensão do sistema quando a possibilidade de ocasionar erros, pois digamos que um desenvolvedor precise fazer a alteração do compositor que utiliza o modulo de Buscar produtos de A, mas como a interface é a mesma ele se distrai e coloca o modulo de Buscar produtos de B, o sistema não vai reclamar, mas o P.O vai, por seu código não estar funcionando.&lt;/p&gt;

&lt;h2&gt;
  
  
  Infra
&lt;/h2&gt;

&lt;p&gt;A camada de infraestrutura é onde vamos conectar nosso sistema as dependências necessárias para fazermos o mesmo funcionar, é a camada mais externa da nossa arquitetura.&lt;/p&gt;

&lt;p&gt;Nosso módulo &lt;em&gt;Get product from A&lt;/em&gt; precisa de um banco de dados para realizar essa busca, e o driver que irá conectar os dois está presente nessa mesma camada, neste caso o módulo em questão se torna também um adaptador ao banco de dados, pois qualquer alteração necessária no banco de dados vai gerar uma alteração no módulo que importa as propriedades de infraestrutura, mas não vai impactar de forma alguma nossa camada de composição que detém a regra de negócio do sistema.&lt;/p&gt;

&lt;p&gt;Digamos que nosso sistema seja uma API Rest e precisamos de um framework para expor endpoints para os acessos do sistema pelos atores, o framework em si estará presente em infra.&lt;/p&gt;

&lt;h2&gt;
  
  
  Main
&lt;/h2&gt;

&lt;p&gt;Esse parte é opcional e depende de como cada tecnologia se comporta, mas precisamos fazer essas camadas conversarem entre si e adicionarmos algum ponto de partida para nosso sistema ser iniciado.&lt;/p&gt;

&lt;p&gt;Caso você esteja utilizando uma linguagem O.O e trabalhando com classes, precisa injetar as dependências necessárias nas classes dos compositores e isso normalmente é feito por &lt;strong&gt;factories&lt;/strong&gt;, idealmente essas instruções estariam na camada Main que inicia o sistema.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Este é um trabalho ainda em desenvolvimento, então se chegou até aqui e quiser contribuir, me envie uma mensagem por aqui mesmo ou deixe um comentário, ficarei muito grato por qualquer esforço, de qualquer forma, muito obrigado pela atenção&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>computerscience</category>
      <category>codequality</category>
      <category>productivity</category>
    </item>
    <item>
      <title>15 minutes to create a Telegram Bot that can answer any question</title>
      <dc:creator>Leonardo Bonetti</dc:creator>
      <pubDate>Fri, 05 Mar 2021 19:39:10 +0000</pubDate>
      <link>https://dev.to/leonardbonetti/15-minutes-to-create-a-telegram-bot-that-can-answer-any-question-2p26</link>
      <guid>https://dev.to/leonardbonetti/15-minutes-to-create-a-telegram-bot-that-can-answer-any-question-2p26</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In last article we create a &lt;a href="https://dev.to/leonardbonetti/15-minutes-to-create-a-personal-assistant-that-can-search-on-wikipedia-and-tell-some-horrible-jokes-1bc7"&gt;personal assistant in 15 minutes&lt;/a&gt;, &lt;br&gt;
due to its good acceptance, I decided to bring other challenges of 15 minutes, today, a telegram bot called Genius, he will try to answer anything you ask&lt;/p&gt;
&lt;h2&gt;
  
  
  The rules:
&lt;/h2&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- interact with the system by telegram chat (Obviously)
- Searches must be carried out using wikipedia
- The robot must be able to change its response if it is not satisfactory to the user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Let's start
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Create project
&lt;/h3&gt;

&lt;p&gt;Create a folder to your project, on terminal execute the following command:&lt;br&gt;
&lt;code&gt;npm init -y &amp;amp;&amp;amp; npx ts-init&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Check that your &lt;code&gt;tsconfig.json&lt;/code&gt; file is as follows&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "compilerOptions": {
    "lib": [
      "es6",
      "DOM"
    ],
    "alwaysStrict": true,
    "strictNullChecks": true,
    "noImplicitAny": true,
    "esModuleInterop": true,
    "resolveJsonModule": true
  },
  "files": [
    "src/index.ts"
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Lets get our packages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;npm i node-telegram-bot-api --save &amp;amp;&amp;amp; npm i @types/node-telegram-bot-api -D&lt;/code&gt; &lt;a href="https://github.com/yagop/node-telegram-bot-api" rel="noopener noreferrer"&gt;node-telegram-bot-api&lt;/a&gt; is an amazing library to abstract Telegram Bot API and make our lives easier.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;npm i wikipedia --save&lt;/code&gt; &lt;a href="https://www.npmjs.com/package/wikipedia" rel="noopener noreferrer"&gt;Wikipedia&lt;/a&gt; is a simple lib that abstract the wiki endpoints.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Create our bot
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Open your telegram and search for &lt;a class="mentioned-user" href="https://dev.to/botfather"&gt;@botfather&lt;/a&gt;
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FLeonBonetti%2F15Minutes%2Fraw%2Fmaster%2FGeniusAnswer%2Fassets%2FsearchBotFather.png" alt="searchBotFather"&gt;
&lt;/li&gt;
&lt;li&gt;Open the conversation and click in start
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FLeonBonetti%2F15Minutes%2Fraw%2Fmaster%2FGeniusAnswer%2Fassets%2FstartBotFather.png" alt="startBotFather"&gt;
&lt;/li&gt;
&lt;li&gt;Type &lt;code&gt;/newBot&lt;/code&gt;
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FLeonBonetti%2F15Minutes%2Fraw%2Fmaster%2FGeniusAnswer%2Fassets%2FtypingNewBot.png" alt="typeNewBot"&gt;
&lt;/li&gt;
&lt;li&gt;Give the common name and the name of the robot as indicated by the telegram instructions
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FLeonBonetti%2F15Minutes%2Fraw%2Fmaster%2FGeniusAnswer%2Fassets%2FgiveBotName.png" alt="giveBotName"&gt;
&lt;/li&gt;
&lt;li&gt;Save the token key in some place to we use later&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Let's code
&lt;/h3&gt;

&lt;p&gt;First of all, wee need to import the libraries that will be used, so, create a file named &lt;code&gt;src/index.ts&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import telegram from 'node-telegram-bot-api';
import wikipedia from 'wikipedia';

const TELEGRAM_KEY = "YOUR-API-KEY-HERE";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;remember to replace where YOUR-API-KEY-HERE is written with your robot key&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Create some interaction
&lt;/h4&gt;

&lt;p&gt;Paste this code inside your &lt;code&gt;src/index.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
const Bot = new telegram(TELEGRAM_KEY, {polling: true});

Bot.onText(/\/start/, async (msg) =&amp;gt; {
    if(!msg.from) return Bot.sendMessage(msg.chat.id, 'I not accept you!');
    Bot.sendMessage(msg.chat.id, 'Wellcome to GeniusAnswer, ask me something');
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a user starts the bot, we send a message asking the user to ask something&lt;/p&gt;

&lt;h4&gt;
  
  
  The main function
&lt;/h4&gt;

&lt;p&gt;Paste this code inside your &lt;code&gt;src/index.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
const wikisearch = async (topic: string, pageIndex: number) =&amp;gt; {
    const search = await wikipedia.search(topic);

    if(pageIndex &amp;gt; search.results.length) throw new Error('Invalid page index');

    const page = await wikipedia.page(search.results[pageIndex].title);

    const summary = await page.summary();

    return {text: summary.extract, pageIndex: 0, pageLength: search.results.length};
};

Bot.on("text", async (msg) =&amp;gt; {
  if (!msg.from) return Bot.sendMessage(msg.chat.id, "I not accept you!");
  if (!msg.text) return Bot.sendMessage(msg.chat.id, "Invalid message");
  if (msg.text[0] === "/") return;

  Bot.sendMessage(msg.chat.id, `Searching for ${msg.text} ...`);

  const search = await wikisearch(msg.text, 0);

  console.log(search);

  let options_button = {};
  if (search.pageIndex &amp;lt; search.pageLength) {
    options_button = {
      reply_markup: {
        inline_keyboard: [
          [
            {
              text: "Next Answer -&amp;gt;",
              callback_data: JSON.stringify({ topic: msg.text, pageIndex: 1 }),
            },
          ],
        ],
      },
    };
  }

  return Bot.sendMessage(
    msg.chat.id,
    `${search.text} \n Answer ${search.pageIndex + 1}/${search.pageLength}`,
    options_button
  );
});

});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we only create a search function thata can make searchs on wikipedia and return the index of this result, if wee need a diferent result for this question, we only need to pass a diferent index for the function.&lt;br&gt;
On next function will listen for text messages send to your bot, on result wee put a button that can change the index of search.&lt;/p&gt;
&lt;h4&gt;
  
  
  The callback function
&lt;/h4&gt;

&lt;p&gt;Paste this code inside your &lt;code&gt;src/index.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
Bot.on("callback_query", async (callback) =&amp;gt; {
  if (!callback.data || !callback.message) return;

  console.log(callback.data);

  const data = JSON.parse(callback.data) as {
    topic: string;
    pageIndex: number;
  };

  try {
    const search = await wikisearch(data.topic, data.pageIndex);

    console.log(search);

    let options_button = {};
    let inline_keyboard_buttons = [];
    if (search.pageIndex + 1 &amp;lt; search.pageLength) {
      inline_keyboard_buttons.unshift({
        text: "Next Answer -&amp;gt;",
        callback_data: JSON.stringify({
          topic: data.topic,
          pageIndex: search.pageIndex + 1,
        }),
      });

      if (search.pageIndex &amp;gt; 0) {
        inline_keyboard_buttons.unshift({
          text: "&amp;lt;- Previous Answer",
          callback_data: JSON.stringify({
            topic: data.topic,
            pageIndex: search.pageIndex - 1,
          }),
        });
      }
    } else if (search.pageIndex + 1 === search.pageLength) {
      inline_keyboard_buttons.unshift({
        text: "&amp;lt;- Previous Answer",
        callback_data: JSON.stringify({
          topic: data.topic,
          pageIndex: search.pageIndex - 1,
        }),
      });
    }

    if (inline_keyboard_buttons.length &amp;gt; 0) {
      options_button = {
        reply_markup: {
          inline_keyboard: [inline_keyboard_buttons],
        },
      };
    }

    return Bot.editMessageText(
      `${search.text} \n Answer ${search.pageIndex + 1}/${search.pageLength}`,
      {
        chat_id: callback.message.chat.id,
        message_id: callback.message.message_id,
        ...options_button,
      }
    );
  } catch (error) {
    return Bot.editMessageText(
      "Sorry, an error seems to have happened, please try again later",
      {
        chat_id: callback.message.chat.id,
        message_id: callback.message.message_id,
      }
    );
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, although the callback function is very long, is easily to be understood, we just capture the search topic and change the index, depending on whether or not you have a next or previous page, we add the respective buttons to the message.&lt;/p&gt;

&lt;h3&gt;
  
  
  Now your code need to be like this
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import telegram from "node-telegram-bot-api";
import wikipedia from "wikipedia";

const TELEGRAM_KEY = "YOUR-TELEGRAM-KEY-HERE";

const Bot = new telegram(TELEGRAM_KEY, { polling: true });

Bot.onText(/\/start/, (msg) =&amp;gt; {
  if (!msg.from) return Bot.sendMessage(msg.chat.id, "I not accept you!");
  Bot.sendMessage(msg.chat.id, "Wellcome to GeniusAnswer, ask me something");
});

const wikisearch = async (topic: string, pageIndex: number) =&amp;gt; {
  const search = await wikipedia.search(topic);

  if (pageIndex &amp;gt; search.results.length) throw new Error("Invalid page index");

  const page = await wikipedia.page(search.results[pageIndex].title);

  const summary = await page.summary();

  return {
    text: summary.extract,
    pageIndex: pageIndex,
    pageLength: search.results.length,
  };
};

Bot.on("text", async (msg) =&amp;gt; {
  if (!msg.from) return Bot.sendMessage(msg.chat.id, "I not accept you!");
  if (!msg.text) return Bot.sendMessage(msg.chat.id, "Invalid message");
  if (msg.text[0] === "/") return;

  Bot.sendMessage(msg.chat.id, `Searching for ${msg.text} ...`);

  const search = await wikisearch(msg.text, 0);

  console.log(search);

  let options_button = {};
  if (search.pageIndex &amp;lt; search.pageLength) {
    options_button = {
      reply_markup: {
        inline_keyboard: [
          [
            {
              text: "Next Answer -&amp;gt;",
              callback_data: JSON.stringify({ topic: msg.text, pageIndex: 1 }),
            },
          ],
        ],
      },
    };
  }

  return Bot.sendMessage(
    msg.chat.id,
    `${search.text} \n Answer ${search.pageIndex + 1}/${search.pageLength}`,
    options_button
  );
});

Bot.on("callback_query", async (callback) =&amp;gt; {
  if (!callback.data || !callback.message) return;

  console.log(callback.data);

  const data = JSON.parse(callback.data) as {
    topic: string;
    pageIndex: number;
  };

  try {
    const search = await wikisearch(data.topic, data.pageIndex);

    console.log(search);

    let options_button = {};
    let inline_keyboard_buttons = [];
    if (search.pageIndex + 1 &amp;lt; search.pageLength) {
      inline_keyboard_buttons.unshift({
        text: "Next Answer -&amp;gt;",
        callback_data: JSON.stringify({
          topic: data.topic,
          pageIndex: search.pageIndex + 1,
        }),
      });

      if (search.pageIndex &amp;gt; 0) {
        inline_keyboard_buttons.unshift({
          text: "&amp;lt;- Previous Answer",
          callback_data: JSON.stringify({
            topic: data.topic,
            pageIndex: search.pageIndex - 1,
          }),
        });
      }
    } else if (search.pageIndex + 1 === search.pageLength) {
      inline_keyboard_buttons.unshift({
        text: "&amp;lt;- Previous Answer",
        callback_data: JSON.stringify({
          topic: data.topic,
          pageIndex: search.pageIndex - 1,
        }),
      });
    }

    if (inline_keyboard_buttons.length &amp;gt; 0) {
      options_button = {
        reply_markup: {
          inline_keyboard: [inline_keyboard_buttons],
        },
      };
    }

    return Bot.editMessageText(
      `${search.text} \n Answer ${search.pageIndex + 1}/${search.pageLength}`,
      {
        chat_id: callback.message.chat.id,
        message_id: callback.message.message_id,
        ...options_button,
      }
    );
  } catch (error) {
    return Bot.editMessageText(
      "Sorry, an error seems to have happened, please try again later",
      {
        chat_id: callback.message.chat.id,
        message_id: callback.message.message_id,
      }
    );
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, our code is complete, let's test?&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;npm run ts&lt;/code&gt; on your terminal and open your telegram.&lt;br&gt;
Search for your bot name (the same that you create in the begin of this article, generally ends with _bot) and press START.&lt;/p&gt;

&lt;p&gt;Enjoy yourself!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;There are some ways to optimize the response time of this robot, if you are interested I can show them in another article later, but I believe this is an interesting challenge for those who liked the idea of ​​the robot, leave in the comments your solutions and ideas&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>typescript</category>
      <category>telegram</category>
      <category>javascript</category>
    </item>
    <item>
      <title>15 minutes to create a personal assistant that can search on wikipedia (and tell some horrible jokes)</title>
      <dc:creator>Leonardo Bonetti</dc:creator>
      <pubDate>Tue, 02 Mar 2021 14:32:42 +0000</pubDate>
      <link>https://dev.to/leonardbonetti/15-minutes-to-create-a-personal-assistant-that-can-search-on-wikipedia-and-tell-some-horrible-jokes-1bc7</link>
      <guid>https://dev.to/leonardbonetti/15-minutes-to-create-a-personal-assistant-that-can-search-on-wikipedia-and-tell-some-horrible-jokes-1bc7</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;On a boring day at work, a colleague and I were talking to Alexa, when a bet arose due to the joke, creating a virtual assistant in 15 minutes.&lt;/p&gt;

&lt;p&gt;Alexa has a multitude of functions, so to make the challenge possible ours should just take questions about common topics.&lt;/p&gt;

&lt;h3&gt;
  
  
  Then we choose the following rules:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The assistant must interact with you by speaking your name&lt;/li&gt;
&lt;li&gt;Responses must be in audio&lt;/li&gt;
&lt;li&gt;Searches must be carried out using wikipedia&lt;/li&gt;
&lt;li&gt;Tell some jokes&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Let's code
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Create project
&lt;/h3&gt;

&lt;p&gt;I can't code without typescript anymore, so...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm init -y &amp;amp;&amp;amp; npx ts-init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check that your &lt;code&gt;tsconfig.json&lt;/code&gt; file is as follows&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "compilerOptions": {
    "lib": [
      "es6",
      "DOM"
    ],
    "alwaysStrict": true,
    "strictNullChecks": true,
    "noImplicitAny": true,
    "esModuleInterop": true,
    "resolveJsonModule": true
  },
  "files": [
    "src/index.ts"
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Lets get our packages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;npm i --save say&lt;/code&gt; &lt;a href="https://www.npmjs.com/package/say"&gt;Say&lt;/a&gt; is an amazing TTS (Text-to-Speech) library, it will help us with a voice to our robot.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;npm i --save wikipedia&lt;/code&gt; &lt;a href="https://www.npmjs.com/package/wikipedia"&gt;Wikipedia&lt;/a&gt; is a simple lib that abstract the wiki endpoints and make our lives easier&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Add some Jokes
&lt;/h3&gt;

&lt;p&gt;Create a file named &lt;code&gt;src/jokes.json&lt;/code&gt;, copie the content of this &lt;a href="https://gist.githubusercontent.com/LeonBonetti/6101b34414761fc4567acb2eb930598a/raw/2454af2e5c362c58b6dd2397bc91fa6c4377bd2f/jokes.json"&gt;gist&lt;/a&gt; to your file&lt;/p&gt;

&lt;h3&gt;
  
  
  Finally we will code
&lt;/h3&gt;

&lt;p&gt;Inside your &lt;code&gt;src/index.ts&lt;/code&gt; import all libraries&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import say from 'say';
import wikipedia from "wikipedia";
import jokes from './jokes.json';
import readline from "readline";

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

&lt;/div&gt;



&lt;p&gt;Our personal assistant will receive the commands by text, like the old ways&lt;br&gt;
So, w'll need a interface to interact with our user by terminal&lt;br&gt;
&lt;/p&gt;

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

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The main goal here is create an assistant that can make searchs on wikipedia, so, lets create this func&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
const wikisearch = async (topic: string) =&amp;gt; {
    const search = await wikipedia.search(topic);
    const page = await wikipedia.page(search.results[0].title);

    const summary = await page.summary();

    return summary.extract;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let's give our assistant a voice&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
const speak = (text: string) =&amp;gt; {
    return new Promise((resolve, reject) =&amp;gt; {
        say.speak(text, 'Samantha', 0.9, (err) =&amp;gt; {
            if(err) reject(err);
            resolve(true);
        });
    })
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As my assistant is a woman, I decided to give her the voice of Samantha, and to make it more audible, I leave the playback speed at 0.9, but feel free to change any of these properties, you can check the full list of voices available &lt;a href="https://github.com/Marak/say.js/blob/master/examples/osx-allvoices.js"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ok, lets interact.&lt;br&gt;
By the first rule of the challenge, the bot need to know our name, so&lt;br&gt;
&lt;/p&gt;

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

let name = "";

rl.question("What is your name ? ", async function(received: string) {
        name = received;
        await speak(`Hello ${received}, my name is Clotilde`);
        ask();
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, lets code the final function&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
const ask = () =&amp;gt; {
    rl.question("ask me something: ", async function(rQuery: string) {

        if(rQuery == 'stop') {
            say.stop();
            return rl.close();
        }

        if(rQuery.toLocaleLowerCase().split(' ').findIndex(item =&amp;gt; item == 'joke') &amp;gt; -1) {
            const jokeIndex = Math.floor(Math.random() * jokes.length);
            const joke = jokes[jokeIndex];
            await speak(joke.text);
        } else {
            const searchTopic = await wikisearch(rQuery);
            await speak(`According to wikipedia, ${searchTopic}`);
        }

        ask();
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The idea here is very simple, if the user asks something that contains the word joke, we tell a joke, if not, we search on wikipedia.&lt;/p&gt;

&lt;p&gt;And, for finally, when we shutdown our assistant:&lt;br&gt;
&lt;/p&gt;

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

rl.on("close", async function() {
    console.log("\nBYE BYE !!!");
    await speak("Bye Bye");
    process.exit(0);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;She will say "Bye Bye"&lt;/p&gt;

&lt;p&gt;Your code should now look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import say from 'say';
import wikipedia from "wikipedia";
import jokes from './jokes.json';
import readline from "readline";

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

const wikisearch = async (topic: string) =&amp;gt; {
    const search = await wikipedia.search(topic);
    const page = await wikipedia.page(search.results[0].title);

    const summary = await page.summary();

    return summary.extract;
}

const speak = (text: string) =&amp;gt; {
    return new Promise((resolve, reject) =&amp;gt; {
        say.speak(text, 'Samantha', 0.9, (err) =&amp;gt; {
            if(err) reject(err);
            resolve(true);
        });
    })
}

let name = "";

rl.question("What is your name ? ", async function(received: string) {
        name = received;
        await speak(`Hello ${received}, my name is Clotilde`);
        ask();
});


const ask = () =&amp;gt; {
    rl.question("ask me something: ", async function(rQuery: string) {

        if(rQuery == 'stop') {
            say.stop();
            return rl.close();
        }

        if(rQuery.toLocaleLowerCase().split(' ').findIndex(item =&amp;gt; item == 'joke') &amp;gt; -1) {
            const jokeIndex = Math.floor(Math.random() * jokes.length);
            const joke = jokes[jokeIndex];
            await speak(joke.text);
        } else {
            const searchTopic = await wikisearch(rQuery);
            await speak(`According to wikipedia, ${searchTopic}`);
        }

        ask();
    });
}


rl.on("close", async function() {
    console.log("\nBYE BYE !!!");
    await speak("Bye Bye");
    process.exit(0);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The complete repo of this project can be found on &lt;a href="https://github.com/LeonBonetti/Clotilde-the-personal-assistant"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you very much, let us know in the comments section how long it took you to create this bot&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>programming</category>
      <category>funny</category>
    </item>
    <item>
      <title>Lint, what and why</title>
      <dc:creator>Leonardo Bonetti</dc:creator>
      <pubDate>Tue, 03 Nov 2020 15:32:46 +0000</pubDate>
      <link>https://dev.to/leonardbonetti/linters-what-and-why-3dff</link>
      <guid>https://dev.to/leonardbonetti/linters-what-and-why-3dff</guid>
      <description>&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The statement “Time is money” makes more and more sense among programmers, being efficient allows more jobs in less time and you certainly don't want to waste your hours behind a ghost character or a dead code due to a lack of attention during development.&lt;/p&gt;

&lt;p&gt;Spending hours developing an application can be exhausting, and it gets worse when we finally test it and "CRASH!". (Let's go back there in the code to resolve this).&lt;br&gt;
After a few more hours it turns out that the problem was the lack of a single character in the code.&lt;/p&gt;

&lt;p&gt;Well, the top case is probably the daily life of many developers, and without a doubt it is one of the oldest problems in programming.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The solution:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;"We are going to write a program that checks the code to find possible syntax errors, infinite loops, dead codes, etc."&lt;/p&gt;

&lt;p&gt;In 1978 a computer scientist working for Bell Labs named Stephen C. Johnson created a program for checking static code in C, currently we have Linters for virtually all commercial programming languages, and at development time they point out flaws in our code that could even pass as a structural or logical problem in our application, making us spend hours and hours behind the problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use?&lt;/strong&gt;&lt;br&gt;
“Prevention is better than cure”, so always, always use Linters in your projects, no matter the size and duration.&lt;/p&gt;

&lt;p&gt;But which linter should I use?&lt;br&gt;
The &lt;a href="https://github.com/mcandre/linters"&gt;https://github.com/mcandre/linters&lt;/a&gt; repository is an extremely useful source for you to find the best one for your language and need.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automation:&lt;/strong&gt;&lt;br&gt;
Okay, it is useless to use a tool to prevent errors caused many times by lack of attention, but forget to use it.&lt;br&gt;
So there are several ways to automate the code checking process, let's talk about my two favorites.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Git Hooks. (My favorite)&lt;br&gt;
During pre-commit, set up a command to perform the inspection of your code using your preferred linter, so the chance of sending broken code to your repository is minimal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CI&lt;br&gt;
If you are using GitFlow, you will probably code your feature in a specific branch for it, and when your work is done if you create a merge request for the development branch, use your Git Host resources (GitHub or GitLab) to set up a CI process that executes a command to check your code before asking another developer to approve it, that way, not only is your time saved, but it helps to save the time of the rest of the team.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>lint</category>
      <category>testing</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
