O Que É Uma Tabela Hash? Hashing E Colisões Explicados

Buscar uma chave em um dict Python com dez entradas leva o mesmo tempo que buscar em um com dez milhões. Isso não é acidente de uma linguagem rápida. O dict do Python, o HashMap do Java e o Map do JavaScript são todos tabelas hash, e todo o design existe para que busca, inserção e remoção rodem em O(1) na média. A notação Big O dá a essa busca o rótulo “tempo constante”. Este é o mecanismo que justifica isso. ...

4 de novembro de 2026 · 8 minutos · 1631 palavras · SpaghettiCoder

Mock, Stub, Fake e Spy: os Test Doubles Explicados

Um teste para place_order precisa de um gateway de pagamento, um cliente de SMS e uma calculadora de impostos. Use os de verdade e cada execução do teste cobra um cartão e manda um SMS para um número de telefone real. Um teste unitário tem que rodar em milissegundos e sem rede, então os três precisam ser substituídos por outra coisa. Esse “outra coisa” vem em cinco tipos, cada um resolvendo um problema diferente, e tratá-los como intercambiáveis é por isso que as discussões de “só usa um mock” em code review não terminam nunca. ...

2 de novembro de 2026 · 8 minutos · 1646 palavras · SpaghettiCoder

Expressões Regulares Explicadas: Como o Regex Funciona

<.+> contra <b>bold</b> and <i>italic</i> não encontra <b>. Encontra a string inteira, do primeiro < ao último >. Nada está quebrado. É exatamente isso que um quantificador greedy deve fazer, e também é o bug mais comum de “o regex está casando demais”. Depois que você entende o que o motor faz enquanto lê o seu padrão, esse bug e a maioria dos parentes dele deixam de ser mistério. Como um Motor de Regex Lê o Seu Padrão Um motor de regex não compara o seu padrão com a string como você compara duas strings por igualdade. Os motores que você usa no dia a dia (re do Python, RegExp do JavaScript, PCRE, .NET, Java) são regex-directed: eles percorrem o padrão da esquerda para a direita, token por token, e para cada token tentam consumir caracteres da string na posição atual. Quando um token casa, o motor avança tanto o ponteiro do padrão quanto o da string. Quando um token falha, o motor faz backtracking: volta ao último ponto em que tinha uma escolha, como um quantificador que poderia ter casado com menos caracteres ou um ramo de alternância ainda não tentado, e tenta a outra opção. ...

28 de outubro de 2026 · 8 minutos · 1621 palavras · SpaghettiCoder

O Que São Unicode e a Codificação UTF-8

Abra um arquivo salvo como UTF-8 em uma ferramenta que assume outra codificação e café se transforma em café. Os bytes no disco não mudaram. O que mudou foi a regra usada para transformá-los de volta em caracteres, e as duas regras discordam sobre o que o byte 0xC3 significa. A maioria dos bugs de “caracteres estranhos” sai da mesma raiz: nomes de arquivo corrompidos, formulários ilegíveis, um emoji que faz um insert no banco falhar, duas strings que parecem idênticas mas falham na comparação. Por trás de cada um está a confusão entre duas coisas distintas: Unicode e UTF-8. ...

20 de outubro de 2026 · 8 minutos · 1633 palavras · SpaghettiCoder

O Que É TDD e Como Funciona o Ciclo Red-Green-Refactor

Um teste escrito depois do código tende a verificar o que o código faz, não o que ele deveria fazer. O desenvolvimento guiado por testes (TDD) resolve isso invertendo a ordem: você escreve o teste, vê ele falhar, e então escreve o menor código possível que o faz passar. Como o teste existe antes do código que ele verifica, ele não pode confirmar silenciosamente o que quer que o código retorne. Kent Beck formalizou esse ciclo como red, green, refactor em seu livro de 2002 Test-Driven Development: By Example. O nome pegou. ...

18 de outubro de 2026 · 7 minutos · 1442 palavras · SpaghettiCoder

Recursão Explicada: Quando Usar e Quando Evitar

Uma função que chama a si mesma tem uma profundidade máxima, e ela é menor do que a maioria imagina: 1.000 chamadas no CPython por padrão, algo entre 10.000 e 15.000 no Node e nos motores de navegador, dependendo de quanto cada frame ocupa. Passar desse limite não deixa o programa mais lento. Ele trava. O Python lança RecursionError: maximum recursion depth exceeded; o JavaScript lança RangeError: Maximum call stack size exceeded. ...

13 de outubro de 2026 · 7 minutos · 1488 palavras · SpaghettiCoder

Princípios SOLID Explicados com Exemplos em Python

Uma classe que salva um usuário no banco de dados, manda um e-mail de boas-vindas e formata um recibo precisa de uma única mudança para quebrar duas funcionalidades com as quais não tem nada a ver. Você toca no template do e-mail e arrisca a escrita no banco. Você toca no layout do recibo e arrisca o e-mail. SOLID são cinco regras que atacam esse tipo de emaranhado a partir de ângulos diferentes, e compartilham uma ideia: uma classe deve mudar por um único motivo, e o resto do código deve depender do que algo promete fazer, não de como faz isso. ...

10 de outubro de 2026 · 10 minutos · 1967 palavras · SpaghettiCoder

O Que É uma Race Condition e Como Corrigi-la

Duas requisições chegam no mesmo endpoint “sacar 100€” com meio milissegundo de diferença. A conta tem 150€. As duas requisições leem esse saldo, as duas veem fundos suficientes, as duas aprovam, as duas subtraem 100€. A conta termina em -50€, e nenhum trecho do código deveria ter permitido isso. Isso é uma race condition: o resultado depende de qual operação termina primeiro, e “primeiro” nunca foi algo que o código decidiu. ...

9 de outubro de 2026 · 9 minutos · 1900 palavras · SpaghettiCoder

Decoradores Python Explicados com Exemplos

O que um decorador realmente faz com sua função Você quer medir o tempo de cada função que chama uma API externa lenta. Pode colar chamadas a time.perf_counter() em cada uma, ou escrever a medição uma única vez e aplicá-la em todas. Um decorador é a segunda opção: é uma função que recebe outra função, a envolve em um comportamento extra e devolve a versão envolvida com o mesmo nome original. ...

7 de outubro de 2026 · 7 minutos · 1330 palavras · SpaghettiCoder

Por Que 0.1 + 0.2 Não É 0.3: Ponto Flutuante Explicado

Execute 0.1 + 0.2 em um shell Python e você não recebe 0.3. Recebe 0.30000000000000004. Tente em JavaScript, Java, Go, C ou Rust e aparece a mesma cauda de dezesseis dígitos. Cada uma dessas linguagens faz exatamente o que o padrão de hardware determina. Um número que precisaria de infinitos dígitos binários é comprimido em 64 bits, e algo precisa ser descartado. Por que 0.1 não pode ser guardado de forma exata em binário Computadores guardam números de ponto flutuante na base 2. Na base 2, a fração 1/10 tem uma expansão periódica, do mesmo jeito que 1/3 se repete para sempre na base 10 (0.3333...). Escrito por completo, 0.1 em binário começa assim: ...

6 de outubro de 2026 · 6 minutos · 1204 palavras · SpaghettiCoder