<?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: Jefferson Rodrigues</title>
    <description>The latest articles on DEV Community by Jefferson Rodrigues (@rodriguesjeff).</description>
    <link>https://dev.to/rodriguesjeff</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1034290%2Fcccc708e-48cf-490b-8a54-cbabf63c7346.jpg</url>
      <title>DEV Community: Jefferson Rodrigues</title>
      <link>https://dev.to/rodriguesjeff</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rodriguesjeff"/>
    <language>en</language>
    <item>
      <title>Extensão do gnome para papel de parede de tela de bloqueio</title>
      <dc:creator>Jefferson Rodrigues</dc:creator>
      <pubDate>Thu, 05 Nov 2026 22:53:12 +0000</pubDate>
      <link>https://dev.to/rodriguesjeff/extensao-do-gnome-para-papel-de-parede-de-tela-de-bloqueio-5f96</link>
      <guid>https://dev.to/rodriguesjeff/extensao-do-gnome-para-papel-de-parede-de-tela-de-bloqueio-5f96</guid>
      <description>&lt;p&gt;Olá a todos, hoje vou compartilhar com vocês a solução pra um problema que talvez você não tenha. Eu sou um distro hopper, mas recentemente decidi me aquietar e usar um sistema só e ficar nele. Eu usava o Arch por muito tempo, mas desde que corrompi o sistema com uma atualização e perdi coisas do trabalho, mais por falha minha mesmo do que por culpa do Arch, eu passei um bom tempo no Mac por ser dev iOS no meu antigo trabalho. Agora que mudei de área, voltei para o Linux e caí naquele problema de sempre, pular de distro em distro para ir testando coisas novas. Acontece que esse é o pc que uso no trabalho novo então eu não queria ficar brincando.&lt;/p&gt;

&lt;h2&gt;
  
  
  Distro Hopping
&lt;/h2&gt;

&lt;p&gt;Em pouco mais de um mês eu instalei 3 distros: Linux mint,OpenSuse Tumbleweed e agora o Ubuntu. No mint passei uma ou duas semanas, fui pro suse porque eu queria voltar ao rolling release (gosto de ficar com os pacotes mais atuais) e instalei o Hyprland, mas vendo um vídeo do DioLinux fiquei reflexivo com algo que ele disse: "Porquê eu vou usar uma distro que complique a minha vida?". Isso ficou na minha cabeça, passei uns dois dias pensando nisso e decidi mudar de distro para uma estável e mais "Tranquila". &lt;/p&gt;

&lt;p&gt;Entrei num dilema, usar o PopPS! ou Ubuntu, ambos usam apt e são base Debian, e eu gosto disso. Mas eu acho que o Cosmic tem uma pegada muito infantil na interface, talvez por ser toda colorida (Se bem que podemos simplesmente mudar o tema né? rsrs). Não sei se é apenas uma opinião minha. Em contra partida o próprio Cosmic tem o tile nativo que você pode ativar e desativar com muita facilidade, e eu gosto de poder ter essa opção e sinto falta dela no Ubuntu. Não sei se nele temos algo assim configurável por meio de extensão.&lt;/p&gt;

&lt;h2&gt;
  
  
  Um problema de ninguém
&lt;/h2&gt;

&lt;p&gt;Daí contexto dado, entramos no assunto do post: extensões. O Windows tem algo que eu acho legal que é aquela mudança de papel de parede da tela de bloqueio a cada novo bloqueio de tela. Algo bem simples, é verdade. Mas o Gnome não me permite nem alterar a imagem padrão, quanto mais mudar ela dinamicamente. Iniciei a minha saga em busca de alguma extensão que me permitisse fazer isso, mas não encontrei... &lt;/p&gt;

&lt;p&gt;Encontrei então &lt;a href="https://github.com/sunwxg/gnome-shell-extension-unlockDialogBackground" rel="noopener noreferrer"&gt;essa extensão&lt;/a&gt; que me permite mudar o papel de parede da tela de bloqueio. Boa! Quase lá, mas ainda tem um problema, eu queria que as fotos mudassem dinamicamente sempre que bloqueasse a tela.&lt;/p&gt;

&lt;h2&gt;
  
  
  Minha solução
&lt;/h2&gt;

&lt;p&gt;Daí resolvi vibe codar a minha própria extensão, abri um fork do repositório desse brother e com o auxílio do Claude, criei a minha própria solução para isso. Ela se chama Gnome Shell Extension Random Lock Screen BG e o diferencial dela está no provider das imagens, você pode configurar ela da seguinte forma:&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;Você pode selecionar somente uma foto e ela fica fixa;&lt;/li&gt;
&lt;li&gt;Você pode selecionar uma pasta com suas fotos que irão ser alteradas de forma aleatória;&lt;/li&gt;
&lt;li&gt;Você pode optar por trazer as fotos do Unsplash, se você não quiser criar uma chave de api, pode deixar selecionado sem adicionar chave e ele vai buscar do Lorem Picsum que são fotos grátis e muito boas também;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  E como a extensão funciona?
&lt;/h2&gt;

&lt;p&gt;Simples, quando a tela bloqueia, o programa não tem acesso para enviar notificação para o sistema fazer a chamada da foto, então sempre que você desbloqueia, ele chama a API e já deixa selecionada em cache a foto para o próximo bloqueio, você pode limitar a quantidade de fotos salvas em cache.&lt;/p&gt;

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

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

&lt;p&gt;Tela bloqueada:&lt;/p&gt;

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

&lt;p&gt;Simples assim e o seu Gnome vai ficando mais bonito, como eu disse lá encima, é um problema que ninguém tem, mas me incomodava e eu resolvi resolver. A IA nos permite ter esse tipo de facilidade, e eu estou muito satisfeito com o resultado.&lt;/p&gt;

&lt;p&gt;Caso você queia o link para contribuir ou baixar na sua máquia e instalar: &lt;br&gt;
&lt;a href="https://extensions.gnome.org/extension/11653/random-lock-screen-background/" rel="noopener noreferrer"&gt;Link da extensão&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/rodriguesJeff/gnome-shell-extension-random-lockscreen-bg" rel="noopener noreferrer"&gt;Link do repositório&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ainda não subi no Gnome Extensions, em breve edito aqui com o link de lá.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>gnome</category>
      <category>ubuntu</category>
      <category>claude</category>
    </item>
    <item>
      <title>Josue Meetings - FOSS aplicativo para transcrever e resumir calls</title>
      <dc:creator>Jefferson Rodrigues</dc:creator>
      <pubDate>Thu, 30 Jul 2026 03:05:33 +0000</pubDate>
      <link>https://dev.to/rodriguesjeff/josue-meetings-foos-aplicativo-para-transcrever-e-resumir-calls-2o0m</link>
      <guid>https://dev.to/rodriguesjeff/josue-meetings-foos-aplicativo-para-transcrever-e-resumir-calls-2o0m</guid>
      <description>&lt;p&gt;&lt;strong&gt;Josue Meetings&lt;/strong&gt; é um aplicativo desktop que grava suas reuniões em segundo plano, capturando o áudio do sistema e do microfone. O aplicativo permanece na menu bar e transforma o áudio em texto utilizando o Whisper executado localmente. Depois, se desejar, gera resumos e responde perguntas usando OpenAI ou DeepSeek.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Sem servidor próprio:&lt;/strong&gt; seus dados permanecem na sua máquina.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  O problema
&lt;/h2&gt;

&lt;p&gt;Toda reunião online gera informações importantes, mas quase sempre elas acabam se perdendo. Gravar o áudio, transcrever e resumir normalmente exige várias ferramentas e serviços na nuvem.&lt;/p&gt;

&lt;p&gt;O Josue Meetings resolve tudo isso em um único fluxo, executado localmente.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como funciona
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Dê um nome para a reunião (ou utilize o padrão).&lt;/li&gt;
&lt;li&gt;Inicie a gravação.&lt;/li&gt;
&lt;li&gt;Acompanhe os níveis de áudio do sistema e do microfone.&lt;/li&gt;
&lt;li&gt;Pause, retome ou finalize quando desejar.&lt;/li&gt;
&lt;li&gt;Continue trabalhando normalmente pela menu bar.&lt;/li&gt;
&lt;li&gt;Ao finalizar, a reunião é aberta automaticamente para transcrição.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Transcrição local
&lt;/h2&gt;

&lt;p&gt;Toda a transcrição é realizada utilizando o Whisper executado na própria máquina.&lt;/p&gt;

&lt;p&gt;Você pode exportar o resultado em:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Markdown (&lt;code&gt;.md&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Texto (&lt;code&gt;.txt&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Após uma transcrição bem-sucedida, o áudio pode ser removido automaticamente, preservando sua privacidade.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inteligência Artificial (Opcional)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fidx1vbw13wvfi36mq57v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fidx1vbw13wvfi36mq57v.png" alt="Opçao de selecionar api da openai ou deepseek" width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Com uma chave de API da OpenAI ou DeepSeek, você pode:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gerar resumos automáticos.&lt;/li&gt;
&lt;li&gt;Conversar com um agente sobre uma reunião.&lt;/li&gt;
&lt;li&gt;Organizar reuniões em pastas.&lt;/li&gt;
&lt;li&gt;Fazer perguntas considerando todas as reuniões de um projeto.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;O aplicativo possui um assistente de configuração que detecta o sistema operacional e orienta a instalação dos componentes necessários.&lt;/p&gt;

&lt;p&gt;Atualmente:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ macOS: captura de sistema + microfone utilizando BlackHole e Multi-Output Device.&lt;/li&gt;
&lt;li&gt;🚧 Windows: suporte em evolução.&lt;/li&gt;
&lt;li&gt;🚧 Linux: suporte em evolução.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Recursos
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Aplicativo desktop (Electron)&lt;/li&gt;
&lt;li&gt;Gravação do sistema + microfone&lt;/li&gt;
&lt;li&gt;Funcionamento na menu bar&lt;/li&gt;
&lt;li&gt;Transcrição 100% local (Whisper)&lt;/li&gt;
&lt;li&gt;Resumos e chat via OpenAI ou DeepSeek&lt;/li&gt;
&lt;li&gt;Organização por projetos&lt;/li&gt;
&lt;li&gt;Agente por pasta&lt;/li&gt;
&lt;li&gt;Lixeira integrada&lt;/li&gt;
&lt;li&gt;Assistente de configuração&lt;/li&gt;
&lt;li&gt;Privacidade por padrão&lt;/li&gt;
&lt;/ul&gt;




&lt;blockquote&gt;
&lt;p&gt;Grave suas reuniões sem interromper seu trabalho, transcreva tudo localmente e utilize IA apenas quando fizer sentido, sempre com a sua própria chave de API.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;O software é livre e aceitamos contribuição de pessoas bem intencionadas que queiram ajudar a melhorar cada dia mais!&lt;br&gt;
&lt;a href="https://github.com/rodriguesJeff/josue" rel="noopener noreferrer"&gt;Repositório do projeto&lt;/a&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>ai</category>
      <category>programming</category>
      <category>electron</category>
    </item>
    <item>
      <title>🚀 Revisando o S.O.L.I.D na Prática com Flutter e Dart</title>
      <dc:creator>Jefferson Rodrigues</dc:creator>
      <pubDate>Thu, 26 Feb 2026 03:58:02 +0000</pubDate>
      <link>https://dev.to/rodriguesjeff/revisando-o-solid-na-pratica-com-flutter-e-dart-44e1</link>
      <guid>https://dev.to/rodriguesjeff/revisando-o-solid-na-pratica-com-flutter-e-dart-44e1</guid>
      <description>&lt;h1&gt;
  
  
  🚀 Revisando o S.O.L.I.D na Prática com Flutter e Dart
&lt;/h1&gt;

&lt;h2&gt;
  
  
  🎯 Introdução
&lt;/h2&gt;

&lt;p&gt;Resolvi revisar os meus conhecimentos sobre temas essenciais da programação. Iniciei pelo &lt;strong&gt;SOLID&lt;/strong&gt; porque é algo que deve ser revisitado de vez em quando para garantir que estamos entendendo não só o conceito, mas a prática também.&lt;/p&gt;

&lt;p&gt;Com isso, podemos escrever códigos mais limpos, escaláveis e de fácil entendimento.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ Metodologia
&lt;/h2&gt;

&lt;p&gt;Usei como base dois repositórios meus de quando eu estava estudando &lt;strong&gt;Clean Architecture&lt;/strong&gt;. Um deles trata-se de um app simples: buscar conselhos em uma API e retornar para o usuário.&lt;/p&gt;

&lt;p&gt;Neste projeto, aplico cada um dos cinco princípios do SOLID. Abaixo, detalho como cada um deles se comporta no código.&lt;/p&gt;




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

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Princípio da Responsabilidade Única:&lt;/strong&gt; Uma classe deve ter um, e apenas um, motivo para mudar.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No exemplo abaixo, a classe abstrata para o data source define apenas o contrato de busca remota. Ela não se preocupa com lógica de negócio ou como os dados serão exibidos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AdviceRemoteDataSource&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Advice&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;getAdvice&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;Outro exemplo claro é o tratamento de erros. Criamos uma estrutura base e especializamos as falhas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Failure&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Equatable&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Failure&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt; &lt;span class="n"&gt;properties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;dynamic&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;[]])&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Responsável apenas por erros de servidor&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ServerFailure&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Failure&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Responsável apenas por erros de cache local&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CacheFailure&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;Failure&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔵 O — Open/Closed Principle (OCP)
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Aberto para Extensão, Fechado para Modificação:&lt;/strong&gt; Você deve ser capaz de estender o comportamento de uma classe sem modificar o seu código-fonte original.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A classe &lt;code&gt;AdviceRepository&lt;/code&gt; está "fechada" (o contrato está definido). Se precisarmos de uma nova forma de obter dados, apenas implementamos o contrato em uma nova classe, sem tocar na interface original.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AdviceRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Either&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Failure&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Advice&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;getAdvice&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;AdviceRepositoryImpl&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="n"&gt;AdviceRepository&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;AdviceRemoteDataSource&lt;/span&gt; &lt;span class="n"&gt;remoteDataSource&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="n"&gt;AdviceRepositoryImpl&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;remoteDataSource&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Either&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Failure&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Advice&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;getAdvice&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;remoteAdvice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;remoteDataSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAdvice&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Right&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;remoteAdvice&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kd"&gt;on&lt;/span&gt; &lt;span class="n"&gt;ServerException&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Left&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ServerFailure&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  🟡 L — Liskov Substitution Principle (LSP)
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Princípio da Substituição de Liskov:&lt;/strong&gt; Objetos de uma superclasse devem ser substituíveis por objetos de suas subclasses sem quebrar a aplicação.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No Flutter, isso é muito comum com os DataSources. A implementação &lt;code&gt;AdviceRemoteDataSourceImpl&lt;/code&gt; pode substituir perfeitamente a abstração &lt;code&gt;AdviceRemoteDataSource&lt;/code&gt; em qualquer lugar que ela seja exigida.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AdviceRemoteDataSourceImpl&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="n"&gt;AdviceRemoteDataSource&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Client&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;AdviceRemoteDataSourceImpl&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="kd"&gt;required&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Advice&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;getAdvice&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;async&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Implementação real da chamada HTTP&lt;/span&gt;
    &lt;span class="c1"&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;em&gt;💡 Obs.: Uma melhoria seria criar um &lt;code&gt;AdviceDataSource&lt;/code&gt; genérico, permitindo trocar o Remote pelo Local de forma transparente.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🟠 I — Interface Segregation Principle (ISP)
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Segregação de Interface:&lt;/strong&gt; Uma classe não deve ser forçada a implementar interfaces e métodos que não utiliza.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Em vez de criar uma interface gigante "TudoNoApp", dividimos em interfaces específicas. No exemplo, o repositório depende apenas do que é essencial para ele: o DataSource de conselhos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Interface específica e focada no domínio de conselhos&lt;/span&gt;
&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AdviceRemoteDataSource&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Advice&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;getAdvice&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔴 D — Dependency Inversion Principle (DIP)
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Inversão de Dependência:&lt;/strong&gt; Dependa de abstrações, não de implementações concretas.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Aqui é onde o &lt;code&gt;GetIt&lt;/code&gt; ou &lt;code&gt;Provider&lt;/code&gt; brilham. O &lt;code&gt;AdviceRepositoryImpl&lt;/code&gt; não conhece a implementação do DataSource, ele conhece apenas o contrato. A "mágica" acontece no nosso Service Locator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setupLocator&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Registramos a abstração apontando para a implementação&lt;/span&gt;
  &lt;span class="n"&gt;getIt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;registerLazySingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AdviceRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
    &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AdviceRepositoryImpl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;remoteDataSource:&lt;/span&gt; &lt;span class="n"&gt;getIt&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;getIt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;registerLazySingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AdviceRemoteDataSource&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
      &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AdviceRemoteDataSourceImpl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;client:&lt;/span&gt; &lt;span class="n"&gt;getIt&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;

  &lt;span class="n"&gt;getIt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;registerLazySingleton&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  📊 Resumo Visual
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Sigla&lt;/th&gt;
&lt;th&gt;Princípio&lt;/th&gt;
&lt;th&gt;Resumo em uma frase&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;S&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Responsabilidade Única&lt;/td&gt;
&lt;td&gt;Cada classe faz apenas uma coisa.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;O&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Aberto/Fechado&lt;/td&gt;
&lt;td&gt;Estenda o comportamento sem alterar o original.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;L&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Subst. de Liskov&lt;/td&gt;
&lt;td&gt;Subclasses devem honrar o contrato da base.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;I&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Segregação de Interface&lt;/td&gt;
&lt;td&gt;Crie interfaces pequenas e específicas.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;D&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Inversão de Dependência&lt;/td&gt;
&lt;td&gt;Dependa de contratos, não de classes concretas.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




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

&lt;p&gt;Utilizar esses conceitos na prática vai além de construir "códigos bonitos". Trata-se de garantir a &lt;strong&gt;manutenibilidade&lt;/strong&gt;. Um código bem estruturado permite que ele viva mais e que as manutenções futuras não sejam um sofrimento.&lt;/p&gt;

&lt;p&gt;Lembre-se: o seu código fala muito sobre você! 🚀&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ficou com alguma dúvida sobre como aplicar isso no seu projeto Flutter? Comenta aqui embaixo e vamos trocar uma ideia!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>solidprinciples</category>
      <category>flutter</category>
      <category>cleancode</category>
      <category>mobile</category>
    </item>
  </channel>
</rss>
