Sistemas legados criam um tipo particular de impaciência.

O time sabe que a arquitetura é difícil. As entregas são lentas. As dependências são antigas. Os testes são frágeis. A infraestrutura é cara. Cada mudança parece afetar algo inesperado.

Em algum momento, alguém propõe a solução emocionalmente satisfatória:

Vamos reescrever tudo.

Às vezes, essa é a decisão certa.

Muitas vezes, é uma reação à frustração acumulada, e não uma estratégia.

Modernizar não exige preservar tudo o que existe. Exige entender quais restrições geram o maior custo para o negócio e a engenharia, e então mudar o sistema de modo a aliviar essas restrições sem criar um risco de transição inaceitável.

Para muitos sistemas críticos, isso leva à substituição incremental, em vez de uma virada única, no estilo big bang.

O viés pela reescrita nasce da clareza sobre a dor do sistema antigo

Os times conhecem as fraquezas do sistema atual porque convivem com elas todos os dias.

Não conhecem as fraquezas do substituto porque ele ainda não existe.

Essa assimetria cria o viés pela reescrita.

O novo sistema parece limpo porque seus requisitos ocultos, casos operacionais de borda e histórico de integrações ainda não foram redescobertos.

Grandes sistemas existentes frequentemente contêm comportamentos que ninguém documentou, mas dos quais alguém depende. Uma reescrita revela essas dependências tarde, porque o comportamento em produção se tornou parte da especificação.

A metáfora Strangler Fig, de Martin Fowler, surgiu dessa realidade. Em vez de substituir um sistema crítico em uma única virada, novas capacidades podem crescer ao redor do sistema antigo enquanto as funcionalidades migram gradualmente para a nova estrutura.

O valor não está na metáfora botânica. Está no modelo de risco.

Comece pelos resultados, não pela tecnologia

“Migrar para microsserviços” não é um resultado de modernização.

“Migrar para Kubernetes” não é um resultado de modernização.

“Reescrever em uma linguagem mais nova” não é um resultado de modernização.

Essas podem ser escolhas de implementação. A modernização deve começar pelas restrições que a organização precisa mudar.

Exemplos:

  • as versões levam seis semanas para sair porque todos os componentes precisam ser implantados juntos;
  • um único banco de dados impede escalar componentes de forma independente;
  • dependências sem suporte criam exposição de segurança;
  • a implantação manual torna a reversão pouco confiável;
  • uma integração bloqueia mudanças de produto;
  • incidentes em produção não podem ser diagnosticados porque a observabilidade é insuficiente;
  • o custo de infraestrutura é dominado por cargas com recursos superdimensionados;
  • um fluxo crítico não consegue evoluir porque as regras de negócio estão espalhadas entre a interface e o banco de dados.

O programa de modernização deve definir capacidades-alvo que respondam a essas restrições.

Caso contrário, a organização pode substituir a tecnologia e preservar o problema.

Crie pontos de separação antes de substituir comportamentos

A modernização incremental exige pontos em que o comportamento antigo e o novo possam coexistir.

Esses pontos de separação podem ser:

  • gateways de API;
  • fachadas;
  • fluxos de eventos;
  • camadas de abstração;
  • visões de banco de dados;
  • camadas anticorrupção;
  • regras de roteamento;
  • adaptadores.

O ponto de separação cria uma fronteira controlável.

Consumidor
   ↓
Fronteira estável
  ↙       ↘
Legado    Nova capacidade

O tráfego ou o comportamento pode migrar gradualmente, em vez de exigir uma única virada.

O AWS Prescriptive Guidance descreve o padrão Strangler Fig como uma forma de migrar funcionalidades incrementalmente, reduzindo o risco de transformação e a interrupção do negócio. Também aponta uma concessão importante: o próprio mecanismo de coexistência pode se tornar complexo ou introduzir gargalos.

A modernização incremental reduz uma categoria de risco enquanto cria complexidade temporária.

Essa concessão deve ser explícita.

Testes são infraestrutura de modernização

Times frequentemente tratam os testes como algo a melhorar depois que a arquitetura estiver mais limpa.

Isso inverte a dependência.

Se a organização não consegue determinar se os comportamentos antigo e novo são equivalentes onde precisam ser, a migração se torna perigosa.

Testes criam confiança para introduzir pontos de separação, redirecionar tráfego, mudar dependências e remover caminhos antigos.

A cobertura mais útil não é necessariamente um percentual alto de testes unitários. A modernização frequentemente precisa de:

  • testes de caracterização do comportamento existente;
  • testes de contrato nas integrações;
  • cobertura de ponta a ponta para fluxos críticos;
  • validação da migração de dados;
  • testes básicos de funcionamento em produção;
  • sinais de implantações canário;
  • reconciliação entre os resultados antigos e novos.

Os testes tornam a substituição incremental observável.

Sem eles, cada etapa se torna um pequeno big bang.

A observabilidade permite mudanças progressivas

A modernização incremental cria um período em que múltiplas implementações coexistem.

A organização precisa saber qual caminho processou uma requisição, como cada caminho se comportou, onde ocorreram erros e se os resultados diferem.

Isso exige observabilidade projetada para a migração.

Sinais úteis incluem:

  • percentual de tráfego por implementação;
  • taxa de erros por rota;
  • latência por rota;
  • diferenças na reconciliação de dados;
  • frequência de uso do caminho alternativo;
  • falhas de dependências;
  • custo de recursos;
  • métricas de resultados percebidos pelo usuário.

A observabilidade não é apenas uma preocupação operacional. É como o programa comprova se o estado-alvo está realmente melhorando o sistema.

Os dados costumam ser a fronteira mais difícil

O código da aplicação frequentemente pode ser roteado de forma incremental. Os dados são menos flexíveis.

Sistemas legados podem compartilhar tabelas entre domínios, codificar regras de negócio em procedimentos armazenados, depender de identificadores não documentados ou permitir que múltiplos componentes alterem os mesmos registros.

Modernizar comportamentos sem esclarecer a responsabilidade pelos dados pode criar uma arquitetura distribuída em torno de um modelo de dados legado compartilhado. A organização ganha complexidade de implantação sem ganhar independência.

As perguntas sobre modernização de dados incluem:

  • Qual sistema é a fonte de autoridade durante a coexistência?
  • Tanto o antigo quanto o novo podem escrever?
  • Como os conflitos são resolvidos?
  • Quais dados históricos precisam migrar?
  • Como a migração é verificada?
  • A migração pode ser reexecutada?
  • O que acontece durante uma reversão?
  • Quais dados podem permanecer onde estão?

Um bom plano de modernização costuma tratar a migração de dados como um problema próprio de produto e operação.

Migrar para a nuvem não é automaticamente modernizar

Mover uma carga legada de um data center para a nuvem pode melhorar a gestão da infraestrutura sem mudar as restrições da aplicação.

Da mesma forma, colocar uma aplicação em contêineres pode melhorar a consistência da implantação sem torná-la modular.

Essas mudanças ainda podem ter valor.

O erro é confundir mudança de plataforma com melhoria de capacidade.

Um programa de modernização deve declarar o que se espera melhorar com cada mudança:

MudançaBenefício possívelO que talvez não resolva
Rehospedar na nuvemSaída do data center, flexibilidade de provisionamentoAcoplamento da aplicação
ConteinerizarConsistência de implantaçãoFronteiras de domínio
Atualizar o ambiente de execuçãoSuporte e segurançaAcoplamento entre versões
Modularizar o códigoIsolamento de mudançasIndependência de implantação
Extrair um serviçoResponsabilidade, escala e isolamento de entregasModelo de domínio inadequado
Substituir o banco de dadosGanho de desempenho ou operaçãoResponsabilidade pouco clara pelos dados

A tecnologia é útil quando muda a restrição que importa.

Sistemas paralelos têm um custo

A modernização incremental não é gratuita.

Durante um período, a organização pode operar:

  • dois caminhos de código;
  • infraestrutura duplicada;
  • processos de sincronização;
  • camadas de compatibilidade;
  • monitoramento adicional;
  • ferramentas de migração;
  • estruturas temporárias de times.

A arquitetura de transição pode se tornar permanente se o programa perder ritmo.

Um padrão de substituição gradual sem eliminação se torna acumulação.

Todo plano de modernização incremental precisa, portanto, de condições de saída:

  • Qual capacidade antiga será removida?
  • Qual dependência desaparece?
  • Qual fonte de dados deixa de ser a referência oficial?
  • Qual adaptador temporário pode ser excluído?
  • O que comprova que o caminho antigo não é mais necessário?

A modernização deve reduzir a complexidade estrutural ao longo do tempo, e não apenas adicionar tecnologia nova ao lado da antiga.

Quando uma reescrita se justifica

“Nunca reescrever” é tão simplista quanto “reescrever tudo”.

Uma reescrita pode ser racional quando:

  • o sistema é pequeno o suficiente para ser substituído com risco delimitado;
  • a arquitetura existente impede pontos de separação incrementais relevantes;
  • a plataforma antiga perdeu suporte e cria exposição urgente;
  • o próprio produto mudou tanto que preservar o comportamento legado tem pouco valor;
  • os dados podem ser migrados com segurança;
  • os requisitos operacionais são bem compreendidos;
  • a organização consegue sustentar mudanças no negócio enquanto a substituição acontece.

Mesmo assim, o time deve ser preciso sobre a virada, a reversão, a migração de dados, a validação e a continuidade do negócio.

A decisão não é ideológica. É econômica e operacional.

A modernização deve mudar o custo das mudanças futuras

A finalidade da modernização não é fazer um diagrama parecer contemporâneo.

É melhorar a capacidade da organização de evoluir.

Isso pode significar entregas mais rápidas, implantações mais seguras, responsabilidades mais claras, menor risco de incidentes, segurança melhor, menor custo de dependências ou escala mais previsível.

Esses resultados se conectam diretamente a Dívida técnica é uma restrição de negócio. A dívida importa quando muda a viabilidade ou a economia de decisões futuras.

Um roadmap útil de modernização prioriza mudanças que facilitam as próximas mudanças.

Evolua o sistema em etapas visíveis

Uma sequência sólida de modernização incremental costuma ser:

Entender as restrições
  ↓
Definir as capacidades-alvo
  ↓
Criar um ponto de separação
  ↓
Mover um comportamento delimitado
  ↓
Validar em produção
  ↓
Migrar dados ou responsabilidades conforme necessário
  ↓
Remover o caminho antigo
  ↓
Repetir

A sequência produz evidências à medida que avança.

Essa é a vantagem em relação a uma reescrita de uma só vez. A organização não precisa esperar até o final para descobrir se a estratégia funciona.

Modernizar continua sendo difícil. Sistemas existentes carregam histórico, dependências e estrutura organizacional. Abordagens incrementais não eliminam essa complexidade.

Elas tornam a complexidade visível em decisões menores.

Um programa de modernização tem sucesso quando cada etapa remove uma restrição relevante e deixa a organização mais capaz de realizar a próxima mudança.

O objetivo não é escapar do sistema legado em um único evento dramático.

É evoluir o sistema até que as restrições que justificaram a modernização deixem de dominar o negócio.

Referências

  1. Martin Fowler. Strangler Fig. 2024. https://martinfowler.com/bliki/StranglerFigApplication.html
  2. Martin Fowler. Original Strangler Fig Application. 2004. https://martinfowler.com/bliki/OriginalStranglerFigApplication.html
  3. AWS. Strangler fig pattern. AWS Prescriptive Guidance. https://docs.aws.amazon.com/prescriptive-guidance/latest/cloud-design-patterns/strangler-fig.html
  4. AWS. Branch by abstraction pattern. AWS Prescriptive Guidance. https://docs.aws.amazon.com/prescriptive-guidance/latest/modernization-decomposing-monoliths/branch-by-abstraction.html
← Todos os Insights