Pular para o conteúdo
Development

Um segfault que não era um bug, e a API que eu finalmente apaguei

Por Victor Da Luz
iosswifttestingdev-logdeep-cut-atlas

Este app foi renomeado depois para Deep Cut Atlas. Abaixo ele é chamado de “Discoverer” o tempo todo, porque era assim que se chamava no dia em que isso aconteceu.

Essa era para ser a tarefa de limpeza fácil. Uma revisão do repositório tinha sinalizado um punhado de coisas na camada de serviço do MusicKit do Discoverer: alguns métodos que ninguém mais chamava, dois tipos de erro que mostravam mensagens padrão feias em vez de um texto de verdade, uma lógica de correspondência duplicada, e algumas buscas de playlist fazendo mais trabalho do que precisavam. Nada disso era um bug funcional. Tudo isso era o tipo de dívida pequena que só precisava de alguém para realmente ir lá e apagar.

Remover o código morto foi estranhamente satisfatório. Quatro métodos, zero chamadores, confirmados com grep antes de eu tocar em qualquer coisa. Um parâmetro que sempre recebia o mesmo valor fixo em cada ponto de chamada, o que significava que um branch inteiro de código atrás dele nunca tinha rodado fora do único lugar onde era realmente necessário. Apagar código que comprovadamente não faz nada é um dos poucos refactors que parecem completamente seguros, porque você não está adivinhando comportamento, só está removendo um caminho que nada percorre.

Aí rodei a suíte de testes e todos os testes falharam instantaneamente. Não “os testes que eu mexi”. Todos eles, incluindo os que não tinham relação nenhuma, helpers de string, utilitários de chunking de array, coisas que não tinham nada a ver com a minha mudança. Cada um reportou um tempo de execução de zero segundos, o que é o sinal de que algo derrubou todo o processo de testes, em vez de um teste individual realmente falhando.

O log de crash apontava para uma violação real de acesso à memória dentro de uma função completamente diferente daquela que eu estava editando, e a função chamadora que ele indicava não chama essa função em nenhum lugar do código atual. Essa incompatibilidade, um chamador nomeado que não poderia de jeito nenhum chamar o chamado nomeado, foi o que me deixou desconfiado em vez de simplesmente tentar corrigir um bug fantasma. Remover métodos de uma interface compartilhada muda o layout de memória subjacente de como essas chamadas são despachadas, e um build incremental pode acabar colando pedaços compilados de antes e depois da mudança. O resultado roda, mas pula para o lugar errado enquanto o debugger ainda mostra os rótulos antigos.

Um clean completo seguido de rebuild resolveu instantaneamente, sem nenhuma mudança de código. Esse é o truque todo: quando você acabou de mudar quais métodos existem em algo, e a próxima execução de testes dá segfault de um jeito que não faz sentido nenhum, não comece a debugar a função nomeada. Faça o clean primeiro.

O resto da limpeza aconteceu do jeito que uma limpeza deveria: silenciosamente. Dois tipos de erro agora dizem algo que uma pessoa realmente entenderia, em vez de um número bruto de caso de enum. Um bloco duplicado de correspondência de strings virou um único helper compartilhado e testado. Duas buscas de playlist que antes buscavam todas as playlists e vasculhavam até achar a certa agora pedem diretamente a que precisam. Nada disso muda o que o app faz. Tudo isso torna o trabalho da próxima pessoa menor.

Leitura relacionada

Development

Uma seção de tracklist, e por que levou 30 minutos

Um método de protocolo, um enum de estado reaproveitado, uma convenção de roteamento que se manteve, e um orçamento de lint que forçou uma divisão que valia a pena fazer de qualquer forma.

Ler

Você também pode achar útil

Proton

Proton VPN

VPN comercial com filtragem NetShield e interruptor de desligamento automático.

Como parceiro da Proton, ganho com compras qualificadas dos serviços de privacidade e segurança da Proton (Pass, Mail, VPN, Drive).

Saiba mais
Proton

Proton Pass

Gerenciador de senhas focado em privacidade, da equipe por trás do Proton Mail.

Como parceiro da Proton, ganho com compras qualificadas dos serviços de privacidade e segurança da Proton (Pass, Mail, VPN, Drive).

Saiba mais
NordPass

NordPass

Gerenciador de senhas da equipe por trás da NordVPN, com um plano gratuito.

Como afiliado da NordPass, ganho com compras qualificadas.

Saiba mais