Divida Tecnica: Como Codigo Legado Vira
Divida tecnica e o Y2K de todo sistema: voce sabe que esta la, sabe que vai cobrar, e continua adiando. Ate que nao da mais pra adiar. Esse
Carregando
Divida tecnica e o Y2K de todo sistema: voce sabe que esta la, sabe que vai cobrar, e continua adiando. Ate que nao da mais pra adiar. Esse
Divida tecnica e o Y2K de todo sistema: voce sabe que esta la, sabe que vai cobrar, e continua adiando. Ate que nao da mais pra adiar. Esse artigo cobre como identificar onde a bomba esta e como desarma-la antes que exploda em producao.
O Y2K custou entre 300 e 600 bilhoes de dolares globalmente para corrigir. O bug do Ariane 5 foi causado por codigo copiado sem revisao das suposicoes do contexto original. O Knight Capital foi derrubado por codigo morto acumulado no sistema. Divida tecnica nao e um problema abstrato de qualidade: e a condicao que os bugs catastroficos precisam para acontecer.
Ward Cunningham, que cunhou o termo divida tecnica nos anos 90, tinha uma analogia financeira precisa. Da mesma forma que divida financeira e legitima quando voce precisa de capital agora e tem capacidade de pagar depois, divida tecnica e legitima quando voce precisa chegar ao mercado antes do concorrente e tem capacidade de refatorar depois. O problema e que poucos times calculam a taxa de juros antes de contrair a divida.
Existem varios tipos de divida tecnica com origens diferentes. Divida deliberada e consciente, como usar uma biblioteca provisoria sabendo que vai ser substituida depois, e gerenciavel se for documentada. Divida deliberada inconsciente, como adotar uma arquitetura sem saber que ela vai ser dificil de escalar, e mais comum do que parece. Divida inadvertida e a que surge de boas praticas que existiam quando o codigo foi escrito mas que a industria superou, como codigo correto em 2010 que usa bibliotecas sem mais manutencao ativa em 2026.
Como um bug de integer overflow destruiu um foguete de 370 milhoes de dolares em 37 segundos.
Integer overflow explicado com exemplos reais e como o Ariane 5 explodiu por causa dele.
A categoria mais perigosa e a divida acumulada por omissao: ninguem decidiu contrair divida, ela foi se acumulando por pequenas decisoes de nao documentar, nao testar, nao atualizar dependencias e nao refatorar quando o codigo ficou mais complexo do que deveria. Essa divida nao tem historico de raciocinio, nao tem data de vencimento e nao tem responsavel claro. E a que mais frequentemente aparece como causa raiz em post-mortems de falhas catastroficas.
O mecanismo e sempre parecido: o sistema sobrevive mais tempo do que as suposicoes originais esperavam. No Ariane 5, o codigo de navegacao foi escrito para os limites de velocidade do Ariane 4. A divida era a ausencia de documentacao das suposicoes de range dos valores. Quando o contexto mudou e o codigo foi reutilizado, ninguem sabia que havia suposicoes de range para verificar.
No Knight Capital, a divida era codigo morto com uma flag de ativacao que ninguem tinha removido porque remover codigo morto nao era prioridade. O custo de nao remover pareceu zero ate que se tornou 440 milhoes de dolares em 45 minutos. No Y2K, a divida era a decisao de armazenar o ano com dois digitos, razoavel em 1965 quando memoria era cara, que acumulou por 35 anos sem que ninguem fizesse o calculo de quanto custaria quando chegasse ao vencimento.
O padrao comum: suposicoes nao documentadas que se tornam invalidas com o tempo, mais a pressao de nao tocar em codigo que funciona, mais a perda de contexto conforme as pessoas que escreveram o codigo original saem. Cada um desses fatores sozinho e gerenciavel. Os tres juntos criam a condicao para falhas que parecem inexplicaveis de fora mas sao completamente compreensíveis quando se conhece a historia do sistema.
Nem toda divida tecnica e igualmente perigosa. A prioridade deve ser inversamente proporcional ao conhecimento disponivel sobre o codigo e diretamente proporcional ao impacto de uma falha. Codigo antigo com documentacao detalhada de suas suposicoes e menos perigoso do que codigo recente sem nenhuma documentacao, mesmo que o codigo antigo seja mais complexo.
A reescrita total e a estrategia mais sedutora e frequentemente a mais perigosa. Joel Spolsky chamou de a coisa mais idiota que um time de software pode fazer. O sistema legado, por mais feio que seja, contem anos de aprendizado sobre casos de borda, regras de negocio implicitas e comportamentos que os usuarios dependem sem saber. Uma reescrita do zero nao herda esse conhecimento, e frequentemente replica os mesmos bugs originais enquanto adiciona bugs novos.
A estrategia do strangler fig, popularizada por Martin Fowler, e mais segura: construir o sistema novo em paralelo ao sistema antigo, roteando gradualmente o trafego para o novo conforme ele e verificado. Cada modulo migrado reduz a superfície do sistema legado sem criar um momento de corte abrupto. O sistema antigo e eventualmente estrangulado pelo novo sem que ninguem tenha passado por um big bang migration.
Para divida tecnica que nao justifica reescrita mas precisa ser gerenciada, a pratica mais eficaz e a regra do escoteiro: sempre deixe o codigo um pouco melhor do que encontrou. Cada pull request que toca uma area de divida tecnica inclui uma pequena melhoria: renomear uma variavel obscura, adicionar um comentario sobre uma suposicao, remover um bloco morto, adicionar um teste para um caminho nao coberto. Esse processo nao paga a divida rapidamente, mas para o acumulo e reduz o risco gradualmente sem impacto nas entregas.
A linguagem que funciona e a de risco e custo de manutencao, nao de qualidade de codigo. Exemplos concretos ajudam mais do que metricas abstratas: 'esse modulo tem causado 3 incidentes de producao nos ultimos 6 meses, cada um custando em media X horas de engenharia para resolver' e mais convincente do que 'esse modulo tem alta complexidade ciclomatica'. A analogia financeira funciona bem: divida tecnica e como divida financeira, tem taxa de juros que se manifesta como velocidade de desenvolvimento decrescente e frequencia crescente de incidentes. Pagar agora e mais barato do que pagar depois com juros.
Vale quando o prazo de vencimento e claro, o custo de pagar e aceitavel, e a decisao e documentada. Um startup que precisa lançar em 2 semanas para nao perder uma janela de mercado pode conscientemente usar uma solucao provisoria com o compromisso explicito de refatorar apos o lancamento. Isso e diferente de usar solucao provisoria sem data de refatoracao. A diferenca entre divida gerenciavel e divida catastrofica e quase sempre a documentacao da decisao: saber que a divida existe, saber por que foi contraida e saber quando precisa ser paga. Sem essa documentacao, a divida e invisivel ate que cause um problema que nao e mais invisivel.