O Bug do Milênio não foi apenas um problema técnico. Foi um problema de logística.

Quando se fala no Bug do Milênio (Y2K), muita gente imagina equipes de programadores procurando datas em programas COBOL e alterando linhas de código. Na verdade, essa era apenas uma pequena parte do trabalho. O verdadeiro desafio era outro.

Como atender dezenas de clientes ao mesmo tempo, modificar dezenas de milhares de programas, testar tudo e colocar os sistemas em produção antes de 1º de janeiro de 2000? Projetos convencionais de manutenção simplesmente não seriam suficientes.

Era necessário transformar manutenção de software em uma linha de produção.

O primeiro passo: descobrir o tamanho do problema

Antes de alterar qualquer programa, era preciso conhecer e entender tudo o que existia no ambiente produtivo do cliente. E muitas vezes, nem o próprio cliente conhecia.

Estávamos falando quase sempre de sistemas desenvolvidos 10 ou 20 anos antes e que continuavam rodando e recebendo manutenções evolutivas e corretivas frequentemente sem documentação.

Mas quantos sistemas o cliente possuía? Quantos programas? Qual o tamanho e a complexidade desses programas? Em qual linguagem cada um deles foi escrito? Quais sistemas dependiam de outros? Quais poderiam ser implantados independentemente?

Esse inventário era essencial para planejar todo o restante do projeto.

Empacotando o trabalho

Depois do inventário, os sistemas eram organizados em partições e pacotes.

Normalmente uma partição correspondia a um sistema e, dentro dela, pacotes de componentes eram separados por tecnologia: COBOL, Natural, PL/I, Easytrieve, JCL e outras linguagens existentes naquele ambiente.

Os pacotes eram então enviados para uma fábrica de software, que havia sido organizada em células especializadas por linguagem. Cada célula era formada por um líder e quatro ou cinco analistas, a quem também chamávamos de “renovadores”.

A organização dos programas em partições e pacotes permitia distribuir o trabalho entre essas células e atender diversos clientes ao mesmo tempo. Quando uma célula concluía seu pacote, ficava disponível para receber outro pacote do mesmo ou de outro cliente. Todo o rastreamento e distribuição desses pacotes era executado por um setor específico da fábrica, que chamávamos genericamente de “logística”.

A seed list: onde começar a procurar?

Ninguém abria milhares de programas manualmente tentando descobrir onde existiam datas. O ponto de partida era uma seed list, criada junto com o cliente na primeira fase do projeto.

A seed list nada mais era do que uma lista de prefixos, sufixos, siglas e abreviações que poderiam indicar que determinada variável armazenava uma data. Por exemplo:

  • DT
  • DATA
  • ANO
  • MES
  • DIA
  • AA
  • MM
  • DD

Essa lista alimentava ferramentas de análise de impacto, que percorriam todo o código-fonte procurando variáveis cujo nome tivesse um desses padrões. Em seguida, outras ferramentas encontravam essas variáveis no resto do programa e geravam uma lista de possíveis pontos de intervenção que depois seriam investigadas por alguém.

Muitas consultorias desenvolveram suas próprias ferramentas para apoiar tanto esse processo de investigação quanto a fase de intervenção que acontecia na sequência.

Ferramentas ajudavam, mas quem decidia era o analista

Depois da busca de variáveis e da geração de possíveis pontos de intervenção começava a parte mais importante do projeto.

Cada ocorrência precisava ser analisada por um analista para confirmar se a variável realmente representava uma data, se era usada em comparações, se participava de cálculos de tempo decorrido ou prazo e se afetavam outras variáveis não identificadas pela seed list.

As ferramentas aceleravam enormemente o trabalho, mas não tomavam decisões. Essa responsabilidade continuava sendo do analista. Somente depois de confirmar que aquele trecho realmente precisava de alteração é que o programa era modificado. Na maioria dos casos, isso significava incluir a lógica de janelamento nas operações de comparação e cálculo.

Quando a fábrica concluía a análise e a intervenção de todos os pacotes de determinada partição, os programas eram reempacotados e devolvidos para o cliente com um “delta” de cada programa alterado.

A fábrica de software fazia as alterações nos fontes, mas os testes aconteciam no cliente, executados por uma equipe de projeto alocada lá pela consultoria.

A hora da verdade: provar que nada foi quebrado

O maior esforço nem sempre estava na programação, e sim nos testes.

Embora fossem realizados testes unitários, integrados e de sistema, muitos clientes priorizavam os testes de regressão. O objetivo era simples: executar exatamente a mesma massa de testes antes e depois da intervenção.

Como a estratégia adotada na maioria dos casos era o janelamento — e não a expansão dos arquivos — as saídas deveriam permanecer rigorosamente iguais.

Se algum resultado mudasse, era sinal de que algo precisava ser investigado e corrigido. A necessidade de correção era muito pontual, e por isso executada pela própria equipe de projeto. Dificilmente uma partição ou pacote precisava voltar para a fábrica para ser processado novamente.

A principal lição

Hoje falamos muito sobre automação, pipelines, integração contínua e DevOps. Na década de 1990, o problema era diferente, mas o desafio era surpreendentemente parecido. Era preciso criar processos repetíveis, ferramentas de apoio, controle de versões, rastreabilidade, padronização das intervenções e evidências de teste para projetos que envolviam milhões de linhas de código.

O Bug do Milênio não foi apenas um grande projeto de correção de software. Foi um enorme exercício de engenharia, logística e organização em larga escala.

E talvez essa seja a parte menos conhecida — e mais interessante — dessa história.