Steven
Steven7 min de leitura

A Anatomia de Lançar Software até à Perfeição: Como a Revisão de Código Apanhou o que os Testes Não Conseguiram

Ao longo da série GeekBye v2, a mesma coisa continua a acontecer: uma correção passa em todos os testes na máquina do programador e, depois, a revisão de código prova que teria falhado para quase toda a gente. Este é o fluxo de trabalho por trás de nove versões — o portão de revisão, as deteções na fase de correção e a disciplina de testar-antes-de-lançar que transforma o "funciona comigo" em "funciona".

Engenharia
Processo
Revisão de Código
Lançamentos GeekBye
A Anatomia de Lançar Software até à Perfeição: Como a Revisão de Código Apanhou o que os Testes Não Conseguiram

Ao longo de algumas semanas, o GeekBye lançou nove versões — da v2.0.0 à v2.0.11 — e esta série contou a história de cada uma delas. Lidas em conjunto, salta à vista um padrão mais interessante do que qualquer erro isolado: vezes sem conta, uma correção passou em todos os testes na máquina do programador e a revisão de código provou que teria falhado para quase toda a gente.

Essa distância — entre o "funciona comigo" e o "funciona" — é onde a fiabilidade vive de facto. Este é o fluxo de trabalho que a fecha, e o índice de todas as versões que produziu.

O padrão: testes verdes, resposta errada

Aqui estão três dos casos mais claros da série, porque tornam o abstrato concreto.

  • Na correção de captura em múltiplos monitores (v2.0.10), a primeira implementação ancorava a captura de ecrã na janela de sobreposição da aplicação. Passou nos testes — numa máquina de desenvolvimento com um único monitor. A revisão raciocinou sobre onde é que essa sobreposição vive de facto (o ecrã principal, sempre, a menos que a arrastes fisicamente) e provou que a "correção" teria resolvido de volta para o monitor errado para quase todos os utilizadores reais. A âncora correta — o cursor — surgiu desse argumento, não de uma execução de testes.
  • No lançamento do fallback por WebSocket (v2.0.8), a revisão descobriu que o exato 403 que um proxy bloqueador devolve estava classificado como um erro fatal de autenticação — pelo que o fallback que a funcionalidade existia para acionar nunca poderia disparar. A funcionalidade teria sido lançada, passado nos seus testes de caminho feliz e não feito nada pelo seu público real.
  • Na correção do tempo limite de inatividade (v2.0.9), a primeira versão carimbava o relógio de "ainda vivo" dentro de um caminho de código que um subconjunto de transcrições legitimamente ignora — as do outro interlocutor. A revisão apanhou que uma alteração futura poderia reintroduzir silenciosamente o exato erro que estava a ser corrigido, e o carimbo foi movido para um sítio incondicional, com um teste para o manter lá.

Nenhum destes foi apanhado ao correr o código. Todos eles foram apanhados por um revisor a raciocinar sobre porque é que o código funciona — e a encontrar um caso onde não funciona.

As três partes do portão

O fluxo de trabalho por trás da série não é elaborado. São três hábitos aplicados sem exceção.

1. A revisão raciocina sobre a correção, não se limita a correr o código. Um teste que passa prova que o código funciona para o caso que pensaste. A revisão é um segundo modelo, adversarial, do sistema a perguntar em que caso é que não pensaste? — o segundo monitor, o proxy corporativo, a transcrição que ignora o ramo, o cliente que está uma versão atrás. O passo de revisão nesta série foi frequentemente um revisor agente independente, instruído para refutar a correção, não para a abençoar. Esse enquadramento é a questão toda: um revisor a tentar partir o teu raciocínio encontra o buraco que um revisor a tentar aprová-lo passa por cima.

2. Cada correção de comportamento é lançada com um teste que fixa a falha exata. Não um teste de que a funcionalidade funciona — um teste de que este erro específico está morto. O 403 de proxy bloqueado tem de cair para o fallback; um 403 real de autenticação não pode. O relógio de atividade tem de carimbar numa transcrição que ignora a atribuição. Estes testes existem para que o erro não possa regressar sorrateiramente daqui a seis meses quando alguém refatorar por perto — a falha fica pregada ao chão.

3. A compilação é notarizada e verificada antes de ser lançada. Várias destas correções foram do diagnóstico a uma versão assinada, notarizada e com atualização automática em menos de um dia. Essa velocidade só é segura porque o portão é disciplinado: o diagnóstico prova a causa raiz (o lançamento da permissão de microfone lançou o seu diagnóstico primeiro), o teste fixa a correção, a revisão refuta o raciocínio, e só então é que sai uma compilação notarizada de verdade. O rigor é o que torna a velocidade segura, não o que se troca por ela.

Porque é que isto importa mais para uma aplicação de IA

Há uma razão para esta disciplina ser inegociável para uma ferramenta como o GeekBye em particular. Vários dos erros mais desagradáveis da série eram silenciosamente-errados, não estridentemente-falhados: uma captura de ecrã que alimentava o monitor errado à IA (v2.0.10), uma transcrição enviesada para termos de lixo, de modo que "speak" saía como um nome (v2.0.11), um assistente a responder no modo errado sem forma de o ver (v2.0.3 + v2.0.5). Quando a tua aplicação alimenta contexto a um modelo, uma entrada errada produz uma saída confiantemente errada e nenhum erro em lado nenhum. Não consegues testar para sair de falhas que não lançam exceções. Tens de raciocinar para sair delas — que é exatamente para isso que serve o portão de revisão.

A série, por ordem

Cada um destes é um estudo de caso autónomo sobre uma versão. Lidos do início ao fim, são a anatomia de levar um produto de "funciona" a "de confiança".

  1. O que uma versão 2 realmente exige: 206 commits de estados honestos — v2.0.0. A fundação: nunca mostrar um estado que não seja verdadeiro.
  2. O dia em que a nossa aplicação fez DDoS a si própria — v2.0.1 + v2.0.4. Um acumulado de uploads no arranque a atropelar o nosso próprio backend, e a escada de liveness que isso forçou.
  3. Software calmo: a correção do flicker e o selo de modo de resposta — v2.0.3 + v2.0.5. Versões sem funcionalidades que compraram confiança um detalhe de cada vez.
  4. A tua aplicação de Mac esquece o acesso ao microfone a cada arranque — v2.0.6. App Translocation do macOS, e lançar o diagnóstico antes da correção.
  5. Uma variável CSS, cinco rondas de revisão e uma toolchain Swift que mentiu — v2.0.7. Translucidez uniforme, e um binário que mudou de tamanho porque a documentação discordava do script de imposição.
  6. Transcrição em direto quando a firewall bloqueia WebSockets — v2.0.8. Um fallback puramente HTTPS, e o 403 que o teria escondido de si próprio.
  7. Porque é que o teu tomador de notas de IA para de gravar a meio de uma reunião — v2.0.9. Um temporizador de inatividade que só te conseguia ouvir a ti, e um crash que podia bloquear o teu ambiente de trabalho.
  8. Porque é que a gravação de ecrã captura o monitor errado — v2.0.10. O erro do ecrã errado, e a correção que passou num monitor e teria falhado em dois.
  9. Porque é que a transcrição de IA percebe mal os termos técnicos — v2.0.11. Enviesar a fala para o teu vocabulário — e a regressão que a piorou antes de a melhorar.

A conclusão

A perfeição não é um estado a que se chega; é um portão que se mantém. Nove versões, e as mesmas três perguntas em cada uma: em que caso é que não pensaste, a falha exata está fixada por um teste, e uma compilação assinada de verdade saiu mesmo? Nada disto é glamoroso. Tudo isto é a razão pela qual o GeekBye v2 se sente calmo. Se constróis software — IA ou outra coisa — a parte transferível não é qualquer correção isolada. É o hábito de tratar uma suíte de testes verde como o início do argumento, não o fim dele.

Todas as versões acima estão em direto via atualização automática. Para o produto em que estas correções se somam, vê o que há de novo no GeekBye v2.