A feature que ninguém admite que está morta

Prévia grátis 5 min de leitura

Uma pessoa de engenharia propõe apagar o botão de exportar CSV. Ele está quebrado há oito meses. O job em segundo plano que gera o arquivo levanta um erro em toda execução, em silêncio, numa fila que ninguém acompanha. Alguém faz um grep no código por csv_export e encontra doze pontos de chamada. O pull request recebe um "melhor não arriscar" e morre na revisão.

Ninguém naquela revisão olhou se o botão era clicado. O grep respondeu "este código é alcançável?", e a pergunta era "alguém está chegando a ele?". O código não consegue responder isso sobre si mesmo; só o tráfego de produção consegue.

Este curso é o espelho dos dois anteriores. Os cursos de nível Sênior "Upgrades Rails sem downtime" e "Migrations de larga escala: gh-ost" tratavam de adicionar e mover coisas sem parar o tráfego. Colunas novas, gems novas e frameworks novos chegavam por baixo de requisições em andamento. Aposentar é a mesma disciplina apontada para o outro lado, removendo uma funcionalidade, um endpoint, uma tabela ou um serviço inteiro, com a mesma restrição. O código precisa continuar atendendo requisições durante todo o tempo em que você o desmonta.

Por que apagar é mais difícil do que parece

Adicionar código é aditivo por natureza: até você virar uma chave, o caminho antigo continua rodando. Um bug no caminho novo não te custa nada que você já não tivesse. Apagar código tira a sua capacidade de responder "alguém precisava disso?" depois do fato. Você não consegue fazer um canary de uma remoção como faz de uma funcionalidade. Depois que o código sumiu, o único rollback é git revert, e quando alguém percebe, o deploy que o quebrou já ficou três releases para trás.

Essa assimetria é o motivo de aposentar sistemas ter um ofício próprio, diferente de escrever menos código:

Adicionar uma funcionalidade Remover uma funcionalidade
Entregar atrás de uma flag Provar primeiro que está morta
Aumentar o tráfego aos poucos Diminuir o tráfego aos poucos
O caminho antigo continua lá se der errado O caminho antigo sumiu se der errado
Rollback = voltar a flag Rollback = implantar o código antigo de novo

"Provar primeiro que está morta" é o assunto da próxima lição. Por enquanto, repare no que matou a revisão da exportação CSV. A única evidência oferecida era estrutural (existem pontos de chamada), enquanto a pergunta era comportamental (alguém está chamando?). Evidência estrutural nunca responde a uma pergunta comportamental. Ela só faz a remoção parecer arriscada o bastante para ser bloqueada, para sempre, sem nenhum jeito de resolver a dúvida.

As quatro coisas que você aposenta, e por que são operações diferentes

Este curso trata quatro alvos como distintos, porque o raio de impacto e as ferramentas mudam:

  • Uma funcionalidade: um fluxo de interface ou um comportamento dentro de uma aplicação que você controla de ponta a ponta. É o menor risco, porque dá para acompanhar o uso dela diretamente.
  • Um endpoint ou uma API pública: tem chamadores que você não controla e nem sempre enxerga. Precisa de uma janela de descontinuação e de um sinal público, porque você não pode remover em silêncio algo de que o sistema de outra pessoa depende.
  • Uma tabela ou coluna: também tem leitores que você não controla. Pense em joins de outras tabelas, queries de relatório, scripts de admin e o SQL avulso de uma consultoria de dois anos atrás. O banco não sabe quem está prestes a quebrar.
  • Um serviço inteiro: a soma dos três, com pipeline de deploy e escala de plantão próprios. Em geral, vem junto a opinião de um segundo time sobre se ele está mesmo morto.

Cada um ganha a própria lição. O que é comum aos quatro, e vale levar pelo curso inteiro, é a ordem. Parar as escritas, depois parar as leituras, depois remover o código, depois apagar o armazenamento. Pule um passo, por exemplo apagando uma coluna antes que todos os leitores tenham parado de lê-la, e você tem o mesmo formato de indisponibilidade de pular um passo numa migration sem downtime. Uma requisição em andamento toca um formato de dados que não existe mais.

O que você vai estudar

  • Lição 2: provar que uma funcionalidade está morta com instrumentação em vez de grep, e por quanto tempo o "silêncio" precisa durar para contar como evidência.
  • Lição 3: o padrão strangler fig rodado ao contrário, e leituras em sombra como o jeito de verificar um substituto antes de confiar nele.
  • Lição 4: reduzir uma flag aos poucos, e a armadilha da flag que sobrevive à funcionalidade que ela protegia.
  • Lição 5: aposentar um endpoint ou uma API pública, com janelas de descontinuação, os cabeçalhos HTTP Sunset e Deprecation, e o que "pública" muda no plano.
  • Lição 6: acabar com um job ou uma fila em segundo plano com segurança. Depois, a ordem de parar escritas, parar leituras, remover código e apagar armazenamento aplicada a uma tabela e a uma coluna.
  • Lição 7: um runbook de aposentadoria que amarra o curso, e a árvore de decisão que diz qual dos quatro alvos uma remoção é.

Uma coisa para levar para a lição 2

O job de exportação CSV que falha em toda execução é, ele mesmo, um tipo de instrumentação, uma acidental. Oito meses de falhas paradas numa fila que ninguém acompanha são evidência de que ninguém depende do resultado. Isso não diz nada sobre se alguém ainda clica no botão esperando que algo aconteça, o que é outra falha, com outra correção. A próxima lição trata de construir a versão deliberada desse sinal, em vez de contar com a sorte da versão acidental.

Aula 1 de 7 · grátis

Continue com a aula 2

Instrumentação antes de apagar

Contadores em produção e uma janela de observação adequada para provar que uma funcionalidade não é usada.

Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.

Digite para buscar...