Frameworks de decisão

TL;DR

Você já sabe mudar um sistema legado sem quebrá-lo — as fases anteriores lhe deram a rede de segurança (notas 10-11), os seams (nota 12), o bisturi (notas 13-14) e o mapa de pré-requisitos (nota 15). Mas saber mudar com segurança não responde à pergunta que o dono do sistema realmente faz: este código merece ser mudado? A fase Magus abre com essa virada — de como intervir para se, onde e por quê intervir. Esta nota dá o vocabulário de decisão: os 7 R’s da modernização (Retain, Rehost, Replatform, Repurchase, Refactor, Retire, Relocate — Gartner→AWS) como cardápio de destinos possíveis para um componente, e o modelo TIME de Gartner (Tolerate, Invest, Migrate, Eliminate) como a lente de portfólio que decide quais componentes recebem qual verbo, cruzando valor de negócio × qualidade técnica. No centro está o debate mais caro da carreira de um restaurador: rewrite total vs. incremento — e por que Spolsky chamou reescrever do zero de “o pior erro estratégico que uma empresa de software pode cometer”, com o contraponto de quando o rewrite de fato se justifica. A tese do galho reaparece aqui em sua forma mais afiada: você não decide o destino do código, decide o destino da teoria que ele carrega (teoria de Naur).

Seis meses depois de assumir a manutenção de uma plataforma de logística, um consultor sênior é chamado para uma reunião que ele sabia que viria. O diretor de tecnologia coloca a pergunta na mesa sem rodeios: “Esse sistema tem quinze anos. Metade do time que o escreveu já foi embora. A gente reescreve tudo do zero, contrata um time novo, faz do jeito certo — ou continua remendando?” Todos na sala já têm uma resposta emocional. Os desenvolvedores mais novos querem o rewrite: código limpo, stack moderna, nada de gambiarra. O gerente financeiro quer remendar: rewrite é caro e arriscado. O diretor quer que alguém decida com autoridade, porque a decisão errada custa um ano de trabalho e, possivelmente, o emprego de quem a defendeu.

O erro que quase todo mundo comete nessa sala é tratar isso como uma pergunta binária e monolítica — reescrever tudo ou manter tudo — quando ela nunca é nem binária nem monolítica. Um sistema legado não é um bloco: é um portfólio de componentes com valores e qualidades muito diferentes. O módulo de faturamento pode ser um horror técnico que sustenta 80% da receita; o gerador de relatórios pode ser código impecável que ninguém usa há dois anos. Aplicar o mesmo verbo aos dois é garantir o desperdício: ou você joga fora algo valioso, ou investe pesado em algo morto. O trabalho do Magus não é escolher um destino para o sistema — é atribuir o destino certo a cada parte dele. E para isso é preciso um vocabulário melhor do que “reescrever” e “remendar”.

O cardápio de destinos: os 7 R’s

Antes de decidir o quê fazer com um componente, você precisa saber quais opções existem. A indústria convergiu, ao longo de quinze anos, para um cardápio de sete verbos — os 7 R’s. A história da lista importa porque explica seu viés: Gartner publicou os 5 R’s originais em 2010 (Richard Watson), num contexto de migração de aplicações para a nuvem; a AWS os reduziu e reorganizou em 6 R’s em 2016 (Stephen Orban), acrescentando depois o sétimo. Ou seja, o vocabulário nasceu falando de para onde mover um sistema — mas cada verbo carrega, embutida, uma decisão sobre o quanto mexer na teoria do sistema, e é assim que o restaurador os lê.

Ordenados do menos ao mais invasivo:

RO que éO que acontece com a teoria (Naur)Custo/risco
Retain (manter)Deixar como está, deliberadamente. Não é inércia — é uma decisão de não investir agora.Preservada intacta, mas não recuperada — continua só no código.Mínimo (mas o débito segue rendendo juros)
Rehost (lift-and-shift)Mover para outra infra sem tocar no código. Trocar o corpo, não o órgão.Intacta — nada muda no comportamento.Baixo
Replatform (lift-and-reshape)Ajustes cirúrgicos para caber numa plataforma nova (trocar o banco, o runtime), sem rearquitetar.Quase intacta — mexe na borda, não no miolo.Baixo-médio
Repurchase (drop-and-shop)Substituir por um produto de prateleira/SaaS. Aposentar o seu código, comprar a função.Descartada — você abre mão da teoria própria e adota a de um fornecedor.Médio (risco de lock-in e de o produto não caber)
Refactor / Re-architect (restaurar)Reescrever internamente preservando o comportamento externo — o coração deste galho.Recuperada e reencarnada — a teoria é reconstruída e passa a viver de novo.Médio-alto (mas incremental e reversível)
Retire (aposentar)Desligar. O componente não serve mais a ninguém.Extinta conscientemente — você confirma que a teoria não tem mais valor.Baixo (se você tiver certeza de que está morto — ver nota 27)
Relocate (mover em bloco)Transferir VMs/containers inteiros para outro hipervisor, sem mexer no SO nem no app.Intacta — variação de infraestrutura do Rehost.Baixo

Repare que os sete verbos se colapsam nos quatro verbos do consultor que abrem esta nota: manter (Retain, Rehost, Relocate — mudanças que não tocam a teoria), restaurar (Replatform, Refactor — recuperar e reencarnar a teoria), substituir (Repurchase — trocar a teoria própria pela de um terceiro) e aposentar (Retire — extinguir a teoria). Os 7 R’s são o cardápio fino; os 4 verbos são como você fala disso com o diretor na reunião.

A lente de portfólio: o modelo TIME

Os 7 R’s dizem o que você pode fazer com um componente. Eles não dizem qual componente merece qual verbo — e é aí que quase toda modernização se perde, gastando o orçamento de refatoração no módulo errado. O framework que resolve isso é o modelo TIME de Gartner, a ferramenta canônica de application portfolio management. Sua genialidade é reduzir a decisão a duas perguntas, e só duas, sobre cada componente:

  1. Quanto valor de negócio ele entrega? (Alto/baixo — quão crítico é para a operação e a estratégia.)
  2. Qual a qualidade técnica dele? (Alta/baixa — quão saudável, manutenível e alinhado à arquitetura desejada.)

Cruzar esses dois eixos produz quatro quadrantes, e cada quadrante prescreve um verbo:


quadrantChart
    title TIME — valor de negocio x qualidade tecnica
    x-axis "Qualidade tecnica BAIXA" --> "Qualidade tecnica ALTA"
    y-axis "Valor de negocio BAIXO" --> "Valor de negocio ALTO"
    quadrant-1 "INVEST: evoluir, e a joia"
    quadrant-2 "MIGRATE: restaurar/substituir ja"
    quadrant-3 "ELIMINATE: aposentar"
    quadrant-4 "TOLERATE: manter, nao invista"
  • Invest (alto valor, alta qualidade): a joia da coroa. Evolua, acrescente features, dê recursos. Nada de arqueologia aqui — é o sistema saudável e importante. Em R’s: Refactor pontual, novas funcionalidades.
  • Tolerate (baixo valor, alta qualidade): funciona bem, mas não é estratégico. Não gaste um centavo além do necessário para mantê-lo vivo. Em R’s: Retain. A armadilha aqui é o engenheiro que quer “melhorar” código que já é bom e irrelevante — puro desperdício.
  • Migrate (alto valor, baixa qualidade): este é o território do restaurador. Crítico para o negócio e tecnicamente podre — o módulo de faturamento da história de abertura. É aqui que a rede de segurança, os seams e o Strangler Fig (nota 18) ganham a vida. Em R’s: Refactor, Replatform ou Repurchase, conforme o caso. Todo o resto deste galho existe para servir bem a este quadrante.
  • Eliminate (baixo valor, baixa qualidade): morto e ruim. Aposente. Em R’s: Retire. O único cuidado é confirmar que “baixo valor” é verdade — código que parece morto às vezes carrega uma obrigação legal ou um cliente esquecido (o if da nota 16, a compliance da nota 27).

Por que só dois eixos?

A tentação é enriquecer o modelo com dez critérios (custo de manutenção, risco de segurança, satisfação do time, idade da stack…). Gartner resiste a isso de propósito. Um framework de decisão que exige medir dez variáveis não é usado — vira planilha morta. Dois eixos cabem na cabeça, cabem num quadro branco na frente do diretor, e forçam a conversa difícil: “você concorda que esse módulo é de alto valor e baixa qualidade?” O poder do TIME é ser rápido o bastante para ser aplicado de verdade a um portfólio inteiro numa tarde. Os outros critérios entram depois, ao escolher o R dentro do quadrante Migrate.

O fluxo de decisão completo, então, tem duas etapas: primeiro o TIME classifica cada componente num quadrante (a decisão estratégica, de portfólio); depois, dentro do quadrante Migrate — o único que demanda intervenção pesada — você escolhe o R específico (a decisão tática, de execução).


graph TD
    A[Componente legado] --> B{TIME: valor x qualidade}
    B -->|alto valor, alta qual.| C[INVEST: evoluir]
    B -->|baixo valor, alta qual.| D[TOLERATE: Retain]
    B -->|baixo valor, baixa qual.| E[ELIMINATE: Retire]
    B -->|alto valor, baixa qual.| F{MIGRATE: qual R?}
    F -->|existe SaaS que cabe| G[Repurchase: substituir]
    F -->|teoria vale a pena recuperar| H[Refactor: restaurar incremental]
    F -->|so a plataforma e o problema| I[Replatform]
    style F fill:#F5A623
    style H fill:#4A90D9

A decisão mais cara: rewrite total vs. incremento

Dentro do quadrante Migrate mora a decisão que define carreiras: quando você conclui que um componente de alto valor está tecnicamente podre, restaura por incrementos (Refactor) ou reescreve do zero (Rebuild)? A pressão emocional empurra quase sempre para o rewrite — e é justamente aí que mora a armadilha mais bem documentada da engenharia de software.

Em 2000, Joel Spolsky escreveu o ensaio Things You Should Never Do, Part I, analisando a decisão da Netscape de reescrever seu navegador do zero. O veredito dele é brutal e famoso: reescrever do zero é “o pior erro estratégico que uma empresa de software pode cometer”. A Netscape passou quase três anos reescrevendo enquanto a Microsoft comia seu mercado com o Internet Explorer; quando o código novo ficou pronto, a guerra dos navegadores já estava perdida. O argumento central de Spolsky é uma verdade incômoda sobre código legado:

O que aquele código feio realmente é

Aquele if esquisito, aquela função de 300 linhas cheia de casos especiais, aquele trecho que “ninguém entende” — cada um deles é, com frequência, um bug consertado. Uma correção que custou horas de investigação, que responde a um caso real de produção que aconteceu uma vez, às três da manhã, e nunca mais. Reescrever do zero joga fora todo esse conhecimento acumulado. O código novo, “limpo”, vai reintroduzir silenciosamente cada um desses bugs — e você vai reconsertá-los, um a um, ao longo dos anos, redescobrindo do jeito difícil por que aquele código feio era feio.

Isso é a tese de Naur dita em outra língua: o valor real do sistema não é o código, é a teoria — o conhecimento sobre por que cada decisão foi tomada. Um rewrite do zero descarta a teoria e mantém só a especificação aparente, que é sempre incompleta. Por isso o default deste galho inteiro é restaurar por incrementos: o Refactor preserva a teoria justamente porque você a recupera peça por peça, mantendo o comportamento (a rede de caracterização garante isso) enquanto troca a estrutura por baixo.

Mas o dogma “nunca reescreva” é tão perigoso quanto o impulso de reescrever tudo. Há casos reais em que o rewrite é a decisão correta — e o restaurador maduro sabe reconhecê-los:

Quando o rewrite de fato se justifica

O que caracteriza: a teoria embutida no código já se perdeu (ninguém a detém, e o custo de recuperá-la por engenharia reversa supera o de reconstruí-la); ou a plataforma-base está morta e sem caminho de migração incremental (linguagem/runtime sem suporte, dependência descontinuada sem equivalente); ou o modelo de domínio mudou tão radicalmente que o sistema atual codifica uma realidade que não existe mais. Por que é raro: todas as três condições exigem que o incremento seja comprovadamente inviável, não apenas desconfortável. “O código é feio” nunca é uma delas. Como decidir com honestidade: faça um spike time-boxed (nota 25) tentando o caminho incremental primeiro. Se você não consegue nem estabelecer um seam para começar a restaurar, isso é evidência real a favor do rewrite — não um palpite.

Assista: Joel Spolsky, Things You Should Never Do: Rewriting the Code from Scratch

Canal: ratherabstract | Duração: ~8min | Idioma: EN

É a leitura em voz alta do próprio ensaio de 2000, mas o formato falado acrescenta algo que o texto corrido não deixa tão nítido: Spolsky separa as três razões pelas quais um programador acha que “o código é um lixo” — problema arquitetural (resolve-se refatorando, sem jogar fora), ineficiência (otimiza-se a parte lenta, não o todo) e feiúra (resolve-se com um macro de 5 minutos) — e mostra, com os casos Borland/Quattro Pro e o projeto “Pyramid” da própria Microsoft para reescrever o Word, que o erro da Netscape não foi um acidente isolado. Trecho de destaque [4:11]: “When you throw away code and start from scratch, you are throwing away all that knowledge, all those collected bug fixes, years of programming work.”

🎬 Assistir no YouTube

E mesmo quando o rewrite se justifica, ele quase nunca é big-bang. A forma segura de reescrever é o Strangler Fig (nota 18): o sistema novo cresce em volta do velho, assumindo uma função de cada vez, com o velho ainda no ar até a última função migrar. Isso transforma o rewrite — uma aposta de tudo-ou-nada de três anos — numa sequência de migrações pequenas e reversíveis. O “nunca reescreva do zero” de Spolsky é, na prática, “nunca reescreva de uma vez, no escuro, com o velho desligado”.

Fundamento teórico: por que decidir é gestão de portfólio sob incerteza

Os frameworks acima parecem receitas práticas, mas repousam sobre uma base teórica que vale nomear — porque entendê-la é o que separa aplicar o TIME mecanicamente de decidir com julgamento.

1. É teoria de portfólio, não de engenharia. O modelo TIME é filho direto da portfolio theory financeira: você não avalia cada ativo isoladamente, avalia como cada um contribui para o valor e o risco do conjunto. Um sistema legado é uma carteira de ativos técnicos de qualidade heterogênea; a decisão racional não é maximizar a qualidade de cada peça, é alocar um orçamento escasso de modernização onde ele rende mais valor de negócio por real investido — exatamente o quadrante Migrate. Investir em Tolerate ou refatorar um Eliminate é o equivalente técnico de comprar um ativo de retorno negativo.

2. A falácia do custo afundado é o inimigo. A pergunta certa nunca é “quanto já gastamos neste sistema?” (custo afundado, irrecuperável, irrelevante para a decisão) mas “qual o valor futuro de cada verbo daqui para frente?“. O apego emocional a um sistema — “investimos dez anos nisso” — é precisamente o viés que o TIME neutraliza ao perguntar apenas por valor futuro e qualidade atual. O mesmo viés, invertido, é o que seduz o time júnior a reescrever: a falácia da tela em branco, a crença de que começar do zero é mais barato do que entender o que existe — quando quase sempre é o contrário (Spolsky).

3. Lehman e a lei da evolução contínua. Meir Lehman formulou, nos anos 1970-80, suas leis da evolução de software. Duas importam aqui. A lei da mudança contínua: um sistema em uso precisa evoluir continuamente ou se torna progressivamente menos útil — o que justifica por que “Retain” é sempre uma decisão temporária, um adiamento com juros, nunca um estado final. E a lei da complexidade crescente: à medida que evolui, um sistema fica mais complexo, a menos que se trabalhe ativamente para reduzir essa complexidade — o que é a definição formal do trabalho de restauração (Refactor) e a razão de o débito técnico ser um custo que cresce sozinho se ignorado.

4. O valor de opção da reversibilidade. A superioridade do incremento sobre o rewrite big-bang não é só psicológica — é teoria de opções reais. Uma sequência de mudanças pequenas e reversíveis (Strangler Fig, Mikado) preserva, a cada passo, a opção de parar, corrigir de rota ou voltar atrás com custo baixo. Um rewrite big-bang é uma aposta única que destrói essa opção: você só descobre se acertou depois de anos, quando voltar atrás já custa tudo. Sob incerteza — e restauração de legado é o reino da incerteza — a estratégia que preserva opcionalidade vence a que aposta tudo de uma vez, mesmo que ambas tenham o mesmo destino final.

Frameworks de decisão em uma frase: decidir o destino de um sistema legado é gestão de portfólio sob incerteza — atribuir a cada componente o menor verbo que recupera seu valor futuro, preservando a teoria onde ela ainda vale e a opção de voltar atrás sempre.

Casos práticos

Frameworks só provam seu valor quando aplicados a um sistema real. Voltemos à plataforma de logística da reunião de abertura e passemos dois de seus componentes pela máquina de decisão inteira — TIME primeiro, R depois.

Cenário 1: o módulo de faturamento — alto valor, baixa qualidade → Migrate → Refactor

O faturamento é 900 linhas de PHP sem testes, com regras de imposto embutidas em ifs aninhados e uma função calcularTotal() de 200 linhas que ninguém ousa tocar. É feio, frágil e assustador. Mas a forense (nota 09) mostra que ele processa toda a receita da empresa e muda toda semana (mudanças de alíquota, novos tipos de contrato). No TIME: valor de negócio altíssimo, qualidade técnica baixa → quadrante Migrate. Esse é o único quadrante que justifica intervenção pesada, então a decisão de portfólio está tomada: sim, invista aqui.

Agora o R. As opções realistas são Repurchase (existe SaaS de faturamento fiscal que caberia?) ou Refactor. Uma investigação rápida mostra que as regras de contrato são específicas demais para um produto de prateleira — a teoria embutida ali tem valor próprio, não é commodity. Logo: Refactor incremental. Nada de rewrite: a caracterização (nota 10) trava o comportamento atual, um seam isola calcularTotal(), e a restauração acontece semana a semana, reversível a cada passo, com o velho no ar. A decisão inteira — de “reescrevemos tudo?” a “refatore o faturamento por incrementos, mantenha o resto” — nasceu de duas perguntas do TIME e uma do cardápio de R’s.

Cenário 2: o gerador de relatórios — parece Eliminate, mas Retire quase custa caro

O gerador de relatórios é o oposto: código relativamente limpo, mas os logs de acesso mostram que ninguém abre aqueles relatórios há dezoito meses. No TIME: baixo valor, qualidade média → parece Eliminate, e a decisão óbvia é Retire (desligar). O time júnior já ia deletar o módulo na sprint seguinte.

Antes de apertar o botão, a verificação de compliance (nota 27) revela o detalhe que muda tudo: um daqueles relatórios — o de movimentação de carga controlada — é exigido por uma norma regulatória e precisa ser gerável sob demanda numa auditoria, mesmo que ninguém o abra no dia a dia. “Ninguém usa” era verdade sobre o uso rotineiro, não sobre a obrigação legal. O verbo correto não era Retire, era Retain (manter só aquele relatório vivo, aposentar o resto) — um lembrete de que “baixo valor de negócio” no eixo do TIME precisa incluir valor de conformidade, não só de operação. Retire, sendo irreversível, é o único R que erra de forma definitiva.

Armadilhas comuns

Aplicar um único verbo ao sistema inteiro

O que acontece: o time decide “vamos reescrever a plataforma” ou “vamos só manter” como bloco monolítico, e o orçamento vai inteiro para o módulo errado — reescrevendo o relatório morto e mantendo o faturamento podre. Por quê: confortável politicamente (uma decisão só) e emocionalmente (uma narrativa só), mas ignora que um sistema é um portfólio heterogêneo. Como evitar: rode o TIME componente a componente antes de escolher qualquer R. A decisão é sempre plural.

Confundir "código feio" com "baixa qualidade técnica" no eixo do TIME

O que acontece: um módulo funcional, estável e crítico é classificado como “baixa qualidade” só porque é feio de ler, e entra na fila de rewrite. Por quê: feiúra é visível e irritante; qualidade real (taxa de defeitos, custo de mudança, acoplamento) exige medição — a forense da nota 09. Como evitar: meça qualidade com hotspots e métricas de mudança, não com a reação estética de quem abre o arquivo. Código feio que muda pouco e falha pouco é, tecnicamente, de qualidade alta.

Tratar Retire e Retain como decisões "de graça"

O que acontece: aposenta-se um módulo que carregava uma obrigação legal, ou mantém-se indefinidamente um componente sobre uma dependência que vira uma CVE crítica. Por quê: ambos parecem “não fazer nada”, mas Retire é irreversível e Retain acumula risco de segurança e EOL silenciosamente. Como evitar: Retire passa pela verificação de compliance (nota 27); Retain tem prazo de validade e um gatilho de reavaliação (nota 22).

Como explicar em inglês

We don’t decide the fate of the system — we decide the fate of each component. I run every module through Gartner’s TIME model first: business value against technical quality. Only the high-value, low-quality quadrant — Migrate — earns a heavy intervention, and there I default to incremental refactoring over a rewrite. A from-scratch rewrite throws away years of embedded bug fixes, so I only take it when the incremental path is provably blocked, and even then I do it as a strangler, never big-bang.

PTEN
decidir o destino do sistemadecide the fate of the system
valor de negócio × qualidade técnicabusiness value vs. technical quality
manter / restaurar / substituir / aposentarretain / refactor / repurchase / retire
reescrever do zerorewrite from scratch
gestão de portfólio de aplicaçõesapplication portfolio management
custo afundadosunk cost
aposta de tudo-ou-nadaall-or-nothing bet

O que vem a seguir

Você agora tem o vocabulário para decidir — mas a decisão mais comum e mais valiosa (o quadrante Migrate) é também a mais arriscada de executar: como você restaura um componente crítico sem desligar o sistema que depende dele? As próximas notas são a caixa de ferramentas da execução dessa decisão.

  • nota 18 — a técnica que transforma “restaurar/reescrever” numa sequência de passos pequenos, entregáveis e reversíveis, com o velho no ar até o fim.
  • nota 19 — como fazer o novo e o velho coexistirem em segurança durante a migração.
  • nota 20 — o problema mais difícil por baixo de toda decisão de Migrate: mover os dados sem downtime e sem perder história.
  • nota 23 — porque nenhum desses frameworks vale nada se você não conseguir vender a decisão para quem assina o orçamento.

Fontes