Na Ramp, um monorepo de fluxos de trabalho de aprendizado de máquina tinha crescido de um espaço compartilhado conveniente para o que a equipe chamava de "um pouco de pântano": um requirements.txt com dependências transitivas sem versões fixadas que divergiam entre máquinas, formatação inconsistente, nenhum teste automatizado e anotações de tipo ausentes ou sutilmente erradas. Os engenheiros passaram a evitar mexer no código por medo de quebrar algo, e a velocidade, o objetivo original, tinha caído a quase zero.
Em vez de reescrever o repositório, a equipe adotou quatro ferramentas no local: poetry para dependências travadas e reproduzíveis; ruff para formatação e linting; pytest para testar utilitários compartilhados de alto impacto em vez de buscar cobertura total; e mypy para verificação de tipos gradual. O truque que tornou a adoção possível em uma base de código em produção não foi corrigir tudo primeiro. Eles executaram um formatador automático uma vez em todo o repositório em um único commit e depois adicionaram o hash desse commit ao .git-blame-ignore-revs para que ele não poluísse o histórico de blame.
Para linting e tipagem, em vez de corrigir centenas de erros pré-existentes antes de ativar a CI, eles geraram por máquina comentários '# noqa' e '# type: ignore' para cada violação existente e então ativaram a aplicação rígida para qualquer coisa nova. A regra 'RUF100' do ruff e a opção 'warn_unused_ignores' do mypy sinalizavam qualquer comentário de supressão que ficasse obsoleto depois que o código subjacente fosse realmente corrigido, de modo que a lista de ignores só podia encolher, nunca apodrecer silenciosamente.
O resultado foi uma base de código que nunca ficou "limpa" por decreto, mas passou a ser aplicada daquele ponto em diante desde o primeiro dia, com a dívida encolhendo à medida que os desenvolvedores naturalmente mexiam em arquivos antigos.
Dar tratamento legado a violações antigas, aplicar as regras apenas ao código novo
Uma reescrita completa ou uma limpeza de grande impacto consumiria semanas antes que qualquer aplicação de regras pudesse começar, então a equipe passou a aplicar as regras daquele ponto em diante em vez de retroativamente.
Gerar por máquina os comentários de supressão iniciais transformou uma limpeza manual sem limites em uma etapa única e automatizável.
Sinalizar comentários de supressão não utilizados significava que a dívida só podia diminuir, já que corrigir uma violação antiga revelava um comentário de ignore agora inútil que a CI detectaria.
Juntar a reformatação em um único commit e excluí-la do git blame preservou a capacidade de ver quem tocou uma linha por último por um motivo real.
Você não precisa de uma base de código limpa antes de aplicar padrões a ela. Silencie cada violação existente uma vez, aplique as regras estritamente apenas ao código novo, e o acúmulo diminui à medida que as pessoas mexem nos arquivos antigos de qualquer forma.
A equipe relatou que a base de código chegou a um estado em que a qualidade era mantida daquele ponto em diante: o arquivo de lock do poetry proporcionou ambientes consistentes entre as máquinas dos desenvolvedores e a CI, o ruff detectou bugs reais, como chaves de dicionário duplicadas, antes do merge, e o mypy detectou regressões de mudança de assinatura em pontos de chamada que os testes unitários não cobriam. O post enquadra o objetivo como a confiança restaurada para fazer mudanças amplas, não as ferramentas em si, e observa que a equipe ainda estava considerando transferir mais dessa carga dos contribuidores para as ferramentas.
CONFIRA AS EVIDÊNCIAS
As fontes
- Increasing velocity by modernizing a Python codebase Ramp Engineering · builders.ramp.com ·