Ao longo da minha carreira como programador de computadores, em todas as empresas pelas quais passei, sempre atuei em equipes que estavam, ou mantendo software antigo e cheio de problemas, ou escrevendo software novo para substituir aqueles considerados antigos e problemáticos. Parece que esse comportamento faz parte da natureza de como os softwares são construídos, desde o setor público até as empresas que buscam lucro acima de qualquer coisa. É curioso que empresas paguem o preço de refazer um sistema em vez de ajustar os sistemas que já existem.
Esse padrão de constante substituição de sistemas pode parecer um problema exclusivo de equipes mal gerenciadas ou de projetos com requisitos mal definidos, mas, na realidade, ele é uma característica inerente ao desenvolvimento de software. Mesmo que um sistema tenha sido projetado com as melhores práticas disponíveis no momento, sua manutenção inevitavelmente se tornará mais complexa com o passar do tempo à medida que novas demandas surgem, tecnologias evoluem e o conhecimento sobre o código original se dissipa.
Não é à toa que Robert C. Martin escreveu, em seu livro “Código Limpo” (2009), sobre o que ele chamou de “O Grande Replanejamento”. Esse fenômeno é a etapa final de uma sequência de eventos que frequentemente ocorrem em ciclos. No livro, Robert C. Martin apresenta uma listagem de boas práticas, de um ponto de vista técnico, com o objetivo de minimizar qualquer um dos problemas que possam levar à decisão de reescrever o sistema, mantendo o código o mais limpo possível.
Quando um software acumula problemas, o custo para mantê-lo também aumenta. A performance da equipe diminui, e até mesmo as mudanças mais simples podem provocar efeitos colaterais cujas consequências são imprevisíveis, exigindo uma codificação cada vez mais remendada. Muitas vezes, na tentativa de melhorar o desempenho e frequência das entregas, mais pessoas são adicionadas à equipe. No entanto, essas novas pessoas não conhecem o sistema, e aqueles que conhecem estão ocupados demais para fazer uma passagem de conhecimento adequada. Além disso, uma equipe sob constante pressão continua adicionando mais confusão ao software. Chega o momento em que ninguém aguenta mais. Algumas pessoas conseguem permissão para criar um sistema do zero, e este é o Grande Replanejamento.
Enquanto o novo sistema é construído, a empresa ainda precisa manter o antigo. Também é necessário garantir que qualquer modificação feita no sistema antigo seja replicada no novo. Os usuários precisam ser instruídos, bases de dados precisam ser sincronizadas e seria legal que os sentimentos negativos da equipe responsável pelo sistema antigo fossem minimizados. Todo esse processo leva muito tempo. Quando tudo finalmente fica pronto, a equipe original do novo sistema não existe mais. Durante esse tempo, o novo sistema acumulou problemas, pois o custo para manter dois softwares simultaneamente é alto e a empresa precisava colocá-lo em produção o quanto antes. Mas quando um software acumula problemas… o custo para mantê-lo também aumenta… a performance da equipe diminui… e até mesmo as mudanças mais simples…

Sobre esses desafios, Frederick P. Brooks, no livro “The Mythical Man-Month” (1975), escreveu que o segundo sistema de uma equipe tende a ser superdimensionado, pois as pessoas tentam corrigir todas as falhas do primeiro sistema e acabam adicionando complexidade desnecessária. Aqui, é importante destacar os dois tipos de complexidade descritos por Brooks. A primeira é a complexidade essencial, inerente ao problema que o software está tentando resolver. Ela decorre da natureza do próprio domínio e não pode ser eliminada sem alterar o propósito do sistema. Por exemplo, ao desenvolver um sistema bancário, espera-se lidar com transações financeiras, segurança, conformidade com regulamentações e requisitos de auditoria. Esses aspectos são essenciais ao problema e não podem ser removidos para facilitar o desenvolvimento. Já a segunda é a complexidade acidental, que surge das ferramentas, linguagens, frameworks, metodologias e implementações utilizadas. Se construímos algo simples, como um site, mas escolhemos uma tecnologia excessivamente complexa (como um framework pesado/complexo para um problema pequeno), estamos adicionando complexidade desnecessária ao projeto.
Brooks também apresentou uma percepção mais profunda sobre a ideia de adicionar mais pessoas a um projeto para ter entregas mais rápidas. Na prática, ele demonstrou que fazer isso em um projeto atrasado pode atrasá-lo ainda mais devido ao aumento da complexidade na comunicação e à necessidade de treinamento.
Adicionar mais pessoas a um projeto atrasado só o atrasa ainda mais.
Em equipes pequenas, a comunicação é mais simples, pois há poucos canais de interação. À medida que a equipe cresce, a comunicação se torna um problema exponencial. Por exemplo, em uma equipe de duas pessoas, existe apenas um canal de comunicação, enquanto que em uma equipe de seis pessoas há 15 canais de comunicação. Não demora muito para que a equipe passe a ocupar grande parte do tempo com reuniões, mensagens e alinhamentos.
Voltando a falar sobre a construção de um novo sistema, isso não é necessariamente ruim. Startups, por exemplo, precisam validar ideias de negócio o mais rápido e com o menor custo possível. Depois que uma ideia é validada, fala-se em escalar o negócio, e a tecnologia desempenha um papel fundamental nesse processo. Posteriormente, com o produto bem estabelecido, pode fazer sentido refazer algumas partes do sistema de maneira estruturada.
O acúmulo de problemas em um software é algo natural, mesmo quando boas práticas de desenvolvimento são seguidas. Isso acontece porque o software não é um sistema estático. Ele está sempre sujeito a mudanças internas, como código, arquitetura e design, e externas, como requisitos de negócio, novas tecnologias e mudanças no mercado. Além desses fatores, é importante lembrar que nenhuma equipe de software é eterna. Programadores saem da empresa e novos entram, trazendo diferentes estilos de codificação e abordagens. Mesmo com boas práticas, a falta de contexto histórico pode levar a decisões que complicam a manutenção.
As tecnologias também envelhecem. Mesmo que o software seja bem projetado, tecnologias se tornam obsoletas. Frameworks deixam de ser suportados, bancos de dados exigem novas abordagens e o que era moderno há cinco anos pode ser uma barreira hoje. Vamos imaginar como era construir frontends há 15 anos (e não estou falando de COBOL ou Visual Basic). Simplesmente, o mercado não terá profissionais suficientes para lidar com tecnologias de 15 ou 30 anos atrás. A evolução tecnológica pode tornar a manutenção de um software tão custosa que reconstruí-lo acaba sendo a melhor opção.
No contexto das empresas, decisões técnicas nem sempre são as ideais, pois há pressão para entregar rápido. Não conseguimos, todos os dias, construir um software que seja o ápice da arte da programação de computadores. As gambiarras vão se acumulando e viram débitos técnicos. Mesmo com boas práticas, a necessidade de cumprir prazos pode forçar soluções temporárias que, no longo prazo, se tornam problemas permanentes.
No geral, em algum momento, um software precisará ser reescrito, seja do zero ou apenas em alguns de seus componentes. Embora o acúmulo de problemas seja inevitável, é possível retardá-lo com estratégias como refatoração contínua, aplicando pequenas melhorias, que são mais fáceis e seguras do que esperar o sistema colapsar. Outro ponto crucial é a existência de testes automatizados. Sem testes, os desenvolvedores evitam modificar o código por medo de quebrar algo. Uma arquitetura modular, ferramentas de monitoramento e observabilidade também são fundamentais, permitindo detectar erros pequenos antes que se tornem problemas difíceis de resolver.
Por tudo isso, muitas vezes, as empresas optam por reescrever sistemas inteiros. Como vimos, esse é um processo natural. No entanto, ele pode ser acelerado ou retardado dependendo da qualidade do software. Mas é algo que faz parte do ciclo de vida de um software, desde aqueles que duram poucas semanas até os que permanecem em funcionamento por décadas.