A entropia do software: o legado não nasceu assim

Um dos maiores problemas enfrentados por pesquisadores que estudam a modernização de sistemas COBOL é a falta de material para experimentação.

Os grandes sistemas que rodam nos mainframe pertencem a empresas que não podem simplesmente publicar seus códigos-fonte na internet. Além de propriedade intelectual, esses programas podem revelar regras comerciais, estruturas de dados e vulnerabilidades operacionais.

O resultado é uma contradição: queremos avaliar ferramentas de inteligência artificial capazes de compreender ou converter sistemas COBOL, mas frequentemente fazemos isso usando programas didáticos, pequenos e organizados — muito diferentes daqueles que essas ferramentas vão encontrar no mundo real.

Foi esse problema que motivou o projeto Spec2COBOLRot, que será apresentado por três pesquisadores e aceito para apresentação no 2nd International Workshop on AI for Software Modernization que acontecerá em outubro de 2026, em Munique.

A proposta é usar inteligência artificial para gerar um programa COBOL correto e, depois, fazer esse programa envelhecer artificialmente.

Como fabricar um programa legado

O processo começa com uma especificação em linguagem natural. Ela descreve o objetivo do programa, suas entradas, suas saídas e as regras de negócio que precisam ser executadas.

A partir dessa especificação, um agente de inteligência artificial gera um programa COBOL relativamente limpo, acompanhado dos arquivos necessários para sua execução. O programa é compilado e executado com GnuCOBOL. Se houver erros, os diagnósticos retornam ao agente, que tenta corrigi-los.

Somente depois que o programa compila e executa começa a segunda fase: a degradação.

Nessa etapa, outro agente modifica progressivamente o fonte para que sua estrutura se aproxime daquela encontrada em programas COBOL mantidos durante muitos anos. Para orientar o processo, os pesquisadores criaram uma biblioteca com 26 características extraídas de programas reais: oito padrões comuns de codificação na linguagem, 15 “vícios” frequentemente introduzidos no código ao longo do tempo – que os pesquisadores chamaram de code smells – e três construções particulares do COBOL que sempre exigem decisões importantes durante projetos de modernização.

Entre os elementos introduzidos estão:

  • Processamento sequencial controlado por fim de arquivo;
  • Pesquisas em tabelas indexadas;
  • Geração de arquivos de registros rejeitados;
  • Fluxos não estruturados fazendo uso de ‘GO TO’;
  • Excesso de variáveis na WORKING-STORAGE;
  • Mistura de entrada e saída com regras de negócio;
  • Representações diferentes sobre a mesma área de memória (REDEFINES);
  • Campos decimais compactados

Boa parte dessa lista não é código ruim; é arquitetura de solução de um sistema construído décadas atrás. Processar um arquivo até o fim, por exemplo, é uma forma tradicional e perfeitamente legítima de implementar programas batch que precisam processar milhões de registros em uma janela curta de produção.  O mesmo vale para pesquisas em tabelas indexadas e REDEFINES.

A cada rodada, o projeto mede quantidade de linhas, número de parágrafos, complexidade ciclomática, ocorrência de `GO TO`, proporção de variáveis utilizadas e outros indicadores. A degradação continua até que o programa se aproxime das faixas observadas no conjunto de sistemas reais.

Os resultados mostram que é possível produzir programas compiláveis e estruturalmente mais parecidos com COBOL de produção. Mas um programa com aparência de legado é realmente um sistema legado?

É relativamente fácil produzir código complicado

Para fazer um programa parecer antigo, podemos aumentar seu tamanho, acrescentar variáveis, fragmentar a lógica em muitos parágrafos e substituir um fluxo organizado por vários desvios. O problema é que essas modificações não reproduzem necessariamente as razões pelas quais um sistema de verdade se torna complexo com o tempo.

Os próprios pesquisadores encontraram essa limitação. Em alguns experimentos, o processo de degradação não preservou completamente o comportamento original. Além disso, os autores reconhecem que perseguir métricas estruturais sem considerar a evolução das regras de negócio pode produzir uma complexidade que não corresponde a uma história de manutenção plausível.

Isso acontece porque sistemas legados não foram deliberadamente projetados para serem confusos. Eles chegaram a esse estado por meio de milhares de decisões que, isoladamente, provavelmente pareciam razoáveis ou inevitáveis.

Imagine um programa criado para calcular um determinado benefício. Alguns anos depois, surge uma exceção para funcionários de uma categoria especial. Em seguida, um novo acordo sindical estabelece outra regra, mas apenas para admissões posteriores a certa data. Uma aquisição exige compatibilidade com um arquivo produzido por outro sistema. Depois, uma decisão judicial estabelece que as regras valem para todos, menos para os herdeiros do Sr. Fulano de Tal.

Cada equipe que trabalhou no sistema ao longo dos anos acrescentou o necessário para resolver o problema – e fechar o ticket. Como o sistema não podia parar, a regra antiga permanecia ao lado da nova. Novas variáveis de trabalho eram criadas para não interferir nos processos que já estavam rodando. Uma condição adicional hard-coded era colocada antes do cálculo para concluir o fechamento do mês. Um segunda versão ligeiramente diferente do programa original era criada para atender a uma demanda específica, e essa versão ficaria para sempre na cadeia de produção.

A entropia nasce justamente da acumulação de soluções localmente justificáveis que nunca são reorganizadas como um todo.

A história fica gravada no sistema

Quando usamos a palavra “entropia” para falar de software, não estamos descrevendo apenas código desorganizado. Estamos falando da perda gradual da correspondência entre o sistema que imaginamos possuir e o sistema que realmente mantém a empresa funcionando.

A documentação, se ainda existir, descreve as regras originais, mas não todas as exceções posteriores. O nome de um campo reflete seu primeiro significado, embora ele já seja utilizado para outras finalidades. Um parágrafo aparentemente inútil é mantido porque ninguém consegue provar que não seja executado durante algum processamento anual. Uma rotina duplicada recebe uma correção, enquanto sua cópia permanece inalterada. Um layout de arquivo não pode ser modificado porque existem consumidores que ninguém conseguiu inventariar.

E nada disso é exclusividade do COBOL. Um sistema construído em Java, C#, Python ou Javascript pode passar pelo mesmo processo de entropia. O COBOL apenas torna isso mais visível porque grande parte dos sistemas construídos nessa linguagem continuam rodando por décadas, mas é mais difícil observar o mesmo com outras linguagens.

E é essa história que o Spec2COBOLRot ainda não consegue fabricar

O Spec2COBOLRot é valioso porque oferece programas públicos mais desafiadores para testar ferramentas de modernização. Seus autores não escondem as limitações e disponibilizaram os programas e as especificações utilizados nos experimentos.

Mas talvez sua contribuição mais interessante seja involuntária. Ao tentar fabricar COBOL legado, o projeto mostrou a diferença entre complexidade estrutural e entropia histórica.

É relativamente fácil produzir código feio. É muito mais difícil reproduzir um sistema que acumulou regras, compromissos, dependências e incertezas durante décadas.

Um sistema COBOL não se torna legado simplesmente porque contém `GO TO`, copybooks extensos ou milhares de variáveis. Ele se torna verdadeiramente difícil quando o conhecimento necessário para modificá-lo com segurança já não está concentrado em nenhum lugar.

E é exatamente por isso que modernizações planejadas como simples projetos de tradução costumam descobrir tarde demais que o desafio nunca esteve apenas na linguagem.