Quatro números decidem quando reescrever software legado
Quatro medidas mostram quando reescrever software legado, quando continuar reparando e como defender a decisão com evidências concretas.

Reescrever um sistema legado se justifica quando o custo e o risco de alterá-lo superam o custo e o risco de substituí-lo. Idade, linguagem e preferência arquitetônica não respondem a essa pergunta. Quatro medições respondem: taxa de falha das mudanças, parcela da equipe que consegue mexer no código com segurança, parcela do ambiente de execução sem suporte e custo de um único incidente grave.
Já vi equipes aprovarem uma reescrita porque um framework parecia antigo e depois descobrirem que o aplicativo velho mudava duas vezes por ano sem causar problemas. Também vi equipes defenderem a "melhoria incremental" enquanto um único mantenedor sustentava um sistema de produção em uma plataforma sem suporte. As duas decisões nasceram de intuição disfarçada de engenharia. Coloque os quatro números em uma página e fica bem mais difícil manipular a discussão.
Decisões de reescrita precisam de medições, não de limite de idade
Não existe idade a partir da qual um software se torna automaticamente candidato à reescrita. Um serviço de quinze anos com interfaces estáveis, dependências suportadas, bons testes e vários mantenedores seguros pode ser mais barato de conservar que um serviço de três anos que falha em toda entrega. A idade indica onde investigar, mas não decide.
O mesmo vale para a linguagem. COBOL, RPG, VB6, Delphi ou uma versão antiga de PHP podem criar problemas de contratação e suporte, mas o nome da linguagem não quantifica nenhum deles. Um lote COBOL bem compreendido que processa um arquivo fixo toda noite pode merecer mais uma década. Um pequeno serviço JavaScript que só um contratado entende talvez já seja um risco operacional.
Comece com uma janela de medição que inclua entregas normais e pelo menos um período exigente do negócio. Um trimestre costuma funcionar para equipes que implantam regularmente. Um sistema que muda devagar pode exigir mais tempo, mas não espere para sempre por dados perfeitos. Registre a incerteza ao lado de cada número e melhore a medição ao longo do trabalho.
Use a mesma unidade de análise para as quatro medidas. Decida se está avaliando um aplicativo, um serviço implantável ou um grupo muito acoplado que precisa mudar em conjunto. Medir falhas em todo um portfólio e mantenedores em um único repositório produz uma ficha bonita e sem significado.
Os quatro números respondem a perguntas diferentes:
- A equipe consegue mudar o sistema sem quebrar a produção?
- Quantas pessoas conseguem fazer essa mudança sem supervisão?
- Quanto do software em execução deixou de receber correções dos responsáveis?
- O que a empresa perde quando o sistema causa um incidente grave?
Nenhum deles tem limite universal. Defina uma fronteira adequada à tolerância ao risco e escreva qual ação ocorrerá ao cruzá-la. O valor está em usar a mesma regra antes de uma pane, quando ninguém consegue torcê-la para sustentar a conclusão que já queria.
A taxa de falha expõe o imposto de cada entrega
A taxa de falha das mudanças informa qual parcela das alterações em produção exige reparação porque causou serviço degradado, interrupção, reversão ou correção urgente. A DORA usa essa ideia como medida de desempenho da entrega de software. Eu manteria a definição restrita: conte falhas causadas por uma mudança, não todo incidente ocorrido perto de uma implantação.
Defina o que conta como mudança em produção antes do cálculo. Inclua implantações de aplicativos, migrações de banco, versões de configuração, mudanças de agendador e infraestrutura quando a equipe controla tudo como um processo de entrega. Não conte uma repetição comum como outra mudança falha nem transforme dez commits emergenciais após uma entrega ruim em dez falhas independentes.
O cálculo básico é simples:
change_failure_rate = failed_production_changes / total_production_changes
A classificação é a parte difícil. Para toda mudança falha, registre a mudança que iniciou o problema, o efeito no cliente, a ação de recuperação e se o defeito veio de código, dados, configuração ou interação desconhecida. Uma etiqueta como change-failure basta se todos a aplicarem da mesma forma. Reveja mensalmente os casos discutidos com engenharia e operações na mesma sala.
Não compare taxas brutas de sistemas com padrões de entrega radicalmente diferentes. Um aplicativo pode publicar cem pequenas mudanças, enquanto outro publica uma versão agrupada. Apresente a taxa junto ao volume e ao tempo mediano de recuperação. Dez por cento em dez controles reversíveis não cria o mesmo risco que dez por cento em versões trimestrais de banco cuja restauração leva seis horas.
A tendência importa mais que uma leitura isolada. Se a taxa cai após melhores testes, observação e entregas menores, os reparos estão devolvendo controle. Se continua alta depois de duas ou três tentativas focadas, a arquitetura talvez esteja derrotando o processo. Procure causas recorrentes: estado mutável compartilhado, ordem de lotes sem documentação, contratos ocultos do banco e etapas de implantação impossíveis de ensaiar. Esses padrões encarecem toda função futura.
Não premie uma equipe por evitar mudanças. Um sistema sem implantações tem uma taxa indefinida ou enganosamente perfeita. Acompanhe a demanda adiada porque publicar parecia arriscado demais. Quando mudanças do negócio se acumulam pelo medo de tocar a produção, a ausência de falhas prova paralisia, não saúde.
Responsabilidade segura é menor que acesso ao repositório
A parcela de toque seguro é a proporção da equipe relevante que consegue fazer, revisar, implantar e recuperar de forma independente uma mudança significativa no sistema. Acesso ao repositório não conta. Saber editar um arquivo enquanto o único especialista dita cada passo também não.
Defina uma mudança significativa com o trabalho que o sistema recebe de verdade. Pode ser adicionar um campo passando pelo banco, serviço e interface; alterar um cálculo com consequências financeiras; ou mudar uma rotina noturna sem quebrar sua retomada. A tarefa deve cruzar os limites onde o conhecimento costuma desaparecer.
Avalie cada engenheiro em quatro capacidades:
- Explicar o caminho de execução afetado e suas dependências.
- Implementar e testar a mudança sem copiar um exemplo que não entende.
- Publicá-la pelo processo real de produção.
- Diagnosticar uma falha e restaurar o serviço sem esperar pelo oráculo do sistema.
Conte uma pessoa apenas quando evidências recentes sustentarem as quatro. Trabalhar em dupla ajuda a ensinar, mas não prova autonomia. Revisões, participação em incidentes e uma alteração bem-sucedida em produção dão provas melhores que uma autoavaliação.
Calcule então:
safe_touch_share = independent_safe_maintainers / relevant_engineers
Registre também o número absoluto. Uma parcela de 50% parece saudável até significar uma pessoa em duas. Por outro lado, quatro mantenedores capazes em uma equipe de vinte podem cobrir bem um aplicativo interno estável, desde que plantões e férias não retirem os quatro ao mesmo tempo.
Essa medida expõe uma distinção que equipes confundem: documentação disponível não é conhecimento operacional. Um manual de mil páginas pode explicar telas e tabelas e omitir por que a liquidação deve vir antes da conciliação, quais registros ruins os operadores consertam à mão ou como retomar uma rotina sem contabilizar duas vezes. Teste o documento pedindo a um novo mantenedor que o use com supervisão. As perguntas dele fazem parte da especificação ausente.
Uma parcela em queda costuma ser o primeiro sinal de reescrita porque esconde um prazo. Aposentadoria, demissão ou saída do fornecedor podem tornar um sistema difícil impossível de mudar de um dia para o outro. Se a transferência aumenta a parcela e as pessoas treinadas continuam fazendo mudanças seis meses depois, os reparos ainda têm defesa. Se toda tentativa leva o trabalho de volta ao mesmo especialista, pare de chamar a situação de treinamento.
A parcela sem suporte mede exposição, não constrangimento
A parcela sem suporte é a proporção da pilha de produção que deixou de receber correções de segurança ou funcionamento do fornecedor ou projeto responsável. Ela inclui mais que a linguagem. Conte sistemas operacionais, bancos, servidores de aplicativos, ambientes de execução, grandes frameworks, drivers e middleware essencial.
Inventarie o que realmente roda, não o que o diagrama afirma. Extraia versões de servidores, imagens de contêiner, arquivos de dependência, definições de tarefas e consultas ao banco. Em mainframes ou sistemas intermediários, inclua compiladores, monitores de transação, agendadores e componentes do fornecedor no caminho. Registre a fonte de cada data de suporte para que boatos de compras não virem política.
Um cálculo ponderado útil é:
unsupported_runtime_share = sum(weight_of_unsupported_components) / sum(weight_of_all_components)
Defina pesos por exposição e papel no negócio. Um servidor público sem suporte merece mais peso que um conversor isolado usado uma vez por mês. Mantenha a ponderação simples o bastante para outro engenheiro reproduzir. Se uma comissão precisa de uma hora para explicar o peso 7,3 de um componente, a precisão é fictícia.
Sem suporte não significa comprometido, e com suporte não significa seguro. Significa que o responsável parou de fornecer um caminho normal de correção. A equipe pode compensar com isolamento, patch virtual, controle estrito de entrada ou contrato pago de suporte estendido. Escreva cada controle ao lado do componente e teste se ele cobre todas as entradas.
Procure o núcleo abandonado escondido sob bordas atuais. Navegador, proxy reverso e banco recentes não salvam lógica que exige uma plataforma abandonada. Algumas equipes atualizam tudo em volta do núcleo e informam poucos componentes obsoletos. Ponderar pela importância na execução impede essa contabilidade.
Continuar reparando é razoável quando os componentes sem suporte estão isolados, são estáveis, substituíveis separadamente e cobertos por controles baratos. Fica difícil defender quando um deles aceita entrada não confiável, bloqueia atualização do sistema ou obriga a manter toda uma cadeia obsoleta. A exposição então se acumula: toda atualização vizinha precisa acomodar a peça mais antiga.
O custo de incidente transforma risco técnico em limite do negócio
O custo de um incidente grave é toda a perda desde a detecção até a recuperação e correção, não apenas a conta da nuvem ou as horas extras. Use um incidente real quando possível. Se não houver, monte um cenário com finanças, operações, segurança e o responsável pelo negócio e identifique cada hipótese.
Calcule categorias que alguém consiga verificar:
incident_cost = lost_margin
+ staff_hours * loaded_hourly_cost
+ customer_remediation
+ contractual_or_regulatory_cost
+ data_reconciliation
+ delayed_business_events
Use margem perdida em vez do valor bruto, a menos que as transações desapareçam para sempre. Separe receita atrasada de receita perdida. Conte trabalho manual de operações, finanças, suporte, engenharia e gestão. Inclua os dias após o retorno do serviço usados para conciliar registros, corrigir duplicidades, responder a clientes e preparar avisos obrigatórios.
Não multiplique um valor horário assustador pela maior interrupção imaginável. Defina precisamente o incidente: quatro horas sem captura de pedidos seguidas de um dia de conciliação, por exemplo, ou preços incorretos que chegam aos clientes. Documente volume, margem, custos de pessoal, termos contratuais e hipóteses de recuperação. Finanças deve conseguir contestar o modelo linha por linha.
Use dois custos quando houver modos de falha distintos. Um incidente de disponibilidade e outro silencioso de integridade raramente têm a mesma forma. O segundo pode parecer barato durante a pane porque ninguém o detecta e ficar muito mais caro na reconstrução. Médias escondem a diferença.
O custo muda o argumento porque define quanto vale gastar para reduzir a exposição. Um sistema frágil que sustenta um fluxo interno menor pode continuar recebendo reparos. Outro igualmente frágil que lança registros contábeis ou controla movimentos de fábrica merece tolerância menor nas outras três medidas.
Não transforme o custo em truque de perda esperada sem dados confiáveis de frequência. Multiplicar uma probabilidade anual inventada por uma consequência modelada produz uma cifra limpa com duas entradas fracas. Deixe visíveis evidências de frequência, consequência e incerteza. A liderança consegue decidir sem fingir ciência atuarial.
Coloque os quatro números em uma ficha de decisão
Uma ficha deve mostrar valores atuais, tendência, confiança, limite acordado e ação ligada ao seu cruzamento. Uma página basta. Sua função é forçar escolhas explícitas, não calcular uma resposta que a gestão precise obedecer.
Use uma tabela assim e substitua os limites ilustrativos:
| Medida | Atual | Tendência | Confiança | Limite de decisão | Ação ao cruzar |
|---|---|---|---|---|---|
| Taxa de falha | 18% de 50 mudanças | Subindo | Alta | 15% por duas revisões | Financiar desenho da substituição |
| Parcela de toque seguro | 2 de 14 engenheiros | Caindo | Média | Menos de 3 pessoas | Congelar funções opcionais |
| Parcela sem suporte | 35% ponderados | Igual | Média | 25% com entrada externa | Iniciar contenção ou substituição |
| Custo de incidente grave | US$ 480.000 modelados | Subindo | Baixa | Acima da tolerância | Finanças valida cenário |
Esses valores são exemplos, não referências universais. Uma interface de cobrança hospitalar, uma impressora de etiquetas e um catálogo público precisam de limites diferentes. Os responsáveis devem escolhê-los antes do próximo incidente e guardar as evidências de cada valor.
Não reduza cedo demais as quatro medidas a uma pontuação ponderada. Uma nota 62 esconde se o sistema tem falhas frequentes e baratas ou uma dependência catastrófica sem suporte. Mantenha os quatro eixos visíveis. Se a liderança exigir um estado, use três:
- Continue reparando enquanto as medidas ficarem dentro dos limites e melhorarem.
- Contenha e prepare quando uma cruzar o limite ou várias piorarem.
- Reescreva quando a exposição superar o limite e a correção confiável tiver falhado.
Defina uma data e nomeie quem atualiza cada entrada. Dados de falha podem vir de registros de implantação e incidente. Evidência de responsabilidade pertence à gestão de engenharia. O suporte de plataforma precisa de revisão técnica ou de segurança. Finanças e negócio devem aprovar a consequência.
A ficha também impede aumento de escopo. Se só um agendador cria exposição, substitua esse componente em vez de condenar todo o conjunto. Se a responsabilidade for a única fraqueza, rodízio e documentação talvez resolvam. A reescrita merece aprovação quando as medidas apontam para uma fronteira impossível de reparar economicamente onde está.
Reparar vence quando o risco é limitado e reversível
Continuar reparando é correto quando mudanças falham pouco, várias pessoas conseguem assumi-las, componentes sem suporte têm contenção confiável e um incidente ficaria dentro da tolerância. Uma reescrita consome atenção que poderia melhorar produtos percebidos pelos clientes. Não substitua software estável para satisfazer um diagrama.
Há vários casos fortes para reparos. O sistema pode estar perto de uma retirada planejada porque uma linha de negócio fechará. Seu comportamento pode estar fixado por regra ou contrato, com poucas mudanças previstas. Um fornecedor pode oferecer atualização suportada que remova o ambiente exposto sem tocar na lógica. Ou o aplicativo pode ficar atrás de uma interface estreita e controlada, sem entrada não confiável e com recuperação testada.
O programa de reparos precisa de escopo e condição de saída. Financie atualização de dependências, testes de caracterização, automação da implantação, observação e transferência de conhecimento. Meça de novo. Se a taxa cai e a responsabilidade cresce, está funcionando. Se a equipe reconstrói a mesma implantação frágil ou protege um ambiente que bloqueia todo o resto, o programa virou atraso caro.
Sou contra a regra popular de que todo monólito antigo deve primeiro ser dividido em microsserviços. O conselho parece incremental e por isso soa mais seguro que reescrever. Na prática, extrair serviços de código cujo comportamento ninguém especifica costuma distribuir a incerteza por uma rede. Você adiciona falhas parciais, interfaces versionadas e trabalho operacional antes de provar paridade. Primeiro capture o comportamento na fronteira do sistema. Depois escolha limites que correspondam a capacidades e propriedade dos dados.
Outra opção válida é a substituição seletiva. Mantenha cálculo ou lote estável e troque a interface sem suporte. Coloque uma dependência de banco atrás de um serviço atual. Retire relatórios não usados antes de traduzi-los. Recalcule as medidas para a fronteira restante após cada remoção, pois um núcleo menor pode ficar barato o suficiente para contenção permanente.
Não confunda reparar com não fazer nada. Manter o sistema aceita trabalho concreto: contratos de suporte, teste de controles, exercícios de recuperação, cobertura de pessoal e reavaliação programada. Se ninguém financiar esses itens, a organização não escolheu reparar. Escolheu degradação sem gestão.
A reescrita deve preservar o comportamento antes de mudar a arquitetura
Uma reescrita defensável captura comportamento observável, executa versões antiga e nova contra os mesmos casos e muda a arquitetura apenas onde a evidência permite. Traduzir linha por linha preserva estrutura acidental e pode reproduzir defeitos sem preservar o contexto operacional que os tornava suportáveis.
Comece com evidências parecidas com produção. Grave requisições e respostas quando a política permitir, capture entradas e saídas de lotes, guarde erros representativos e identifique efeitos como arquivos, mensagens, escritas no banco e perguntas ao operador. Remova valores sensíveis, mas preserve distribuições, ordem e casos malformados que exercitam os ramos reais.
Monte um comparador de paridade que envie o mesmo caso aos dois sistemas e compare resultados normalizados. Normalize explicitamente horários, identificadores gerados, ordem sem significado e outros campos não determinísticos. Nunca esconda uma diferença com um filtro de texto amplo. Cada regra deve dizer por que a diferença não importa.
Para comportamento com estado, compare transições, não telas finais. Inicie ambos com o mesmo estado do banco, execute a ação e compare linhas alteradas, mensagens, arquivos e retornos. Para um lote, teste conclusão limpa, retomada após interrupção, entrada duplicada, entrada tardia e falha parcial posterior. Operadores muitas vezes dependem desses casos mais do que desenvolvedores imaginam.
A arquitetura então pode mudar com segurança. Um conjunto COBOL e JCL pode virar serviços Go com Postgres, um núcleo numérico pode justificar Rust e um cliente de desktop pode passar a TypeScript. São decisões de desenho, não objetivos. O objetivo é comportamento de negócio equivalente em um modelo que a equipe atual consiga manter.
CodeHero lê toda a árvore de código e verifica o sistema modernizado com um comparador de paridade contra tráfego gravado de produção, em vez de traduzir arquivos isoladamente. Seus projetos são entregues em menos de 30 dias, inclusive em ambientes regulados onde os modelos fornecidos podem rodar isolados dentro do perímetro do cliente.
Trate falhas de paridade como descobertas de especificação. Algumas revelam defeitos da reescrita. Outras expõem comportamento antigo contraditório, lógica dependente do ambiente ou dados que violam regras supostas. O responsável do negócio precisa decidir quais peculiaridades são contratos e quais são erros. Engenharia não deduz essa resposta apenas do código.
A aprovação exige uma alternativa calculada, não entusiasmo
Uma proposta de reescrita deve competir com um plano completo de reparos e outro de contenção, ambos calculados. Se a alternativa é "continuar sofrendo", a comparação está viciada. Calcule atualizações, testes, especialistas, contratos, controles, exposição a incidentes e atraso de funções que os reparos realmente exigem.
Calcule a reescrita além da implementação. Inclua descoberta, captura de comportamento, conversão de dados, operação paralela, aceitação, troca, preparação de retorno, treinamento e desativação. Atribua responsáveis a decisões e validação de dados. Uma substituição tecnicamente pronta ainda falha se finanças não conciliar saldos ou operações não recuperar um lote incompleto.
Exija evidência para o cronograma. Inventarie integrações, armazenamentos, tarefas, relatórios, papéis, trocas de arquivos e procedimentos. Marque cada item como observado, inferido ou desconhecido. O desconhecido não bloqueia automaticamente, mas alguém deve decidir como testá-lo antes da troca.
A aprovação deve responder cinco perguntas em linguagem simples:
- Qual medida cruzou o limite acordado e qual é a evidência?
- Que reparo a equipe tentou e como a medida respondeu?
- Qual fronteira será substituída, mantida ou retirada?
- Como provar paridade e ensaiar a reversão?
- Qual responsável aceita diferenças e risco restantes?
Se as respostas forem vagas, financie uma fase curta de evidências em vez da reescrita. Ela deve produzir inventário, avaliação de responsabilidade, modelo de incidente, conjunto comportamental e fronteira do sistema. Não deve produzir slides sobre modernidade.
A aprovação também inclui condições de parada. Se restarem diferenças em um fluxo de grande consequência, a conversão não conciliar ou a substituição não cumprir uma exigência de recuperação, a troca espera. Custo já gasto não torna seguro um sistema sem verificação.
Reavalie a decisão após toda mudança relevante
A decisão expira quando sistema, equipe ou consequência mudam. Recalcule após grande atualização, transferência de responsabilidade, aquisição, mudança de tráfego, nova obrigação ou incidente grave. Uma ficha esquecida por um ano vira mais um documento legado.
Mantenha as evidências perto do trabalho normal. Registros de implantação devem identificar mudanças reparadas. Revisões precisam separar falhas causadas por mudanças e guardar custos reais de trabalho e conciliação. Habilidade se prova por entregas. O inventário deve atualizar-se a partir de ambientes em execução, não de questionário anual.
Observe direção e limites. Quatro medidas dentro dos limites, mas piorando juntas, justificam preparação. Uma fora do limite e melhorando rapidamente pode justificar outro ciclo. Escreva a exceção, o responsável e a validade para uma tolerância temporária não virar política permanente.
Os casos mais difíceis têm sinais conflitantes. Um sistema pode ser estável e barato durante incidentes enquanto a responsabilidade desaba. Pode ter muitos mantenedores e depender de um ambiente público sem suporte. Não elimine o eixo incômodo por média. Decida se um controle confiável consegue movê-lo antes do prazo escondido.
A primeira reunião útil não é um workshop de reescrita. É uma revisão em que engenharia, operações, segurança, finanças e negócio trazem evidências de um número cada. Ao final, defina limites e financie a ação ligada a eles. Se os números apoiam reparos, repare sem pedir desculpas. Se mostram que toda mudança segura depende de conhecimento menor, software abandonado e custo inaceitável, pare de pagar pela ilusão de que outro patch devolverá o controle.
Perguntas frequentes
Quando uma empresa deve reescrever software legado?
Reescreva quando risco medido e exposição do negócio cruzarem limites definidos antes e a correção focada tiver falhado. Idade e tecnologia impopular sozinhas não justificam substituição.
Qual é uma boa taxa de falha para um sistema legado?
Não há uma taxa universal para todo processo. Defina um limite com seu volume de mudanças, tempo de recuperação e consequência e acompanhe a tendência por várias revisões.
Como medir quem consegue manter código legado com segurança?
Conte quem consegue explicar, alterar, testar, implantar e recuperar de forma independente uma mudança significativa. Acesso ao repositório, autoavaliação e trabalho dirigido pelo especialista original não bastam.
Um ambiente sem suporte sempre exige reescrita?
Não. Isolamento, controles estritos, patch virtual ou suporte estendido pago podem justificar reparos. A substituição fica urgente quando aceita entrada não confiável, bloqueia atualizações ou custa demais para conter.
Como estimar o custo de incidente antes de uma pane?
Defina um cenário específico e peça a finanças, operações, segurança e negócio que contestem as hipóteses. Inclua margem perdida, custo completo de pessoal, correção a clientes, custos contratuais, conciliação e eventos atrasados.
Poucas implantações provam que o software é estável?
Não. Um sistema pode parecer estável porque a equipe teme publicá-lo. Registre demanda adiada junto à taxa de falha para a paralisia não parecer confiabilidade.
Um monólito antigo deve virar microsserviços primeiro?
Em geral, não antes de capturar seu comportamento. Dividir código mal compreendido adiciona falhas de rede e versões de interface enquanto distribui a mesma incerteza.
É possível substituir só uma parte do sistema legado?
Sim, e a substituição seletiva costuma ser a opção mais sensata. Remova o componente que cria exposição ou falhas e recalcule as quatro medidas para a fronteira menor.
Como provar que uma reescrita corresponde ao sistema antigo?
Execute as duas versões nos mesmos casos parecidos com produção e compare resultados e transições. Toda normalização de horário, identificador ou ordem precisa de justificativa para manter diferenças reais visíveis.
Com que frequência a decisão deve ser revista?
Reveja após qualquer mudança relevante em dependências, responsabilidade, consequência, tráfego ou obrigações. Defina também uma data regular e um responsável por cada medida.