Escrever código ficou barato, e quem lê ficou caro
Aprovar sem ler é o jeito mais rápido de virar coautor de um defeito.
$ whoami
Julio Cezar Neves
Escrever código ficou barato nesta década, e ler código virou a habilidade mais cara da profissão. A semana trouxe duas provas disso, as duas vindas de projetos que tratam qualidade como assunto sério. Quem ainda mede a própria carreira pela quantidade de linhas que produz está contando uma moeda que acabou de perder valor no câmbio.
A primeira prova veio do kernel. O LWN registrou nesta quarta-feira a primeira série de patches que Linus Torvalds preparou com o auxílio de um modelo de linguagem, conforme ele mesmo havia contado no encontro anual dos mantenedores. São dez patches que mudam a forma como o kernel procura páginas de arquivo na memória, e um teste carregado de chamadas read() ficou cerca de dez vezes mais rápido. A revisão, fiel à tradição da casa, já encontrou uma condição de corrida no código.
A segunda prova chegou do PostgreSQL. Peter Eisentraut, da equipe central do projeto, escreveu na semana passada um texto comentado pelo LWN em que explica por que o beta da versão 19 viu um número incomumente alto de funcionalidades revertidas. Parte da explicação está na revisão de código assistida por LLMs, que passou a encontrar defeitos muito mais depressa. Segundo ele, quase todo o código revertido foi escrito há bastante tempo, quando ninguém ainda pedia programa a uma máquina.
Repare no desenho das duas histórias. Num caso, a máquina ajudou a escrever, e quem leu com atenção já achou um problema. No outro, gente competente escreveu tudo à mão anos atrás, e a máquina ajudou a ler. Defeito antigo tem uma qualidade admirável, porque espera anos, sem reclamar, a chegada de alguém disposto a ler com cuidado. Em ambos os casos, o trabalho que decidiu o destino do código aconteceu depois da escrita.
Estou na computação desde 1969 e já vi a escrita de programas ficar mais fácil muitas vezes. Cada linguagem nova prometia que agora qualquer um escreveria software, e a promessa costumava se cumprir. O que mudava pouco era a outra ponta, a de entender o que o programa faz quando dois eventos acontecem ao mesmo tempo ou quando a entrada chega torta. Essa ponta continua cobrando o mesmo preço de sempre, e agora a conta chega mais cedo.
A condição de corrida, aliás, merece um exemplo, porque ela é o defeito preferido de quem lê com pressa. Pense num script de backup agendado no cron que precisa evitar duas execuções simultâneas. A versão que mais aparece por aí confere se existe um arquivo de trava e, se ele faltar, cria o arquivo e segue em frente:
if [ ! -e /tmp/backup.lock ]; then
touch /tmp/backup.lock
echo "$$ entrou"
sleep 1
rm /tmp/backup.lock
fi
Quem lê esse trecho de cima para baixo enxerga uma lógica impecável. Quem lê pensando em dois processos enxerga um intervalo entre o teste e o touch, e nesse intervalo cabe outro script inteiro. Disparei duas cópias ao mesmo tempo, vinte vezes seguidas, no Bash 5.2.21. As duas entraram nas vinte rodadas, e em todas uma delas ainda reclamou ao apagar uma trava que a outra já tinha removido. Condição de corrida tem um talento raro, porque some sempre que o autor testa o script sozinho, com um processo só e a melhor das intenções.
A correção cabe na mesma quantidade de linhas e troca o teste seguido de ação por uma operação única. O mkdir cria o diretório ou falha, num só passo, e o sistema operacional garante que apenas um dos concorrentes vence:
if mkdir /tmp/backup.lock 2>/dev/null; then
trap 'rmdir /tmp/backup.lock' EXIT
echo "$$ entrou"
sleep 1
else
echo "$$ achou outro backup rodando" >&2
exit 1
fi
Rodei as mesmas vinte rodadas com duas cópias simultâneas, e em todas exatamente um processo entrou enquanto o outro avisou que havia backup em andamento. O trap cuida de remover a trava quando o script termina, inclusive se ele sair antes da hora por causa de um erro. As duas versões passam em qualquer teste feito por uma pessoa só diante do terminal. A diferença entre elas aparece apenas para quem lê o código imaginando o que pode acontecer em paralelo.
Esse tipo de leitura se aprende, e aprende-se devagar. Ela exige saber o que o mkdir e o trap prometem ao sistema, e exige também a desconfiança treinada de quem já viu script bonito derrubar servidor. Uma ferramenta capaz de gerar as duas versões em segundos entrega a mesma confiança nas duas, e cabe a alguém da equipe saber qual delas vai para produção.
O ponto pesa diretamente sobre quem pensa em carreira. Durante muito tempo, o profissional júnior aprendia escrevendo e ouvindo o veterano apontar o erro na revisão. A escrita agora sai pronta e com boa aparência, e o júnior que só aprendeu a pedir código chega à revisão sem o repertório para avaliá-lo. Aprovar sem ler é o jeito mais rápido de virar coautor de um defeito, e o nome no commit fica lá para sempre.
Ler código de outra pessoa incomoda, e por isso tanta gente empurra a tarefa para o fim da fila. Esse código segue uma lógica que ainda precisamos reconstruir e esconde hipóteses que o autor achou óbvias. Ler o próprio código depois de seis meses traz o mesmo incômodo, com o agravante de reconhecer a letra. A boa notícia é que esse músculo cresce com uso, e o terminal oferece material gratuito em quantidade para o exercício.
Os scripts do próprio sistema servem de academia. Abrir com calma um hook do Git ou um instalador baixado da internet ensina mais sobre Shell que muitas horas de vídeo. O man bash também entra nessa conta, porque ler a documentação do interpretador é ler a especificação do que o código promete. Quem lê o manual entende por que o mkdir resolve o que o [ sozinho deixa escapar.
O kernel, que costuma enxergar essas coisas antes do resto do mundo, resolveu a questão há muito tempo com duas linhas no rodapé de cada patch. A documentação de envio de patches explica que o Signed-off-by: certifica quem participou do desenvolvimento, e que o Reviewed-by: declara que alguém fez uma revisão técnica e considerou a mudança aceitável. O revisor assina com o próprio nome, e essa assinatura fica gravada no histórico do projeto ao lado da do autor.
Essa segunda linha vai valorizar bastante nos próximos anos. Qualquer pessoa com acesso a um modelo de linguagem consegue produzir um Signed-off-by: por semana, e poucas conseguem merecer um Reviewed-by: que os mantenedores levem a sério. Se eu tivesse vinte anos e quisesse construir reputação em software livre, passaria um bom tempo lendo patches dos outros antes de mandar os meus. A escrita continua necessária, e cada patch gerado em segundos agora entra numa fila que espera, sem pressa nenhuma, alguém capaz de lê-lo.
PS: Conte nos comentários qual defeito você só enxergou na segunda leitura, depois de jurar na primeira que estava tudo certo, e encaminhe o texto ao colega que aprova pull request pelo celular durante a reunião. Ele vai ler na diagonal, como de costume, e garantir que leu com atenção.
$ tee # compartilhe este artigo WhatsApp Telegram LinkedIn
$ cat comentarios.log
lendo o log…