<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Blog do Riverfount</title>
    <link>https://riverfount.dev.br/</link>
    <description>Recent content on Blog do Riverfount</description>
    <generator>Hugo -- 0.148.2</generator>
    <language>pt-br</language>
    <lastBuildDate>Sun, 16 Aug 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://riverfount.dev.br/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>mongo_bakery: o fim da factory que você escrevia pra cada Document do MongoEngine</title>
      <link>https://riverfount.dev.br/posts/mongo-bakery-fim-da-factory/</link>
      <pubDate>Sun, 16 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/mongo-bakery-fim-da-factory/</guid>
      <description>&lt;p&gt;O teste queria garantir uma coisa só: cancelar um pedido pendente devolve 200. Pra chegar até essa asserção, ele teve que passar por isso primeiro:&lt;/p&gt;</description>
    </item>
    <item>
      <title>asyncio.TaskGroup: quando gather não é suficiente</title>
      <link>https://riverfount.dev.br/posts/asyncio-taskgroup/</link>
      <pubDate>Wed, 12 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/asyncio-taskgroup/</guid>
      <description>&lt;p&gt;Um endpoint de checkout dispara três operações concorrentes com &lt;code&gt;asyncio.gather&lt;/code&gt;: cobra o cartão, reserva o estoque, envia a notificação de confirmação do pedido. O serviço de pagamento cai no meio da chamada e lança uma exceção. &lt;code&gt;gather&lt;/code&gt; propaga esse erro imediatamente para quem está aguardando. O handler captura a exceção, devolve um 500 para o cliente, registra a falha no log. Para quem está de plantão, o sistema reagiu do jeito certo.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Protocol: duck typing com garantias em tempo de análise</title>
      <link>https://riverfount.dev.br/posts/protocol_duck_typing_mypy/</link>
      <pubDate>Wed, 22 Jul 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/protocol_duck_typing_mypy/</guid>
      <description>&lt;p&gt;Você herdou um sistema de cálculo de descontos. Não tem classe base, não tem ABC, não tem interface formal nenhuma. Cada tipo de desconto (cupom, fidelidade, campanha sazonal) é só uma classe qualquer com um método &lt;code&gt;aplicar(pedido)&lt;/code&gt; que devolve o valor final. O código que orquestra isso nem sabe que tipo de objeto está recebendo, só chama &lt;code&gt;desconto.aplicar(pedido)&lt;/code&gt; e segue em frente. Duck typing raiz: se anda como pato e grasna como pato, aplica desconto como pato.&lt;/p&gt;</description>
    </item>
    <item>
      <title>O backend não ficou pronto e o frontend não pode esperar</title>
      <link>https://riverfount.dev.br/posts/json_server_mock_api/</link>
      <pubDate>Sat, 11 Jul 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/json_server_mock_api/</guid>
      <description>&lt;p&gt;Você está construindo a tela de uma lista de tarefas. Os componentes estão prontos, o layout se comporta em qualquer largura de tela, e falta uma única coisa: buscar as tarefas de algum lugar. Só que a API que deveria devolver essas tarefas ainda não existe. Está na fila de outra equipe, ou é você mesmo que vai escrevê-la depois. Talvez em FastAPI, talvez em Django, quando o frontend já estiver de pé. De qualquer forma, hoje ela não responde, e o &lt;code&gt;fetch&lt;/code&gt; que você acabou de escrever aponta para o nada.&lt;/p&gt;</description>
    </item>
    <item>
      <title>O bug que o mypy teria pego antes do deploy</title>
      <link>https://riverfount.dev.br/posts/bug_mypy_pegaria_antes_deploy/</link>
      <pubDate>Fri, 26 Jun 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/bug_mypy_pegaria_antes_deploy/</guid>
      <description>&lt;p&gt;A função recebe um pedido vindo de uma integração externa, soma o valor de cada item e aplica um desconto. Em homologação, com os pedidos de teste, funciona perfeitamente. Em produção, na terceira semana, um cliente específico começa a receber o erro &lt;code&gt;TypeError: unsupported operand type(s) for +: &#39;float&#39; and &#39;str&#39;&lt;/code&gt; em pleno checkout.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;calcular_total&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;itens&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;list&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;total&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;item&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;in&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;itens&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;total&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;item&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;preco&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;item&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;quantidade&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;total&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;item&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;desconto&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Note que a assinatura já tem uma anotação de tipo: &lt;code&gt;itens: list&lt;/code&gt;. Ela não é falsa, mas é rasa o suficiente para não dizer nada de útil. &lt;code&gt;list&lt;/code&gt; não revela que cada elemento é um dicionário com chaves específicas, nem que &lt;code&gt;desconto&lt;/code&gt; deveria ser numérico. Essa anotação solta passa pelo code review sem levantar suspeita, porque parece tipagem, mas não carrega informação nenhuma sobre o formato real dos dados. É esse tipo de anotação incompleta, não a ausência total de anotação, que vai aparecer recorrentemente neste artigo como o verdadeiro adversário.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Decisões de arquitetura para uma integração com webhook, retry e fallback</title>
      <link>https://riverfount.dev.br/posts/decisoes_de_arquitetura/</link>
      <pubDate>Thu, 18 Jun 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/decisoes_de_arquitetura/</guid>
      <description>&lt;p&gt;Você precisa integrar com dois serviços externos de avaliação de crédito, e eles não se parecem em nada na hora de responder. O principal recebe a proposta, processa por alguns minutos e te chama de volta por um webhook. O fallback — acionado só quando o principal falha — não chama ninguém: você é quem precisa ficar perguntando se ele já terminou. A tentação é tratar tudo isso como uma chamada com um &lt;code&gt;try/except&lt;/code&gt; em volta. No caminho feliz, funciona. É no resto que mora este artigo.&lt;/p&gt;</description>
    </item>
    <item>
      <title>suas queries do SQLAlchemy podem ser cacheadas sem Redis manual</title>
      <link>https://riverfount.dev.br/posts/dogpile_cache_sqlalchemy/</link>
      <pubDate>Tue, 02 Jun 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/dogpile_cache_sqlalchemy/</guid>
      <description>&lt;p&gt;O pool está configurado. As queries têm índice. O &lt;code&gt;lru_cache&lt;/code&gt; eliminou as buscas repetidas nos
endpoints mais simples. Mesmo assim, um endpoint de relatório continua lento, não porque está
mal escrito, mas porque ele é genuinamente caro: agrega dados de várias tabelas, cruza informações
de três meses, e faz isso a cada requisição, mesmo que os dados subjacentes não mudem por horas.&lt;/p&gt;
&lt;p&gt;O &lt;code&gt;lru_cache&lt;/code&gt; não resolve. Ele cacheia por argumentos exatos, e os filtros de data variam o
suficiente para inviabilizar o hit rate. O Redis resolve, mas exige serializar o resultado
manualmente, gerenciar a chave, decidir em que camada a invalidação acontece, código de infraestrutura
espalhado pela camada de negócio. O que falta é uma abstração que entenda o ORM.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Por que a aplicação travava mesmo com queries rápidas</title>
      <link>https://riverfount.dev.br/posts/connection-pooling-sqlalchemy/</link>
      <pubDate>Tue, 05 May 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/connection-pooling-sqlalchemy/</guid>
      <description>&lt;p&gt;O profiling não encontrou nada. As queries estão com índice, rodam em menos de 5ms,
e o cache eliminou as buscas repetidas. Mas sob carga — dez, vinte requisições
simultâneas — a aplicação trava. Requisições acumulam na fila, o tempo de resposta
explode, e o log mostra um erro que parece absurdo: &lt;code&gt;TimeoutError: QueuePool limit of size 5 overflow 10 reached&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;O banco de dados não está sobrecarregado. As queries são rápidas. O problema está entre
a aplicação e o banco — no pool de conexões que ninguém configurou.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Sua aplicação está buscando os mesmos dados várias vezes</title>
      <link>https://riverfount.dev.br/posts/cache-lru-redis/</link>
      <pubDate>Fri, 17 Apr 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/cache-lru-redis/</guid>
      <description>&lt;p&gt;O profiling apontou um endpoint lento. Você abre o relatório do cProfile, ordena por &lt;code&gt;cumtime&lt;/code&gt;, e o topo está dominado por chamadas ao banco de dados. Antes de qualquer coisa: se o problema for N+1 queries, cache não é a solução — é um emplastro. N+1 se resolve na query, com joins, &lt;code&gt;selectinload&lt;/code&gt; ou subqueries conforme o ORM. Depois disso, índices. Cache entra só se, após a query estar correta e os índices no lugar, a performance ainda não for suficiente.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Hypothesis encontra os bugs que seus testes ignoram</title>
      <link>https://riverfount.dev.br/posts/hypothesis_property_based_testing/</link>
      <pubDate>Tue, 14 Apr 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/hypothesis_property_based_testing/</guid>
      <description>&lt;p&gt;A suite de testes está verde. Fixtures bem organizadas, parametrize cobrindo os casos
óbvios, mocks isolando as dependências externas. Cobertura em 94%. O PR passa no CI e
vai para produção.&lt;/p&gt;
&lt;p&gt;Três dias depois, um usuário reporta um comportamento estranho. Você reproduz o bug
localmente com um input que nunca ocorreu a ninguém testar: uma string vazia em que se
esperava pelo menos um caractere, um número negativo em que a função assumia valores
positivos, uma lista com um único elemento no qual a lógica de comparação silenciosamente
quebra. O teste que teria pego isso seria trivial de escrever — se alguém tivesse pensado
em escrever.&lt;/p&gt;</description>
    </item>
    <item>
      <title>dataclass, NamedTuple, attrs ou pydantic: qual usar de verdade?</title>
      <link>https://riverfount.dev.br/posts/cover-dataclass_namedtuple_attrs_pydantic./</link>
      <pubDate>Fri, 10 Apr 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/cover-dataclass_namedtuple_attrs_pydantic./</guid>
      <description>&lt;p&gt;Existe um ponto no crescimento de qualquer projeto Python em que os dicionários começam a doer. Não de vez — vai acontecendo aos poucos. Você passa um &lt;code&gt;dict&lt;/code&gt; para uma função, a função passa para outra, e em algum momento ninguém mais sabe ao certo quais chaves estão garantidas, qual é o tipo de cada valor, ou o que acontece se uma chave estiver faltando.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;calcular_desconto&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pedido&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;dict&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;float&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# pedido tem &amp;#34;valor&amp;#34;? &amp;#34;valor_bruto&amp;#34;? &amp;#34;subtotal&amp;#34;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;# &amp;#34;cliente&amp;#34; é um dict também? tem &amp;#34;nivel&amp;#34;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;pedido&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;valor&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;_fator&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pedido&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;cliente&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;][&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;nivel&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Funciona. Ninguém vai questionar em code review. O problema aparece três meses depois, quando alguém passa um pedido sem a chave &lt;code&gt;&amp;quot;nivel&amp;quot;&lt;/code&gt; — ou quando você tenta debugar e o &lt;code&gt;repr&lt;/code&gt; do dicionário tem quarenta chaves misturadas.&lt;/p&gt;</description>
    </item>
    <item>
      <title>O .env que você não deveria ter commitado</title>
      <link>https://riverfount.dev.br/posts/env_vars_secrets/</link>
      <pubDate>Mon, 06 Apr 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/env_vars_secrets/</guid>
      <description>&lt;p&gt;Existe uma busca no GitHub que retorna milhares de resultados úteis para um atacante:
&lt;code&gt;filename:.env DB_PASSWORD&lt;/code&gt;. Repositórios públicos com arquivos &lt;code&gt;.env&lt;/code&gt; commitados por
acidente, contendo senhas de banco, chaves de API, segredos JWT — tudo em texto claro,
indexado, pesquisável.&lt;/p&gt;
&lt;p&gt;Não é incompetência. É o resultado natural de uma prática que parece razoável: colocar
credenciais num arquivo, adicionar esse arquivo ao &lt;code&gt;.gitignore&lt;/code&gt;, e confiar que o
&lt;code&gt;.gitignore&lt;/code&gt; vai proteger. Funciona até o dia que não funciona — um &lt;code&gt;git add .&lt;/code&gt; no
momento errado, um novo membro do time que clona o repo e cria o &lt;code&gt;.env&lt;/code&gt; a partir do
&lt;code&gt;.env.example&lt;/code&gt; sem perceber que o exemplo já tem valores reais, ou um editor que cria
arquivos temporários fora do padrão ignorado.&lt;/p&gt;</description>
    </item>
    <item>
      <title>JWT: três erros que todo mundo comete na primeira implementação</title>
      <link>https://riverfount.dev.br/posts/jwt_tres_erros/</link>
      <pubDate>Thu, 26 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/jwt_tres_erros/</guid>
      <description>&lt;p&gt;Você abre o README do &lt;code&gt;PyJWT&lt;/code&gt;, copia o exemplo de dez linhas, gera um token, valida do outro lado — e funciona. O token tem o &lt;code&gt;user_id&lt;/code&gt;, expira em uma hora, a assinatura bate. O que pode estar errado?&lt;/p&gt;
&lt;p&gt;Bastante coisa. JWT é um dos padrões mais mal implementados em aplicações web, não porque seja complicado, mas porque os exemplos básicos funcionam mesmo com configurações que criam vulnerabilidades sérias. O código roda, os testes passam, e os problemas aparecem meses depois — ou não aparecem, porque ninguém tentou explorar.&lt;/p&gt;</description>
    </item>
    <item>
      <title>A GIL finalmente saiu do caminho: o que muda com o Python 3.14 free-threaded</title>
      <link>https://riverfount.dev.br/posts/python_314_free_threading/</link>
      <pubDate>Mon, 23 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/python_314_free_threading/</guid>
      <description>&lt;p&gt;Você tem quatro núcleos disponíveis. Seu script Python usa um. Isso nunca foi um bug — era
uma decisão de design que durava desde 1992. O Python 3.14 não remove essa limitação de vez,
mas dá o passo mais concreto até agora para deixá-la para trás.&lt;/p&gt;
&lt;h2 id=&#34;o-que-é-a-gil-e-por-que-ela-importa&#34;&gt;O que é a GIL e por que ela importa&lt;/h2&gt;
&lt;p&gt;A Global Interpreter Lock é um mutex que garante que apenas uma thread execute bytecode Python
por vez dentro de um processo CPython. Ela existe por uma razão pragmática: simplifica
imensamente o gerenciamento de memória e a integração com extensões C, que historicamente
assumem que esse lock existe.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Injeção de dependência do jeito certo: IoC com Dishka e FastAPI</title>
      <link>https://riverfount.dev.br/posts/ioc_dishka/</link>
      <pubDate>Fri, 20 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/ioc_dishka/</guid>
      <description>&lt;p&gt;Você já escreveu algo assim numa aplicação FastAPI?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@router.get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/orders/&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{order_id}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;get_order&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;order_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;SessionLocal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;repo&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;OrderRepository&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;service&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;OrderService&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;repo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;settings&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;TAX_RATE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;service&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;get_order&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;order_id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;finally&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;close&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;O código funciona. Mas há um problema sério: cada endpoint é responsável por montar sua própria árvore de dependências. Quando &lt;code&gt;OrderService&lt;/code&gt; precisar de um &lt;code&gt;CacheClient&lt;/code&gt; e de um &lt;code&gt;EventPublisher&lt;/code&gt;, quem vai sofrer é quem escreve — e depois testa — cada endpoint.&lt;/p&gt;
&lt;p&gt;O FastAPI tem seu próprio sistema de &lt;code&gt;Depends()&lt;/code&gt; que resolve parte disso, mas tem limites quando a aplicação cresce e os grafos de dependência ficam complexos. É aqui que entra o conceito de &lt;strong&gt;Inversão de Controle&lt;/strong&gt; e, mais especificamente, uma biblioteca que acerta onde o &lt;code&gt;Depends()&lt;/code&gt; tropeça: o &lt;strong&gt;Dishka&lt;/strong&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Você provavelmente não precisa desse try/finally</title>
      <link>https://riverfount.dev.br/posts/context_manager/</link>
      <pubDate>Thu, 19 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/context_manager/</guid>
      <description>&lt;p&gt;Existe um padrão que aparece em quase todo projeto Python com mais de algumas semanas de vida. Ele tem variações, mas o esqueleto é sempre o mesmo:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;get_db_connection&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;resultado&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;execute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;resultado&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;finally&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;conn&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;close&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Funciona. Fecha a conexão mesmo se der exceção. Ninguém vai questionar em code review. O problema é que esse bloco vai se repetir em todo lugar que precisar de uma conexão — e quando a lógica de encerramento mudar (adicionar log, métricas, rollback), você vai caçar essa duplicação pelo projeto inteiro.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Por que seu script Python consome mais memória do que deveria</title>
      <link>https://riverfount.dev.br/posts/generators_intertools/</link>
      <pubDate>Tue, 17 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/generators_intertools/</guid>
      <description>&lt;p&gt;Se você já usou o &lt;code&gt;memory_profiler&lt;/code&gt; para inspecionar um script que processa arquivos grandes, provavelmente se deparou com um gráfico de consumo de RAM que sobe em escada — e não desce. O arquivo tem 500 MB, o script consome 600, 700, às vezes mais de 1 GB, e o culpado raramente é o que parece.&lt;/p&gt;
&lt;p&gt;Este artigo começa exatamente aí: num script real com consumo excessivo de memória, explica por que ele se comporta assim, e mostra como generators e &lt;code&gt;itertools&lt;/code&gt; resolvem o problema sem mudar a lógica de negócio.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Testes que Realmente Testam: pytest Além do Básico</title>
      <link>https://riverfount.dev.br/posts/pytest_alem_do_basico/</link>
      <pubDate>Mon, 16 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/pytest_alem_do_basico/</guid>
      <description>&lt;p&gt;No artigo sobre &lt;a href=&#34;https://www.riverfount.dev.br/posts/injecao_dependencia/&#34;&gt;injeção de dependência&lt;/a&gt; ficou um problema em aberto. A classe &lt;code&gt;OrderService&lt;/code&gt;
não dava para testar sem subir banco, sem fazer chamada HTTP real, sem criar arquivo em disco.
A solução apresentada foi injetar as dependências pelo construtor — o que deixa o código
testável. Mas testável não significa testado. Este artigo fecha esse loop.&lt;/p&gt;
&lt;p&gt;O objetivo aqui não é ensinar &lt;code&gt;assert 1 == 1&lt;/code&gt;. É mostrar as ferramentas que separam uma
suite de testes que protege o código de uma suite que só infla a cobertura: fixtures com
escopo controlado, &lt;code&gt;parametrize&lt;/code&gt; para eliminar duplicação, e mocks com &lt;code&gt;pytest-mock&lt;/code&gt; para
isolar dependências externas de verdade.&lt;/p&gt;</description>
    </item>
    <item>
      <title>O Primeiro Plugin para niri &#43; DankMaterialShell</title>
      <link>https://riverfount.dev.br/posts/primeiro_plugin_niri_danklinux/</link>
      <pubDate>Fri, 13 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/primeiro_plugin_niri_danklinux/</guid>
      <description>&lt;p&gt;O blog tem bastante conteúdo sobre software, Python e hardware embarcado. Mas há um lado que nunca apareceu por aqui: o ambiente de trabalho em si. Este é o primeiro relato sobre o setup com o compositor Wayland &lt;strong&gt;niri&lt;/strong&gt; e o &lt;strong&gt;DankMaterialShell&lt;/strong&gt; — e começa pelo primeiro plugin criado do zero para esse ambiente.&lt;/p&gt;
&lt;p&gt;A motivação foi simples: queria ver no painel a versão do kernel em uso e o tempo de uptime do sistema. Sem abrir terminal, sem script externo. Só um widget discreto na barra mostrando &lt;code&gt;6.19.6-arch1-1  ⏱ 7h 54m&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Controlando Hardware pelo Celular: Uma Experiência com ESP32 e MQTT</title>
      <link>https://riverfount.dev.br/posts/controlando-hardware-pelo-celular-esp32-mqtt/</link>
      <pubDate>Wed, 11 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/controlando-hardware-pelo-celular-esp32-mqtt/</guid>
      <description>&lt;p&gt;O &lt;a href=&#34;https://riverfount.dev.br/posts/hello-world-hardware-esp32&#34;&gt;post anterior&lt;/a&gt; mostrou o Blink — o Hello World do hardware embarcado. Um LED piscando sozinho, controlado por um timer, sem nenhuma interação externa. Era o suficiente para validar o ambiente, mas deixava uma pergunta óbvia no ar: e se a gente quiser controlar esse LED de verdade? De outro dispositivo, em tempo real, sem cabos?&lt;/p&gt;
&lt;p&gt;Essa pergunta levou ao experimento deste post: usar o protocolo MQTT para acionar um LED no ESP32 a partir de um celular, com um broker Mosquitto rodando localmente no PC. O resultado funcionou. O caminho até lá teve algumas surpresas que valem ser documentadas.&lt;/p&gt;</description>
    </item>
    <item>
      <title>asyncio na prática: quando concorrência resolve e quando atrapalha</title>
      <link>https://riverfount.dev.br/posts/asyncio_na_pratica/</link>
      <pubDate>Tue, 10 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/asyncio_na_pratica/</guid>
      <description>&lt;p&gt;Se você chegou até aqui provavelmente já passou pelo profiling e encontrou um gargalo. A tentação imediata é jogar &lt;code&gt;async/await&lt;/code&gt; em cima do problema e torcer para que o tempo de execução caia. Na maioria das vezes, não cai. Às vezes, piora.&lt;/p&gt;
&lt;p&gt;Este artigo começa mostrando exatamente esse cenário — código assíncrono que não resolve nada — e explica por quê. Depois mostra um caso onde &lt;code&gt;asyncio&lt;/code&gt; faz diferença real, e só então desce para o mecanismo que explica os dois resultados.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Sets em Python: Desvendando O(1) com Operações de Conjunto</title>
      <link>https://riverfount.dev.br/posts/sets_em_python/</link>
      <pubDate>Mon, 09 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/sets_em_python/</guid>
      <description>&lt;p&gt;Se você já usou um &lt;code&gt;set&lt;/code&gt; em Python apenas para remover duplicatas com um &lt;code&gt;.add()&lt;/code&gt; aqui e ali, está deixando na mesa uma das estruturas de dados mais poderosas e mal compreendidas da linguagem. Sets não são apenas listas sem duplicatas — são implementações de conjuntos matemáticos otimizadas para operações de associate arrays com tempo constante O(1), suportando operações que vão de interseção até diferença simétrica com performance que impressiona.&lt;/p&gt;</description>
    </item>
    <item>
      <title>O Hello World do Hardware: Piscando um LED com ESP32</title>
      <link>https://riverfount.dev.br/posts/experiencia_esp32/</link>
      <pubDate>Sun, 08 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/experiencia_esp32/</guid>
      <description>&lt;p&gt;O blog tem bastante conteúdo sobre software — princípios, boas práticas, Python, APIs. Mas há um lado da computação que sempre esteve no horizonte: o hardware embarcado. Este é o primeiro relato de experiência nessa direção, e começa pelo início: o famoso &lt;em&gt;Blink&lt;/em&gt; — o Hello World do hardware.&lt;/p&gt;
&lt;p&gt;A ideia é simples. Pegar uma ESP32, um resistor, um LED, montar o circuito numa protoboard e gravar um programa que faça o LED piscar. O que parece ser coisa de uma tarde revelou algumas surpresas que valem ser registradas.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Argon2 em Python: o jeito certo de guardar senhas</title>
      <link>https://riverfount.dev.br/posts/password_hash_argon2/</link>
      <pubDate>Thu, 05 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/password_hash_argon2/</guid>
      <description>MD5, SHA-256 e bcrypt ainda aparecem em bases de código novas. O que está errado nessa escolha, como o Argon2 resolve o problema e por que o pepper é a camada extra que separa uma implementação boa de uma implementação sólida.</description>
    </item>
    <item>
      <title>Profiling em Python: Encontrando Gargalos com cProfile e memory_profiler</title>
      <link>https://riverfount.dev.br/posts/profiling-em-python/</link>
      <pubDate>Mon, 02 Mar 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/profiling-em-python/</guid>
      <description>&lt;p&gt;Existe um padrão que se repete em quase todo projeto Python que cresce. O código funciona, os testes passam, a feature está pronta — aí alguém percebe que uma rota específica demora três segundos quando deveria demorar duzentos milissegundos. Ou que um processo que roda em batch está consumindo 4 GB de RAM sem nenhuma razão óbvia.&lt;/p&gt;
&lt;p&gt;O instinto natural é abrir o código e começar a suspeitar. Aquele loop ali, essa chamada de banco, aquela list comprehension aninhada. O problema é que intuição é um método caro: você otimiza o que acha que é lento, gasta horas em algo que mal contribui para o tempo total, e o gargalo real continua intacto.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Construindo Bots para o Fediverso com Python e apkit</title>
      <link>https://riverfount.dev.br/posts/translate-bot/</link>
      <pubDate>Fri, 27 Feb 2026 08:14:37 -0300</pubDate>
      <guid>https://riverfount.dev.br/posts/translate-bot/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Como implementar um bot ActivityPub funcional — do WebFinger ao HTTP Signature — e os bugs reais que você vai encontrar pelo caminho.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;O Fediverso cresce a cada ano, e com ele cresce o interesse de engenheiros em criar aplicações que se integram nativamente ao ecossistema descentralizado. O ActivityPub, padrão W3C desde 2018, é o protocolo que cola tudo isso: Mastodon, Pleroma, Pixelfed e dezenas de outras plataformas falam a mesma língua. A boa notícia para quem escreve Python é que existe uma biblioteca que encapsula a complexidade do protocolo e deixa você focar no que o bot realmente faz.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Injeção de Dependência em Python sem Frameworks</title>
      <link>https://riverfount.dev.br/posts/injecao_dependencia/</link>
      <pubDate>Tue, 24 Feb 2026 08:05:23 -0300</pubDate>
      <guid>https://riverfount.dev.br/posts/injecao_dependencia/</guid>
      <description>&lt;p&gt;Existe uma sequência bastante comum em projetos Python: você escreve uma classe, ela funciona bem, aí chega a hora de testar — e percebe que não dá para testar sem subir um banco de dados, sem fazer uma chamada HTTP real, sem criar um arquivo em disco. O código &lt;em&gt;funciona&lt;/em&gt;, mas ele não é &lt;em&gt;testável&lt;/em&gt;. E não testável, na prática, significa frágil.&lt;/p&gt;
&lt;p&gt;O problema quase sempre tem a mesma raiz: a classe criou as próprias dependências em vez de recebê-las.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Decorators Internamente: Como Funcionam e Como Criar os Seus</title>
      <link>https://riverfount.dev.br/posts/decorators/</link>
      <pubDate>Thu, 19 Feb 2026 11:29:23 -0300</pubDate>
      <guid>https://riverfount.dev.br/posts/decorators/</guid>
      <description>&lt;p&gt;Se você escreve Python há algum tempo, já usou decorators sem perceber. O &lt;code&gt;@app.route&lt;/code&gt; do Flask, o
&lt;code&gt;@pytest.mark.parametrize&lt;/code&gt;, o &lt;code&gt;@dataclass&lt;/code&gt; da stdlib, o &lt;code&gt;@property&lt;/code&gt; nativo da linguagem — todos são decorators. Eles
aparecem em todo framework relevante do ecossistema, mas a maioria dos recursos disponíveis explica &lt;em&gt;como usar&lt;/em&gt; sem
explicar &lt;em&gt;por que funciona&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Este artigo corrige isso.&lt;/p&gt;
&lt;p&gt;A ideia aqui não é ensinar a sintaxe do &lt;code&gt;@&lt;/code&gt;. É mostrar o mecanismo embaixo: o que Python faz quando encontra esse
símbolo, como construir um decorator do zero com segurança e como evitar as armadilhas que só aparecem em produção.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Sobre mim</title>
      <link>https://riverfount.dev.br/about/</link>
      <pubDate>Thu, 19 Feb 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/about/</guid>
      <description>&lt;p&gt;Olá! Eu sou Vicente Marçal, também conhecido como &lt;strong&gt;Riverfount&lt;/strong&gt;, desenvolvedor de software especializado em Python,
baseado em Londrina-PR. Apaixonado por programação open source, crio soluções práticas e inovadoras para desafios reais.&lt;/p&gt;
&lt;h2 id=&#34;minhas-habilidades-e-projetos&#34;&gt;Minhas Habilidades e Projetos&lt;/h2&gt;
&lt;p&gt;Trabalho remotamente, com foco em aprendizado contínuo e entrega de software de alta qualidade. Entre meus projetos no
GitHub &lt;a href=&#34;https://github.com/Riverfount&#34;&gt;@Riverfount&lt;/a&gt;, destaco:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;translate-bot&lt;/strong&gt;: Bot ActivityPub para o Fediverso que detecta o idioma de menções e responde com a tradução via Google Translate API. &lt;a href=&#34;https://github.com/Riverfount/translate-bot&#34;&gt;github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;vm-exchange&lt;/strong&gt;: Uma API leve para cotações de câmbio, construída com FastAPI. &lt;a href=&#34;https://github.com/Riverfount/vm-exchange&#34;&gt;github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PesquisaTeses&lt;/strong&gt;: Ferramenta para busca automatizada de teses acadêmicas. &lt;a href=&#34;https://github.com/Riverfount/PesquisaTeses&#34;&gt;github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;vm_cpf_validator&lt;/strong&gt;: Validador eficiente de CPF em Python. &lt;a href=&#34;https://github.com/Riverfount/vm_cpf_validator&#34;&gt;github&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;gen-cutter-sanborn&lt;/strong&gt;: Gerador de códigos para catalogação bibliográfica. &lt;a href=&#34;https://github.com/Riverfount/gen-cutter-sanborn&#34;&gt;github&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Esses projetos open source são apenas a ponta do iceberg, refletindo minha experiência em automação, APIs e ferramentas
práticas para o dia a dia.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Nomear Para Comunicar: Como Escrever Variáveis Claras Concisas e Inteligentes em Python</title>
      <link>https://riverfount.dev.br/posts/nomear_para_comunicar/</link>
      <pubDate>Tue, 13 Jan 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/nomear_para_comunicar/</guid>
      <description>&lt;p&gt;Saber dar bons nomes é uma das habilidades mais valiosas — e menos ensinadas — na engenharia de software. Em Python,
nomes de variáveis e funções bem escolhidos tornam o código legível, reduzem ambiguidade e ajudam a preservar o design
ao longo do tempo. Seguindo as diretrizes da &lt;strong&gt;PEP 8&lt;/strong&gt; e os princípios da &lt;strong&gt;Clean Architecture&lt;/strong&gt;, este artigo mostra
como criar nomes expressivos, consistentes e concisos, sem cair na armadilha dos identificadores longos ou genéricos.
Você verá exemplos reais, más práticas comuns e um mini &lt;em&gt;refactor&lt;/em&gt; que demonstra como nomes claros transformam o código.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Complexidade Ciclomática em Python: Guia Essencial para Engenheiros de Software</title>
      <link>https://riverfount.dev.br/posts/complexidade_clicomatica/</link>
      <pubDate>Fri, 02 Jan 2026 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/complexidade_clicomatica/</guid>
      <description>&lt;p&gt;A complexidade ciclomática mede o número de caminhos de execução independentes em uma função ou módulo Python, ajudando a identificar código difícil de testar e manter. Desenvolvida por Thomas J. McCabe em 1976, essa métrica é calculada como o número de pontos de decisão (if, for, while, etc.) mais um, revelando riscos em fluxos ramificados excessivos.&lt;/p&gt;
&lt;h2 id=&#34;mas-o-que-é-complexidade-ciclomática&#34;&gt;Mas o que é Complexidade Ciclomática?&lt;/h2&gt;
&lt;p&gt;Complexidade ciclomática (CC) quantifica a densidade de caminhos lógicos em um grafo de controle de fluxo. Em Python, cada estrutura condicional ou de loop adiciona ramificações: um &lt;code&gt;if&lt;/code&gt; simples eleva a CC para 2, enquanto &lt;code&gt;and/or&lt;/code&gt; em condições compostas multiplica caminhos independentes. A fórmula básica é &lt;code&gt;CC = E - N + 2P&lt;/code&gt;, onde &lt;code&gt;E&lt;/code&gt; são arestas, &lt;code&gt;N&lt;/code&gt; nós e &lt;code&gt;P&lt;/code&gt; componentes conectados, mas ferramentas como &lt;code&gt;radon&lt;/code&gt; ou &lt;code&gt;flake8&lt;/code&gt; computam isso automaticamente.&lt;/p&gt;</description>
    </item>
    <item>
      <title>PLR2004 na prática: por que evitar números mágicos em expressões booleanas em Python</title>
      <link>https://riverfount.dev.br/posts/plr2004_na_pratica/</link>
      <pubDate>Mon, 29 Dec 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/plr2004_na_pratica/</guid>
      <description>&lt;p&gt;Evitar números mágicos em expressões booleanas é uma recomendação explícita de linters Python modernos (como Pylint e Ruff, via regra PLR2004), pois esses valores dificultam a leitura e a manutenção do código.  Entender essa regra e o contexto em que ela surgiu ajuda a justificar a prática ao time e a padronizar o estilo da base de código.&lt;/p&gt;
&lt;h2 id=&#34;plr2004-de-onde-vem-essa-regra&#34;&gt;PLR2004: de onde vem essa regra?&lt;/h2&gt;
&lt;p&gt;A sigla &lt;strong&gt;PLR2004&lt;/strong&gt; é o identificador da regra &lt;em&gt;magic-value-comparison&lt;/em&gt; em ferramentas de lint para Python, como o linter Ruff, que reutiliza a numeração herdada do Pylint.  A regra é derivada diretamente da mensagem de refatoração &lt;strong&gt;R2004 – magic-value-comparison&lt;/strong&gt; do Pylint, mantido pelo projeto PyCQA, que incentiva o uso de constantes nomeadas em vez de valores mágicos em comparações.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Pattern Matching em Python: Revolucione seu Código Além do Switch Case Tradicional</title>
      <link>https://riverfount.dev.br/posts/pattern_matching/</link>
      <pubDate>Mon, 22 Dec 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/pattern_matching/</guid>
      <description>&lt;p&gt;Descubra como o &lt;strong&gt;pattern matching&lt;/strong&gt; no Python 3.10+ transforma árvores de if/elif em código declarativo e poderoso, superando limitações do switch case clássico. Neste guia técnico para desenvolvedores Python, explore exemplos práticos de destructuring de listas, dicionários e classes, guards e padrões compostos – otimizado para buscas como &amp;ldquo;pattern matching Python tutorial&amp;rdquo;, &amp;ldquo;match case vs switch Python&amp;rdquo; e &amp;ldquo;structural pattern matching exemplos&amp;rdquo;.&lt;/p&gt;
&lt;h2 id=&#34;o-que-torna-o-pattern-matching-único&#34;&gt;O que Torna o Pattern Matching Único&lt;/h2&gt;
&lt;p&gt;Introduzido pelos PEPs 634, 635 e 636 no Python 3.10, o &lt;code&gt;match&lt;/code&gt;/&lt;code&gt;case&lt;/code&gt; vai além da comparação de valores: descreve a &lt;strong&gt;estrutura&lt;/strong&gt; de dados, desconstruindo tuplas, listas, dicionários e objetos em variáveis prontas para uso. Diferente do switch case de C/Java, que compara apenas escalares sem fallthrough automático, aqui o primeiro case que casa encerra o bloco, eliminando bugs comuns. Ideal para APIs REST, eventos JSON e parsers em projetos full-stack Python.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Dominando Dicionários em Python: O Segredo O(1) para DSA Eficiente!</title>
      <link>https://riverfount.dev.br/posts/dominando_dicionarios/</link>
      <pubDate>Tue, 09 Dec 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/dominando_dicionarios/</guid>
      <description>&lt;p&gt;Procurando por &lt;strong&gt;dicionários Python DSA&lt;/strong&gt;, &lt;strong&gt;hash tables em Python&lt;/strong&gt;, &lt;strong&gt;complexidade Big O dict Python&lt;/strong&gt; ou &lt;strong&gt;estruturas de dados Python avançadas&lt;/strong&gt;? Neste guia técnico desvendamos os princípios internos dos dicionários (&lt;code&gt;dict&lt;/code&gt;), desde hashing e colisões até operações otimizadas para algoritmos reais. Ideal para engenheiros de software que buscam performance em microservices, grafos e entrevistas técnicas – leia e eleve seu código Python a outro nível!&lt;/p&gt;
&lt;p&gt;Dicionários em Python (&lt;code&gt;dict&lt;/code&gt;) são uma implementação eficiente de &lt;strong&gt;hash tables&lt;/strong&gt; (tabelas de hash), uma estrutura de dados essencial em DSA para mapear chaves únicas a valores com acesso médio em tempo constante &lt;strong&gt;O(1)&lt;/strong&gt;. Essa performance os torna superiores a listas para operações de busca, inserção e deleção em cenários não ordenados, como caches, contagens de frequência ou representações de grafos. Desde Python 3.7, eles mantêm ordem de inserção, combinando benefícios de hash tables com listas ordenadas.[1]&lt;/p&gt;</description>
    </item>
    <item>
      <title>Generators em Python: Técnicas Essenciais para Código Eficiente e Robusto</title>
      <link>https://riverfount.dev.br/posts/generators_em_python/</link>
      <pubDate>Thu, 04 Dec 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/generators_em_python/</guid>
      <description>&lt;p&gt;Generators em Python são funções especiais que usam &lt;code&gt;yield&lt;/code&gt; para gerar valores sob demanda, economizando memória em vez
de criar listas completas na RAM. Pense neles como &amp;ldquo;listas preguiçosas&amp;rdquo; que produzem um item por vez, ideais para
processar arquivos grandes ou sequências infinitas sem travar o sistema.&lt;/p&gt;
&lt;h2 id=&#34;yield-vs-return-a-diferença-fundamental&#34;&gt;Yield vs Return: A Diferença Fundamental&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;return&lt;/code&gt; encerra a função imediatamente após retornar um único valor, enquanto &lt;code&gt;yield&lt;/code&gt; pausa a execução, retorna um
valor e preserva o estado interno para continuar de onde parou na próxima chamada. Isso permite que uma única função
gere múltiplos valores sequencialmente, como um loop &amp;ldquo;congelado&amp;rdquo; e retomado.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Desvende o Segredo do Garbage Collector do Python: Evite Vazamentos e Otimize Sua Memória Agora!</title>
      <link>https://riverfount.dev.br/posts/segredos_garbage_collector/</link>
      <pubDate>Wed, 03 Dec 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/segredos_garbage_collector/</guid>
      <description>&lt;p&gt;Você já parou para pensar por que seu código Python consome cada vez mais memória em aplicações de longa duração, mesmo sem vazamentos óbvios? Palavras-chave como &amp;ldquo;garbage collector Python&amp;rdquo;, &amp;ldquo;contagem de referências Python&amp;rdquo;, &amp;ldquo;ciclos de referência Python&amp;rdquo; e &amp;ldquo;otimização de memória CPython&amp;rdquo; dominam buscas de desenvolvedores que enfrentam pausas inesperadas, inchaço de heap ou serviços que &amp;ldquo;incham&amp;rdquo; ao longo do tempo. Neste guia técnico expandido e atualizado, um engenheiro especialista em Python mergulha nos mecanismos internos do GC do CPython – com exemplos práticos de código, benchmarks reais e dicas avançadas de tuning – para você dominar a gestão de memória, detectar vazamentos sutis, configurar gerações otimizadas e escalar aplicações de produção sem surpresas.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Primitive Obsession no Python: Refatorando com Dataclasses para Value Objects Robustos</title>
      <link>https://riverfount.dev.br/posts/primitive_obsession_no_python/</link>
      <pubDate>Tue, 02 Dec 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/primitive_obsession_no_python/</guid>
      <description>&lt;p&gt;Baseado na Live de Python #150 do canal &lt;a href=&#34;https://www.youtube.com/watch?v=NtZY3AmsBSk&amp;amp;pp=ygUfZWR1YXJkbyBtZW5kZXMgdGlwb3MgcHJpbWl0aXZvcw%3D%3D&#34;&gt;Eduardo Mendes no YouTube&lt;/a&gt;, este artigo explora de maneira prática e direta a &amp;ldquo;primitive obsession&amp;rdquo; — code smell onde tipos primitivos (strings, dicts, lists) substituem abstrações de domínio ricas — e como dataclasses (Python 3.7+, &lt;a href=&#34;https://peps.python.org/pep-0557/&#34;&gt;PEP 557&lt;/a&gt;) oferecem solução definitiva para criar Value Objects tipados, imutáveis e comportamentalmente ricos. Para sêniores buscando elevar modelagem DDD e reduzir technical debt em escala.&lt;/p&gt;
&lt;h2 id=&#34;primitive-obsession-raiz-do-problema&#34;&gt;Primitive Obsession: Raiz do Problema&lt;/h2&gt;
&lt;p&gt;Primitive obsession ocorre quando entidades de domínio são reduzidas a &amp;ldquo;bags of primitives&amp;rdquo;, i. e., em que objetos de domínio são representados apenas como coleções simples de tipos primitivos (como strings, números, listas e dicionários) sem encapsulamento ou comportamento. Ou seja, em vez de ter classes ou estruturas que representem conceitos ricos com regras, validações e métodos, o código manipula &amp;ldquo;sacos&amp;rdquo; ou &amp;ldquo;pacotes&amp;rdquo; de dados primitivos soltos, o que aumenta a complexidade, propensão a erros e dispersa a lógica de negócio. Aplicando princípios de POO fundamentais: encapsulamento, polimorfismo e responsabilidade única. Consequências incluem:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Arquitetura Hexagonal em Python: Isolando o Domínio para Aplicações Robustas e Escaláveis</title>
      <link>https://riverfount.dev.br/posts/arquitetura_hexagonal_em_python/</link>
      <pubDate>Mon, 01 Dec 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/arquitetura_hexagonal_em_python/</guid>
      <description>&lt;p&gt;A arquitetura hexagonal, ou &lt;strong&gt;Ports and Adapters&lt;/strong&gt;, coloca a lógica de negócio no centro de um hexágono simbólico, cercada por portas (interfaces abstratas) que conectam adaptadores externos como bancos de dados, APIs web, filas ou serviços de terceiros. Proposta por Alistair Cockburn em 2005, ela inverte as dependências tradicionais: o domínio não conhece frameworks ou persistência, mas estes dependem dele via injeção de dependências, promovendo código limpo e adaptável em Python. Essa abordagem alinha-se perfeitamente à filosofia &amp;ldquo;simples é melhor&amp;rdquo; do Python, mas com rigor para domínios complexos.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Scripts Python Autocontidos: Como Rodar Qualquer `.py` com Dependências Embutidas no UV</title>
      <link>https://riverfount.dev.br/posts/scritps_python_autocontidos/</link>
      <pubDate>Fri, 28 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/scritps_python_autocontidos/</guid>
      <description>&lt;p&gt;Você já precisou compartilhar um script Python com colegas e teve que explicar: “Instala o Python 3.12, cria um venv, instala requests e rich, depois roda”? Com o gerenciador UV, isso acabou.&lt;/p&gt;
&lt;p&gt;Agora é possível escrever um único arquivo &lt;code&gt;.py&lt;/code&gt; que já traz suas dependências dentro dele, como &lt;code&gt;requests&amp;lt;3&lt;/code&gt; e &lt;code&gt;rich&lt;/code&gt;, e rodar tudo com apenas &lt;code&gt;uv run script.py&lt;/code&gt;. Neste guia, você vai aprender como usar o bloco &lt;code&gt;# /// script&lt;/code&gt; do UV para transformar scripts comuns em artefatos autocontidos, reprodutíveis e portáteis — perfeitos para automações, ferramentas internas e protótipos.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Descubra o UV: Gerenciador de Projetos Python para Iniciantes</title>
      <link>https://riverfount.dev.br/posts/descubra_o_uv/</link>
      <pubDate>Thu, 27 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/descubra_o_uv/</guid>
      <description>&lt;p&gt;O UV é um gerenciador de pacotes e projetos Python extremamente rápido, escrito em Rust, que substitui ferramentas como &lt;code&gt;pip&lt;/code&gt;, &lt;code&gt;venv&lt;/code&gt; e &lt;code&gt;pipenv&lt;/code&gt; por comandos simples e automação de ambientes virtuais. Ele conecta gerenciamento de versões do Python, instalação de dependências e execução de scripts em um único comando, proporcionando agilidade no desenvolvimento.​&lt;/p&gt;
&lt;h2 id=&#34;instalação-rápida&#34;&gt;Instalação Rápida&lt;/h2&gt;
&lt;p&gt;Para começar, instale o UV facilmente via terminal:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Linux/macOS: &lt;code&gt;curl -LsSf https://astral.sh/uv/install.sh | sh&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Windows PowerShell: &lt;code&gt;irm https://astral.sh/uv/install.ps1 | iex&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Confirme a instalação com &lt;code&gt;uv --version&lt;/code&gt; para garantir que está pronto para uso.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Por que abandonar números mágicos em status codes HTTP</title>
      <link>https://riverfount.dev.br/posts/numeros_maagicos/</link>
      <pubDate>Tue, 25 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/numeros_maagicos/</guid>
      <description>&lt;p&gt;Em desenvolvimento de APIs REST, status codes HTTP são tão importantes quanto o payload da resposta. Eles comunicam, de forma padronizada, o resultado de cada requisição e são consumidos por clientes, gateways, observabilidade e ferramentas de monitoração. Apesar disso, ainda é comum encontrar código repleto de “números mágicos”, como &lt;code&gt;200&lt;/code&gt;, &lt;code&gt;404&lt;/code&gt; ou &lt;code&gt;500&lt;/code&gt; espalhados pela base.&lt;/p&gt;
&lt;p&gt;Uma abordagem mais robusta é substituir esses valores literais por constantes descritivas, como &lt;code&gt;HTTP_200_OK&lt;/code&gt; ou &lt;code&gt;HTTP_404_NOT_FOUND&lt;/code&gt;. Essa prática aproxima o código das boas práticas de engenharia de software e melhora diretamente a legibilidade, a manutenção e a confiabilidade da API.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Usando Abstract Base Classes (ABC) em Projetos Reais de Python: Um Exemplo Prático com Microserviços</title>
      <link>https://riverfount.dev.br/posts/usando_abc/</link>
      <pubDate>Mon, 24 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/usando_abc/</guid>
      <description>&lt;p&gt;Este artigo mostra como aplicar Abstract Base Classes (ABC) em um projeto real robusto, focado no desenvolvimento de microserviços. O objetivo é garantir clareza, contratos explícitos e extensibilidade, aliando os conceitos a práticas modernas.&lt;/p&gt;
&lt;h2 id=&#34;contexto-do-projeto&#34;&gt;Contexto do Projeto&lt;/h2&gt;
&lt;p&gt;Imagine um sistema de microserviços para gerenciamento de pedidos, em que diferentes serviços precisam manipular objetos que representam entidades diversas, como &lt;code&gt;Pedido&lt;/code&gt; e &lt;code&gt;Cliente&lt;/code&gt;. Queremos garantir que todas as entidades sigam um contrato explícito para operações comuns (ex.: obter ID, validação). Além disso, há um repositório genérico para armazenar dados dessas entidades com verificação de tipo.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Protocols, Generics e Typing Avançado em Python: Técnicas para Construir Aplicações Robústas e Manuteníveis</title>
      <link>https://riverfount.dev.br/posts/protocols_generics_typing/</link>
      <pubDate>Fri, 21 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/protocols_generics_typing/</guid>
      <description>&lt;p&gt;Este artigo aborda como usar funcionalidades avançadas de tipagem em Python, como &lt;em&gt;Protocols&lt;/em&gt;, &lt;em&gt;Generics&lt;/em&gt; e técnicas avançadas de &lt;em&gt;typing&lt;/em&gt;, para criar aplicações escaláveis, flexíveis e de fácil manutenção.&lt;/p&gt;
&lt;h2 id=&#34;protocols-contratos-flexíveis-e-estruturais&#34;&gt;Protocols: Contratos Flexíveis e Estruturais&lt;/h2&gt;
&lt;p&gt;Protocols permitem definir contratos de métodos e propriedades sem herança explícita, facilitando a interoperabilidade entre microserviços. Qualquer classe que implemente os métodos definidos no protocolo pode ser usada onde esse protocolo é esperado.&lt;/p&gt;
&lt;p&gt;Exemplo prático:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;typing&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Protocol&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Serializer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Protocol&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;serialize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;bytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;pass&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;JsonSerializer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;serialize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;bytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;{&amp;#34;user&amp;#34;: &amp;#34;alice&amp;#34;}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;XmlSerializer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;serialize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;bytes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;sa&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;lt;user&amp;gt;alice&amp;lt;/user&amp;gt;&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;send_data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;serializer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Serializer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;serializer&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;serialize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sa&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Enviando dados: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;send_data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;JsonSerializer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;send_data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;XmlSerializer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Neste exemplo, &lt;code&gt;send_data&lt;/code&gt; aceita qualquer objeto que implemente o método &lt;code&gt;serialize&lt;/code&gt;, garantindo baixo acoplamento e flexibilidade.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Desvendando a Armadilha dos Argumentos Mutáveis como Default em Python</title>
      <link>https://riverfount.dev.br/posts/desvendando_armadila_argumentos_mutaveis/</link>
      <pubDate>Wed, 19 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/desvendando_armadila_argumentos_mutaveis/</guid>
      <description>&lt;p&gt;Você já enfrentou resultados inesperados ao usar listas ou dicionários como valores padrão em funções Python? Esse é um problema comum que pode causar bugs sutis e difíceis de encontrar. Neste artigo técnico, vamos desmistificar o motivo desse comportamento, mostrando exemplos práticos e como evitá-lo com boas práticas de programação. Se você é um desenvolvedor Python buscando produzir código mais robusto e previsível, este conteúdo é essencial para o seu dia a dia.&lt;/p&gt;</description>
    </item>
    <item>
      <title>`from módulo import *` em Python: por que você nunca deveria usar essa prática</title>
      <link>https://riverfount.dev.br/posts/from_module_import_/</link>
      <pubDate>Tue, 18 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/from_module_import_/</guid>
      <description>&lt;p&gt;Entenda os riscos do uso de &lt;code&gt;from módulo import *&lt;/code&gt; em Python, saiba por que ele compromete a legibilidade e a manutenção do código e descubra as alternativas recomendadas por desenvolvedores experientes.&lt;/p&gt;
&lt;h2 id=&#34;a-armadilha-da-conveniência-em-python&#34;&gt;A armadilha da conveniência em Python&lt;/h2&gt;
&lt;p&gt;Há algo em Python que seduz até os desenvolvedores mais experientes: a promessa de simplicidade. Poucas linguagens conseguem equilibrar legibilidade e poder expressivo como ele faz. Mas é justamente essa aparente simplicidade que, às vezes, nos leva a atalhos perigosos. Entre eles, um velho conhecido: &lt;code&gt;from módulo import *&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Comparações com True em Python: erros comuns e práticas recomendadas para engenheiros</title>
      <link>https://riverfount.dev.br/posts/comparacoes_com_true/</link>
      <pubDate>Mon, 17 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/comparacoes_com_true/</guid>
      <description>&lt;p&gt;No desenvolvimento Python, especialmente em projetos de médio a grande porte e pipelines complexos de testes automatizados, é comum encontrar erros sutis relacionados a comparações com o valor booleano &lt;code&gt;True&lt;/code&gt;. Uma prática aparentemente inofensiva, como usar &lt;code&gt;== True&lt;/code&gt; para verificar condições, pode introduzir comportamentos inesperados que dificultam a manutenção, geram falsos positivos em testes e causam dúvidas em revisões de código.&lt;/p&gt;
&lt;p&gt;Essas situações não são incomuns em equipes que lidam com múltiplas camadas de abstração — desde o código de negócio até frameworks de teste — e evidenciam a importância de entender profundamente a diferença entre identidade e igualdade em Python, bem como as melhores práticas para escrever condicionais claras e robustas.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Como aplicar o Princípio da Inversão de Dependência em Python: um guia prático para sistemas flexíveis</title>
      <link>https://riverfount.dev.br/posts/inversao_dependencia_python/</link>
      <pubDate>Fri, 14 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/inversao_dependencia_python/</guid>
      <description>&lt;p&gt;&lt;strong&gt;Resumo:&lt;/strong&gt;&lt;br&gt;
O Princípio da Inversão de Dependência (DIP), parte do conjunto SOLID, é fundamental para criar sistemas sustentáveis, extensíveis e fáceis de testar. Este artigo explora como aplicá-lo em Python usando &lt;code&gt;typing.Protocol&lt;/code&gt; e injeção de dependência, com foco em arquiteturas limpas e aplicação prática em sistemas corporativos.&lt;/p&gt;
&lt;h2 id=&#34;contexto&#34;&gt;Contexto&lt;/h2&gt;
&lt;p&gt;Projetos orientados a objetos de longo prazo exigem mais do que modularidade: precisam de estabilidade arquitetural. O Princípio da Inversão de Dependência (Dependency Inversion Principle - DIP) aborda exatamente esse ponto.&lt;br&gt;
Ele recomenda que módulos de alto nível (os que contêm as regras de negócio) não conheçam os detalhes de baixo nível (implementações, drivers, frameworks), mas interajam por meio de abstrações.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Segregação de Interfaces em Python: projetando contratos enxutos com ABC e Protocol</title>
      <link>https://riverfount.dev.br/posts/segregacao_interfaces/</link>
      <pubDate>Wed, 12 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/segregacao_interfaces/</guid>
      <description>&lt;p&gt;O Princípio da Segregação de Interfaces (ISP — Interface Segregation Principle) é um dos pilares do SOLID e trata diretamente da qualidade dos contratos entre componentes. Em essência, ele afirma que uma classe não deve ser obrigada a depender de métodos que não utiliza. Essa regra incentiva o desenho de interfaces menores, mais coesas e representativas de um papel específico no sistema.&lt;/p&gt;
&lt;p&gt;Na prática, o ISP força uma reflexão arquitetural: qual é a verdadeira responsabilidade dessa abstração? Se a resposta envolve comportamentos heterogêneos, a interface provavelmente está concentrando demasiadas responsabilidades — um sinal de design frágil e baixo reuso.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Liskov, Duck Typing e Protocolos: Como Python Transforma o Princípio de Substituição</title>
      <link>https://riverfount.dev.br/posts/liskov_ducktyping_protocols/</link>
      <pubDate>Tue, 11 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/liskov_ducktyping_protocols/</guid>
      <description>&lt;p&gt;No mundo da programação orientada a objetos, o Princípio de Substituição de Liskov (LSP) é um guia essencial para criar sistemas robustos e flexíveis. Porém, em Python, esse princípio ganha uma nuance especial graças ao &lt;strong&gt;duck typing&lt;/strong&gt; e aos &lt;strong&gt;protocolos&lt;/strong&gt;, que mudam completamente a forma como pensamos em substituição e hierarquia.&lt;/p&gt;
&lt;p&gt;Neste post, vamos explorar como esses conceitos se entrelaçam, por que o LSP faz tanto sentido na linguagem pythonica e como seu entendimento ajuda a escrever códigos mais limpos, seguros e reutilizáveis — tudo isso sem depender exclusivamente de herança formal. Prepare-se para olhar para o LSP através das lentes de Python e descobrir ferramentas poderosas para o design de software elegante e eficiente.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Como o Princípio Aberto-Fechado Pode Transformar Seu Código Python</title>
      <link>https://riverfount.dev.br/posts/principio_aberto_fechado/</link>
      <pubDate>Mon, 10 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/principio_aberto_fechado/</guid>
      <description>&lt;p&gt;O Princípio Aberto-Fechado (Open-Closed Principle), um dos pilares do SOLID, é essencial para quem busca escrever código Python orientado a objetos mais flexível, escalável e de fácil manutenção. Ele estabelece que entidades de software — como classes, módulos e funções — devem estar abertas para extensão, mas fechadas para modificação.&lt;br&gt;
Em outras palavras, o comportamento do sistema deve poder evoluir sem necessidade de alterar o código existente.&lt;/p&gt;
&lt;h2 id=&#34;entendendo-o-princípio-aberto-fechado&#34;&gt;Entendendo o Princípio Aberto-Fechado&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Aberto para extensão&lt;/strong&gt; significa que o sistema pode adquirir novas funcionalidades.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fechado para modificação&lt;/strong&gt; significa que essas melhorias não devem exigir alterações nas implementações originais, reduzindo a chance de regressões e preservando a integridade do código já testado.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Em Python, a aplicação desse princípio está fortemente relacionada ao uso de &lt;strong&gt;abstrações&lt;/strong&gt;, &lt;strong&gt;polimorfismo&lt;/strong&gt; e &lt;strong&gt;injeção de dependências&lt;/strong&gt;. Projetar para interfaces (ou classes abstratas) é o caminho para permitir evolução sem quebrar funcionalidades existentes.&lt;/p&gt;</description>
    </item>
    <item>
      <title>O Princípio da Responsabilidade Única em Python: menos é mais</title>
      <link>https://riverfount.dev.br/posts/principio_responsabilidade_unica/</link>
      <pubDate>Sun, 09 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/principio_responsabilidade_unica/</guid>
      <description>&lt;p&gt;Em Python, é comum — especialmente pela flexibilidade da linguagem e pelo foco em produtividade — cairmos na armadilha de escrever grandes blocos de código em uma única função, método ou rota. Às vezes, é tentador resolver “tudo em um só lugar”: validar os dados, consultar o banco, tratar erros e ainda montar a resposta final.&lt;/p&gt;
&lt;p&gt;Mas essa abordagem tem um preço. O código cresce, as responsabilidades se misturam e, de repente, você tem uma função que faz de tudo — e nada bem feito.&lt;/p&gt;</description>
    </item>
    <item>
      <title>DRY: o princípio que separa código amador de código profissional</title>
      <link>https://riverfount.dev.br/posts/principio_dry/</link>
      <pubDate>Fri, 07 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/principio_dry/</guid>
      <description>&lt;p&gt;Na prática de desenvolvimento, é comum ver blocos de código duplicados, copiados e colados em diferentes partes de um sistema. Parece inofensivo; afinal, “funciona”. Mas com o tempo, essa abordagem se torna um problema sério. É aqui que entra o princípio DRY — Don&amp;rsquo;t Repeat Yourself — um dos fundamentos mais importantes da engenharia de software moderna.&lt;/p&gt;
&lt;h2 id=&#34;o-que-é-o-princípio-dry&#34;&gt;O que é o princípio DRY&lt;/h2&gt;
&lt;p&gt;O princípio DRY afirma que cada informação, comportamento ou lógica de negócio deve ter uma única representação dentro de um sistema. Repetir código é repetir responsabilidade, e cada duplicação se transforma em um ponto a mais para corrigir quando algo muda.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Como usar Type Hints em Callables no Python para aumentar a qualidade do seu código</title>
      <link>https://riverfount.dev.br/posts/type_hints_callables/</link>
      <pubDate>Thu, 06 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/type_hints_callables/</guid>
      <description>&lt;p&gt;Os Type Hints transformaram a forma como escrevemos e mantemos código Python. Desde que foram introduzidos oficialmente no Python 3.5+, eles se tornaram essenciais em projetos que buscam clareza, segurança e manutenção mais fácil.&lt;/p&gt;
&lt;p&gt;Mesmo sendo uma linguagem dinamicamente tipada, o Python se beneficia muito dessas anotações estáticas, especialmente em callables — funções, métodos e classes. Neste artigo, vamos entender por que usar Type Hints é uma prática que vale o investimento.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Comparando `type()` vs `isinstance()` em Python — e o que o duck typing tem a ver com isso</title>
      <link>https://riverfount.dev.br/posts/type_vs_isinstance/</link>
      <pubDate>Wed, 05 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/type_vs_isinstance/</guid>
      <description>&lt;p&gt;Você sabe qual é a forma mais Pythonic de verificar tipos em seu código? Se ainda usa &lt;code&gt;type()&lt;/code&gt; para testar variáveis, talvez esteja limitando o potencial do seu projeto sem perceber. Entender a diferença entre &lt;code&gt;type()&lt;/code&gt;, &lt;code&gt;isinstance()&lt;/code&gt; e o conceito de duck typing pode transformar a maneira como você escreve código mais limpo, flexível e verdadeiro ao estilo do Python.&lt;/p&gt;
&lt;h2 id=&#34;entendendo-a-diferença-entre-type-e-isinstance&#34;&gt;Entendendo a diferença entre &lt;code&gt;type()&lt;/code&gt; e &lt;code&gt;isinstance()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Em Python, é comum verificar o tipo de uma variável em um &lt;code&gt;if&lt;/code&gt;. Dois padrões clássicos são:&lt;/p&gt;</description>
    </item>
    <item>
      <title>O que é uma API REST? Segunda parte ...</title>
      <link>https://riverfount.dev.br/posts/api_rest_part2/</link>
      <pubDate>Tue, 04 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/api_rest_part2/</guid>
      <description>&lt;p&gt;Dando continuidade ao artigo &lt;strong&gt;&amp;ldquo;O que é uma API REST? Explicação Detalhada para Desenvolvedores&amp;rdquo;&lt;/strong&gt;, esta segunda parte aprofunda-se em um método HTTP essencial que não foi coberto anteriormente: o &lt;strong&gt;PATCH&lt;/strong&gt;, destacando seu papel na atualização parcial de recursos. Enquanto no artigo inicial exploramos os métodos GET, POST, PUT e DELETE para operações completas de criação, leitura, atualização e exclusão, aqui explicamos como o PATCH permite modificações mais precisas e eficientes, sem a necessidade de substituir o recurso inteiro.&lt;/p&gt;</description>
    </item>
    <item>
      <title>O que é uma API REST? Explicação Detalhada para Desenvolvedores</title>
      <link>https://riverfount.dev.br/posts/api_rest_part1/</link>
      <pubDate>Mon, 03 Nov 2025 00:00:00 +0000</pubDate>
      <guid>https://riverfount.dev.br/posts/api_rest_part1/</guid>
      <description>&lt;h2 id=&#34;introdução&#34;&gt;Introdução&lt;/h2&gt;
&lt;p&gt;APIs REST (Representational State Transfer) são um padrão amplamente adotado para comunicação entre sistemas distribuídos, especialmente na web. Elas definem um conjunto de princípios que permitem que aplicações se comuniquem de forma simples, eficiente e escalável usando o protocolo HTTP. Este artigo detalha os conceitos fundamentais, a arquitetura REST e traz exemplos práticos para facilitar o entendimento.&lt;/p&gt;
&lt;h2 id=&#34;conceitos-fundamentais-de-rest&#34;&gt;Conceitos Fundamentais de REST&lt;/h2&gt;
&lt;p&gt;REST não é um protocolo, mas um conjunto de restrições arquiteturais para criar APIs, proposto por Roy Fielding em 2000. Para que uma API seja considerada RESTful, ela deve seguir princípios essenciais:&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
