☕ Um Café no Bellacosa Mainframe
Gostou do conteúdo? Ajude a manter o café quente, o COBOL compilando e o mainframe acordado. 😄
☕ Pague um café ao Bellacosa

Translate

domingo, 7 de agosto de 2022

The Wild Wild COBOL — Quando James West Embarcou no Trem do z/OS, Artemus Gordon Vestiu um COMP-3 e o Dr. Loveless Tentou Sabotar a PROCEDURE DIVISION

 

Bellacosa Mainframe e as quatro divisoes do cobol

☕ Um Café no Bellacosa Mainframe

The Wild Wild COBOL — Quando James West Embarcou no Trem do z/OS, Artemus Gordon Vestiu um COMP-3 e o Dr. Loveless Tentou Sabotar a PROCEDURE DIVISION

Ou: o jovem padawan COBOL descobriu que as quatro divisões não são quatro fases de execução, um arquivo não é apenas um arquivo, WORKING-STORAGE não é um depósito de velharias — e nenhum agente secreto deveria atualizar o saldo antes de verificar o FILE STATUS



Prólogo — O trem que entrou no datacenter

Ano de 1965.

Enquanto o mundo assistia à Guerra Fria, à corrida espacial e à multiplicação de computadores empresariais, a televisão americana colocava nos trilhos uma série estranhíssima.

The Wild Wild West misturava faroeste, espionagem, ficção científica, invenções impossíveis, vilões megalomaníacos e agentes secretos que viajavam a bordo de um trem equipado como uma agência móvel de inteligência.

James West, interpretado por Robert Conrad, era o homem da ação. Artemus Gordon, vivido por Ross Martin, era inventor, estrategista e mestre dos disfarces. Ambos protegiam o presidente Ulysses S. Grant contra planos que normalmente começavam com uma pequena engrenagem e terminavam com alguma máquina destinada a dominar o país.

A série estreou em 17 de setembro de 1965 e durou quatro temporadas, com 104 episódios. A ideia era mais ou menos colocar “James Bond a cavalo”, acrescentar um laboratório dentro de um trem e soltar o Dr. Miguelito Loveless no ambiente de produção. The Wild Wild West — série de 1965

Agora imagine que James West receba uma nova missão:

“Agente West, alguém está alterando operações bancárias dentro do mainframe. O suspeito deixou quatro palavras na cena do crime: IDENTIFICATION, ENVIRONMENT, DATA e PROCEDURE.”

West verifica o revólver.

Artemus ajusta os óculos.

No fundo, começa a trilha de Richard Markowitz, misturando jazz, aventura e música de faroeste.

O trem parte para o datacenter.



1. Afinal, como “pensa” um programa COBOL?

Dizer que um programa “pensa” é uma metáfora.

O programa não possui consciência, intenção ou compreensão do negócio. Ele não olha para um campo chamado SALDO-CLIENTE e sente preocupação com o correntista.

O que ele faz é:

  1. receber ou acessar dados;

  2. interpretá-los conforme suas definições;

  3. executar instruções;

  4. verificar condições;

  5. alterar estados;

  6. produzir resultados;

  7. informar sucesso ou erro ao ambiente.

Por isso, uma definição mais precisa seria:

Um programa COBOL processa informações segundo contratos de dados e regras procedurais previamente definidas.

Sua famosa organização em quatro divisões responde a quatro perguntas:

DivisãoPergunta
IDENTIFICATION DIVISIONQuem sou?
ENVIRONMENT DIVISIONCom quais recursos externos trabalharei?
DATA DIVISIONComo minhas informações estão organizadas?
PROCEDURE DIVISIONO que devo fazer?

A IBM continua documentando essa estrutura no Enterprise COBOL moderno. As quatro divisões organizam o programa-fonte, embora nem todas precisem conter a mesma quantidade de elementos em todos os programas. IBM — COBOL program structure

Mas aqui encontramos a primeira armadilha do Dr. Loveless:

As quatro divisões não são quatro etapas executadas uma depois da outra.

O computador não executa a IDENTIFICATION DIVISION, entra na ENVIRONMENT DIVISION, passeia pela DATA DIVISION e finalmente chega à PROCEDURE DIVISION.

As três primeiras são essencialmente declarativas. Elas fornecem informações para que o compilador compreenda o programa.

A execução das instruções acontece na PROCEDURE DIVISION.

As quatro divisões são os compartimentos do trem. A PROCEDURE DIVISION é a locomotiva.



2. IDENTIFICATION DIVISION: os documentos do agente

Todo agente precisa de uma identidade:

       IDENTIFICATION DIVISION.
       PROGRAM-ID. PROCESSA-OPERACOES.

O elemento central é o PROGRAM-ID, que identifica a unidade de programa.

Em códigos mais antigos, podemos encontrar:

       AUTHOR. VAGNER BELLACOSA.
       INSTALLATION. BANCO-WILD-WEST.
       DATE-WRITTEN. 1965-09-17.

Esses parágrafos documentais foram mais importantes em uma época anterior a Git, Endevor, Changeman, ISPW e outros sistemas de controle de versão e gerenciamento do ciclo de vida.

Hoje, manter um histórico completo de alterações dentro do fonte costuma provocar blocos enormes de comentários:

      * ALTERADO POR FULANO EM 1987
      * ALTERADO POR SICRANO EM 1994
      * ALTERADO NOVAMENTE EM 2001
      * NINGUÉM SABE QUEM ALTEROU EM 2007

Esse tipo de comentário pode ser útil, mas não substitui um repositório confiável.

O que a divisão não faz

Ela não é executada como uma rotina.

O programa não começa dizendo:

Olá, sistema operacional.
Meu nome é PROCESSA-OPERACOES.
Fui escrito por Vagner.

Sua função principal é identificar o programa para o compilador e para o ecossistema de desenvolvimento.

Dica do agente West

Ao analisar um fonte desconhecido, procure primeiro:

       PROGRAM-ID.

Depois procure:

  • comentários iniciais;

  • descrição funcional;

  • nomes de copybooks;

  • PROCEDURE DIVISION USING;

  • programas chamados;

  • comandos CICS ou SQL.

O PROGRAM-ID mostra o nome. As interfaces mostram quem o programa realmente é.

Easter egg número 1

O programa de exemplo poderia se chamar:

       PROGRAM-ID. NIGHT-OF-THE-COMP3.

Os episódios de The Wild Wild West frequentemente começavam com “The Night of...”. Portanto, “The Night of the Packed Decimal” seria um episódio perfeitamente plausível no datacenter Bellacosa.



3. ENVIRONMENT DIVISION: o trem e os trilhos

James West e Artemus Gordon viajavam em seu próprio trem, o Wanderer, equipado com aposentos, armas, dispositivos e laboratório.

O trem era a plataforma operacional dos agentes.

No COBOL, a ENVIRONMENT DIVISION ajuda a descrever como o programa se relaciona com seu ambiente e, particularmente, com os arquivos utilizados.

       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.

           SELECT ARQUIVO-ENTRADA
               ASSIGN TO TRANSIN
               ORGANIZATION IS SEQUENTIAL
               FILE STATUS IS WS-STATUS-ENTRADA.

           SELECT ARQUIVO-SAIDA
               ASSIGN TO TRANSOUT
               ORGANIZATION IS SEQUENTIAL
               FILE STATUS IS WS-STATUS-SAIDA.

Aqui existem diferentes níveis de nome:

  • ARQUIVO-ENTRADA: nome lógico conhecido pelo programa;

  • TRANSIN: ligação externa;

  • dataset: recurso físico fornecido durante a execução.

O JCL poderia conter:

//STEP01   EXEC PGM=PROCESSA
//STEPLIB  DD DSN=BANCO.LOADLIB,DISP=SHR
//TRANSIN  DD DSN=BANCO.OPERACOES.ENTRADA,DISP=SHR
//TRANSOUT DD DSN=BANCO.OPERACOES.SAIDA,
//            DISP=(NEW,CATLG,DELETE),
//            SPACE=(CYL,(10,5))

O programa não precisa ter o nome físico BANCO.OPERACOES.ENTRADA gravado dentro do fonte.

Ele pede TRANSIN.

O ambiente entrega o dataset correspondente.

Isso permite executar o mesmo programa com diferentes arquivos:

//TRANSIN DD DSN=BANCO.OPERACOES.20260829,DISP=SHR

ou:

//TRANSIN DD DSN=BANCO.OPERACOES.20260830,DISP=SHR

Nenhuma recompilação é necessária.

Isso parece moderno?

É uma forma antiga e muito eficiente de separar:

  • código;

  • configuração;

  • recurso físico;

  • execução.

Em linguagens modernas, talvez alguém chamasse isso de configuração externa, abstração de recursos ou injeção de dependência.

No mainframe, o jovem padawan encontra o conceito dentro de um JCL escrito quando “cloud-native” ainda poderia significar um índio olhando para as nuvens antes de uma tempestade.

O contrato entre três partes

ParticipanteResponsabilidade
COBOLDeclara o nome lógico e a forma de acesso
JCL ou subsistemaAssocia o nome lógico ao recurso
Sistema operacionalExecuta e controla o I/O

Curiosidade

A ENVIRONMENT DIVISION não descreve tudo sobre o ambiente de produção.

Ela não contém necessariamente:

  • capacidade da LPAR;

  • política do WLM;

  • regras RACF;

  • configuração do sysplex;

  • parâmetros do CICS;

  • velocidade dos discos;

  • prioridade do job;

  • quantidade de memória disponível.

Por isso, dizer que ela “descreve onde o programa será executado” é didaticamente aceitável, mas amplo demais.

Ela descreve aspectos do ambiente relevantes ao COBOL, especialmente a relação com arquivos e dispositivos lógicos.



4. DATA DIVISION: o laboratório de Artemus Gordon

Artemus Gordon era o inventor e mestre dos disfarces.

Ele podia entrar num episódio como vendedor, cientista, militar, médico ou personagem improvável. O homem mudava a aparência, mas continuava sendo Artemus.

A DATA DIVISION possui algo dessa natureza: ela informa como sequências de bytes devem ser interpretadas.

Os mesmos bytes podem representar:

  • caracteres;

  • números;

  • datas;

  • valores monetários;

  • chaves;

  • indicadores;

  • registros;

  • tabelas;

  • áreas recebidas de outros programas.

A DATA DIVISION não é apenas um depósito de variáveis. É o laboratório onde bytes recebem forma e significado.

Ela pode conter seções como:

  • FILE SECTION;

  • WORKING-STORAGE SECTION;

  • LOCAL-STORAGE SECTION;

  • LINKAGE SECTION.

Cada uma responde a uma necessidade diferente.


4.1 FILE SECTION: a planta dos vagões

A ENVIRONMENT DIVISION informa como localizar o trem.

A FILE SECTION informa como cada vagão está organizado.

       DATA DIVISION.
       FILE SECTION.

       FD  ARQUIVO-ENTRADA
           RECORDING MODE IS F.

       01  REGISTRO-ENTRADA.
           05  IN-TIPO-OPERACAO     PIC X.
           05  IN-NUMERO-CONTA      PIC 9(10).
           05  IN-VALOR             PIC 9(11)V99.
           05  IN-DATA              PIC 9(8).
           05  IN-IDENTIFICADOR     PIC X(20).

O FD, ou File Description, descreve o arquivo para o programa.

O nível 01 descreve cada registro lido.

A diferença é importante:

ElementoFunção
SELECTDeclara a relação lógica com o arquivo
FDDescreve características do arquivo
Registro 01Define o layout dos dados
JCL DDFornece o dataset físico

O perigo do vagão deslocado

Imagine que o arquivo contenha:

C00012345670000000012500020260830ABC123

Se o layout estiver deslocado por uma posição, o programa pode interpretar:

  • parte da conta como valor;

  • parte do valor como data;

  • parte da data como identificador.

O arquivo existe. O job pode até começar. Mas os significados estarão errados.

Esse é um dos grandes ensinamentos do COBOL:

Dados não são apenas conteúdo; são conteúdo, posição, tamanho, formato e contexto.


4.2 WORKING-STORAGE SECTION: a bancada permanente

       WORKING-STORAGE SECTION.

       01  WS-CONTADORES.
           05  WS-REGISTROS-LIDOS       PIC 9(9) VALUE ZERO.
           05  WS-APROVADOS             PIC 9(9) VALUE ZERO.
           05  WS-REJEITADOS            PIC 9(9) VALUE ZERO.

       01  WS-TOTAL-PROCESSADO           PIC S9(13)V99 COMP-3
                                         VALUE ZERO.

       01  WS-STATUS-ENTRADA             PIC XX.
       01  WS-STATUS-SAIDA               PIC XX.

A WORKING-STORAGE guarda dados internos necessários ao processamento:

  • contadores;

  • acumuladores;

  • indicadores;

  • mensagens;

  • resultados intermediários;

  • chaves de pesquisa;

  • códigos de retorno;

  • áreas auxiliares;

  • tabelas internas.

Ela é a bancada de Artemus Gordon: engrenagens, tubos, ferramentas, documentos e explosivos que Igor jurou serem apenas “materiais de homologação”.

Cuidado com uma simplificação perigosa

Muitos iniciantes imaginam que a WORKING-STORAGE sempre nasce completamente limpa toda vez que o programa é chamado.

Isso não deve ser presumido sem compreender:

  • o ambiente de execução;

  • o ciclo de vida do módulo;

  • se o programa é inicial;

  • se é chamado repetidamente;

  • se utiliza IS INITIAL;

  • se há reutilização da área.

O comportamento da WORKING-STORAGE importa especialmente em subprogramas, aplicações residentes e ambientes CICS.

A regra prática é:

Inicialize explicitamente aquilo cujo valor inicial seja importante para a lógica.

       INITIALIZE WS-CONTADORES
                  WS-TOTAL-PROCESSADO

Mas também compreenda o que INITIALIZE fará com cada categoria de campo. Não transforme o comando numa varinha mágica usada sem ler o layout.


4.3 LOCAL-STORAGE SECTION: uma bancada para cada missão

       LOCAL-STORAGE SECTION.

       01  LS-CONTADOR-TEMPORARIO       PIC 9(4).
       01  LS-VALOR-INTERMEDIARIO        PIC S9(9)V99 COMP-3.

A LOCAL-STORAGE é alocada a cada entrada no programa e liberada quando a execução retorna.

Ela é útil quando diferentes ativações precisam de áreas independentes, especialmente em situações recursivas ou reentrantes.

Podemos imaginar assim:

  • WORKING-STORAGE: laboratório instalado no trem;

  • LOCAL-STORAGE: maleta nova entregue para esta missão;

  • LINKAGE: documento recebido de outro agente.

A IBM distingue essas áreas pelo modo como o armazenamento é obtido e pelo ciclo de vida dos dados. IBM — Describing the data


4.4 LINKAGE SECTION: a mensagem secreta de Washington

       LINKAGE SECTION.

       01  LK-OPERACAO.
           05  LK-CONTA                 PIC 9(10).
           05  LK-VALOR                 PIC S9(11)V99 COMP-3.
           05  LK-TIPO                  PIC X.
           05  LK-CODIGO-RETORNO        PIC XX.

A LINKAGE SECTION descreve dados disponibilizados por outro componente.

       PROCEDURE DIVISION USING LK-OPERACAO.

O programa chamado conhece o layout, mas normalmente não é o proprietário original da área.

Outro programa poderia executar:

       CALL 'VALOPER'
           USING WS-OPERACAO

O programa VALOPER receberia a área por meio da LINKAGE SECTION.

A metáfora correta

James West recebe uma mensagem cifrada do presidente Grant.

Ele não criou o papel.

Não é dono da pasta.

Mas precisa conhecer a estrutura da mensagem para interpretá-la.

A LINKAGE SECTION descreve essa mensagem.

Perigo de produção

Chamador e chamado precisam concordar sobre:

  • tamanho da área;

  • ordem dos campos;

  • representação;

  • sinal;

  • quantidade de casas decimais;

  • forma de passagem;

  • campos de retorno.

Se um programa define:

       05 VALOR PIC S9(7)V99 COMP-3.

e outro acredita receber:

       05 VALOR PIC X(20).

Artemus Gordon pode usar todos os disfarces disponíveis: o contrato continua incompatível.



5. PICTURE: o código secreto dos dados

Considere:

       05  WS-VALOR              PIC S9(7)V99 COMP-3.

Esse campo diz muito mais do que “sou um número”.

  • S: possui sinal;

  • 9(7): comporta sete dígitos inteiros;

  • V: possui ponto decimal implícito;

  • 99: possui duas casas decimais;

  • COMP-3: usa representação decimal compactada.

O V não ocupa um byte físico. Ele informa a posição lógica do separador decimal.

Se o campo contiver os dígitos equivalentes a:

000012345

o COBOL poderá tratá-los como:

1.234,45

conforme o PICTURE.

Por que isso importa aos bancos?

Valores financeiros precisam de precisão decimal previsível.

Usar ponto flutuante binário indiscriminadamente pode introduzir aproximações inconvenientes para dinheiro. COBOL oferece representações de ponto fixo, e itens COMP-3 são tratados como decimais compactados para operações aritméticas. IBM — Numeric data formats

COMP-3 não é o cofre do presidente Grant

Ele não impede automaticamente:

  • estouro;

  • truncamento;

  • arredondamento indevido;

  • dado inválido;

  • erro de sinal;

  • campo insuficiente;

  • regra financeira incorreta.

Por exemplo:

       01 WS-PEQUENO PIC 9(3).

O campo só comporta três dígitos. Tentar colocar um valor maior exige compreender o comportamento da operação e as opções de compilação.

Dica Bellacosa

Para dinheiro, não pergunte apenas:

“Quantos bytes esse campo ocupa?”

Pergunte também:

  • qual é a moeda?

  • quantas casas decimais?

  • pode ser negativo?

  • qual é o maior valor permitido?

  • qual regra de arredondamento?

  • zero é válido?

  • espaços são possíveis na entrada?

  • dados negativos representam débito ou estorno?

O tipo físico é apenas metade do contrato. A semântica empresarial é a outra.



6. Níveis de dados: o trem dentro do trem

Os números 01, 05 e 10 indicam hierarquia:

       01  CLIENTE.
           05  CLIENTE-ID                 PIC 9(10).
           05  CLIENTE-NOME.
               10  CLIENTE-PRIMEIRO-NOME PIC X(20).
               10  CLIENTE-SOBRENOME     PIC X(30).
           05  CLIENTE-ENDERECO.
               10  CLIENTE-RUA           PIC X(40).
               10  CLIENTE-NUMERO        PIC 9(6).
               10  CLIENTE-CEP           PIC 9(8).

CLIENTE é um grupo.

CLIENTE-NOME é um subgrupo.

CLIENTE-SOBRENOME é um campo elementar.

Podemos mover o grupo:

       MOVE CLIENTE-NOME TO NOME-IMPRESSAO

ou somente uma parte:

       MOVE CLIENTE-SOBRENOME
         TO SOBRENOME-IMPRESSAO

COBOL permite trabalhar com o registro completo e com suas partes.

Curiosidade: nome qualificado

Se existirem dois campos chamados NUMERO:

       NUMERO OF CLIENTE-ENDERECO

podemos qualificá-los por sua estrutura superior.

Isso demonstra que o nome de um campo também pode depender de seu contexto.


7. Nível 88: quando um código vira regra de negócio

Veja:

       01  WS-FIM-ARQUIVO             PIC X VALUE 'N'.
           88  FIM-DO-ARQUIVO         VALUE 'S'.
           88  HA-REGISTROS           VALUE 'N'.

O nível 88 cria nomes de condição.

Em vez de:

       IF WS-FIM-ARQUIVO = 'S'

podemos usar:

       IF FIM-DO-ARQUIVO

Outro exemplo:

       01  WS-STATUS-CONTA            PIC X.
           88  CONTA-ATIVA            VALUE 'A'.
           88  CONTA-BLOQUEADA        VALUE 'B'.
           88  CONTA-ENCERRADA        VALUE 'E'.

A lógica torna-se expressiva:

       IF CONTA-BLOQUEADA
           MOVE 'OPERACAO NAO PERMITIDA'
             TO WS-MENSAGEM
       END-IF

O nível 88 não costuma reservar outra área independente. Ele atribui significado a valores da variável associada.

O disfarce de Artemus Gordon

O byte físico contém B.

Para o computador, é um caractere.

Para o programa, significa CONTA-BLOQUEADA.

Para o negócio, significa que determinadas operações precisam ser impedidas.

Artemus não alterou o byte. Alterou a maneira pela qual nós o compreendemos.



8. PROCEDURE DIVISION: James West entra em ação

Aqui ficam as instruções executáveis:

       PROCEDURE DIVISION.

       0000-PRINCIPAL.
           PERFORM 1000-INICIALIZAR

           PERFORM 2000-PROCESSAR
               UNTIL FIM-DO-ARQUIVO

           PERFORM 3000-FINALIZAR

           GOBACK.

A estrutura revela um programa batch clássico:

  1. inicializar;

  2. processar;

  3. finalizar;

  4. devolver o controle.

       1000-INICIALIZAR.
           OPEN INPUT  ARQUIVO-ENTRADA
                OUTPUT ARQUIVO-SAIDA

           IF WS-STATUS-ENTRADA NOT = '00'
               DISPLAY 'ERRO NA ABERTURA: '
                       WS-STATUS-ENTRADA
               MOVE 12 TO RETURN-CODE
               GOBACK
           END-IF

           PERFORM 1100-LER-ENTRADA.

Depois:

       2000-PROCESSAR.
           PERFORM 2100-VALIDAR

           IF OPERACAO-VALIDA
               PERFORM 2200-EFETIVAR
           ELSE
               PERFORM 2300-REJEITAR
           END-IF

           PERFORM 2400-GRAVAR-RESULTADO
           PERFORM 1100-LER-ENTRADA.

No final:

       3000-FINALIZAR.
           CLOSE ARQUIVO-ENTRADA
                 ARQUIVO-SAIDA

           DISPLAY 'LIDOS:      ' WS-REGISTROS-LIDOS
           DISPLAY 'APROVADOS:  ' WS-APROVADOS
           DISPLAY 'REJEITADOS: ' WS-REJEITADOS.

O erro do iniciante

O iniciante pode acreditar que o COBOL começa executando o primeiro parágrafo visualmente encontrado em qualquer ponto do fonte.

A execução começa na primeira instrução executável da PROCEDURE DIVISION, salvo particularidades e pontos de entrada definidos.

Organizar um parágrafo não é chamá-lo.

Este parágrafo:

       EXPLODIR-TREM.
           DISPLAY 'BOOM'.

não será executado apenas porque existe. Ele precisa ser alcançado pelo fluxo, por exemplo:

       PERFORM EXPLODIR-TREM

Igor agradece a informação.



9. O ciclo clássico: ler, testar, processar, ler novamente

Um programa sequencial costuma seguir este modelo:

       PERFORM LER-ENTRADA

       PERFORM UNTIL FIM-DO-ARQUIVO
           PERFORM PROCESSAR-REGISTRO
           PERFORM LER-ENTRADA
       END-PERFORM

A primeira leitura ocorre antes do laço.

Isso garante que o programa só processe quando houver um registro disponível.

       LER-ENTRADA.
           READ ARQUIVO-ENTRADA
               AT END
                   SET FIM-DO-ARQUIVO TO TRUE
               NOT AT END
                   ADD 1 TO WS-REGISTROS-LIDOS
           END-READ.

O fim do arquivo não é necessariamente erro ou ABEND.

É uma condição esperada.

O programa lê até que o arquivo informe:

“Agente West, não existem mais passageiros.”

Então finaliza o processamento.

flowchart TD
    A["Abrir arquivos"] --> B["Ler registro"]
    B --> C{"Fim do arquivo?"}
    C -- Não --> D["Validar e processar"]
    D --> E["Gravar resultado"]
    E --> B
    C -- Sim --> F["Fechar e emitir totais"]

A armadilha do último registro

Se o programa processar antes da primeira leitura, trabalhará com uma área ainda não preenchida corretamente.

Se esquecer a leitura ao final do laço, processará o mesmo registro para sempre.

O resultado pode ser um laço infinito, alto consumo de CPU ou um job aparentemente decidido a atravessar o continente sem parar em nenhuma estação.



10. O verdadeiro pensamento: estados e condições

Um programa COBOL não trabalha somente com linhas. Ele trabalha com estados:

  • arquivo fechado;

  • arquivo aberto;

  • registro disponível;

  • fim do arquivo;

  • operação válida;

  • operação rejeitada;

  • atualização pendente;

  • commit realizado;

  • rollback solicitado.

Considere:

       EVALUATE TRUE
           WHEN IN-CONTA = ZERO
               PERFORM REJEITAR-CONTA
           WHEN IN-VALOR <= ZERO
               PERFORM REJEITAR-VALOR
           WHEN IN-VALOR > WS-LIMITE
               PERFORM ANALISAR-LIMITE
           WHEN OTHER
               PERFORM APROVAR-OPERACAO
       END-EVALUATE

O EVALUATE TRUE permite expressar uma cadeia organizada de condições.

Também podemos avaliar um campo diretamente:

       EVALUATE IN-TIPO-OPERACAO
           WHEN 'C'
               PERFORM PROCESSAR-CREDITO
           WHEN 'D'
               PERFORM PROCESSAR-DEBITO
           WHEN 'E'
               PERFORM PROCESSAR-ESTORNO
           WHEN OTHER
               PERFORM REJEITAR-TIPO
       END-EVALUATE

O WHEN OTHER é a porta dos fundos.

Se ele não existir, uma entrada inesperada pode passar sem o tratamento necessário.

A pergunta de produção

Ao depurar, não pergunte somente:

“Qual foi a última linha executada?”

Pergunte:

“Em que estado o programa acreditava estar?”

Um incidente frequentemente ocorre porque o estado real e o estado imaginado pelo programa divergiram.



11. FILE STATUS: a mensagem escondida no bolso do vilão

Ao declarar:

       FILE STATUS IS WS-STATUS-ENTRADA

o programa recebe informações sobre o resultado das operações de arquivo.

Depois de OPEN, READ, WRITE, REWRITE ou CLOSE, deve avaliar o código quando necessário.

       READ ARQUIVO-ENTRADA

       EVALUATE WS-STATUS-ENTRADA
           WHEN '00'
               CONTINUE
           WHEN '10'
               SET FIM-DO-ARQUIVO TO TRUE
           WHEN OTHER
               DISPLAY 'ERRO DE LEITURA: '
                       WS-STATUS-ENTRADA
               MOVE 12 TO RETURN-CODE
       END-EVALUATE

Os significados exatos dependem da organização e da operação, devendo ser consultados na documentação aplicável.

Não faça isso no saloon

       READ ARQUIVO-ENTRADA
       PERFORM PROCESSAR-REGISTRO

Sem verificar o resultado, o programa pode processar uma área não atualizada ou tratar um erro como se fosse sucesso.

James West nunca entraria num quarto escuro sem verificar a janela.

Igor entra, atualiza o VSAM e pergunta depois.



12. O programa bancário completo

Considere uma operação contendo:

  • tipo;

  • conta;

  • valor;

  • data;

  • identificador único.

O fluxo poderia ser:

  1. validar o tamanho e o formato;

  2. validar o tipo;

  3. verificar duplicidade;

  4. localizar a conta;

  5. verificar o estado da conta;

  6. conferir saldo ou limite;

  7. calcular o novo saldo;

  8. atualizar a conta;

  9. registrar auditoria;

  10. confirmar a unidade de trabalho;

  11. gerar a resposta.

Uma versão didática:

       PROCESSAR-OPERACAO.
           SET OPERACAO-VALIDA TO TRUE

           PERFORM VALIDAR-TIPO
           PERFORM VALIDAR-CONTA
           PERFORM VALIDAR-VALOR

           IF OPERACAO-VALIDA
               EVALUATE IN-TIPO-OPERACAO
                   WHEN 'C'
                       ADD IN-VALOR TO WS-SALDO
                       MOVE '00' TO OUT-CODIGO
                   WHEN 'D'
                       IF WS-SALDO >= IN-VALOR
                           SUBTRACT IN-VALOR
                             FROM WS-SALDO
                           MOVE '00' TO OUT-CODIGO
                       ELSE
                           MOVE '51' TO OUT-CODIGO
                       END-IF
                   WHEN OTHER
                       MOVE '12' TO OUT-CODIGO
               END-EVALUATE
           END-IF.

Mas este código ainda não representa um sistema financeiro completo.

Faltam assuntos como:

  • autorização;

  • concorrência;

  • bloqueio;

  • persistência;

  • duplicidade;

  • idempotência;

  • segurança;

  • auditoria;

  • commit;

  • rollback;

  • reconciliação;

  • recuperação após falha.

Idempotência: a mesma diligência não pode ser assaltada duas vezes

Se a mesma operação chegar novamente por causa de retry, o sistema precisa saber se deve repeti-la.

Um identificador único pode ajudar a reconhecer que ela já foi processada.

Sem isso, um retry de comunicação pode transformar um débito de R$100 em dois débitos de R$100.

O primeiro processamento foi correto.

O segundo também seguiu corretamente as instruções.

O resultado empresarial, porém, está errado.



13. COMMIT e ROLLBACK: quem fica com o dinheiro?

Em processamento transacional, alterar uma conta e registrar a operação precisam formar uma unidade coerente.

Imagine:

  1. debitar a conta;

  2. gravar o histórico;

  3. atualizar a auditoria;

  4. confirmar.

Se o sistema falhar entre os passos 1 e 2, o saldo poderia mudar sem existir histórico correspondente.

O controle transacional procura impedir esse tipo de estado parcial.

  • COMMIT: confirma as alterações;

  • ROLLBACK: desfaz alterações da unidade de trabalho ainda não confirmadas.

O Dr. Loveless do retry

O retry não é um mecanismo automaticamente bondoso.

Se uma operação falha antes da confirmação, talvez seja seguro repeti-la.

Se o cliente apenas não recebeu a resposta, mas a operação já foi confirmada, repeti-la pode duplicar o efeito.

Por isso, sistemas críticos precisam distinguir:

  • a solicitação não chegou;

  • chegou, mas falhou;

  • foi processada e sofreu rollback;

  • foi confirmada;

  • foi confirmada, mas a resposta se perdeu.

O agente competente não pergunta apenas “deu erro?”.

Ele pergunta:

“Em qual lado do COMMIT estávamos quando o trem explodiu?”


14. Em CICS, James West não percorre o arquivo inteiro

Num programa batch, o fluxo frequentemente percorre muitos registros.

Em CICS, uma transação normalmente recebe uma solicitação, executa uma unidade curta de processamento e responde.

       EXEC CICS READ
            FILE('CONTAS')
            INTO(WS-REGISTRO-CONTA)
            RIDFLD(WS-CHAVE-CONTA)
            UPDATE
            RESP(WS-RESP)
       END-EXEC

Depois:

       EVALUATE WS-RESP
           WHEN DFHRESP(NORMAL)
               PERFORM PROCESSAR-CONTA
           WHEN DFHRESP(NOTFND)
               PERFORM TRATAR-CONTA-INEXISTENTE
           WHEN OTHER
               PERFORM TRATAR-ERRO-CICS
       END-EVALUATE

Aqui, o código COBOL trabalha sob o controle de um gerenciador transacional.

O CICS participa de:

  • despacho da transação;

  • acesso a recursos;

  • controle de unidade de trabalho;

  • comunicação;

  • recuperação;

  • gerenciamento operacional.

COBOL não está sozinho no trem. O CICS é o chefe da ferrovia.



15. Com Db2, entra o especialista relacional

       EXEC SQL
           SELECT SALDO,
                  STATUS_CONTA
             INTO :WS-SALDO,
                  :WS-STATUS-CONTA
             FROM CONTAS
            WHERE NUMERO_CONTA = :WS-CONTA
       END-EXEC

Depois:

       EVALUATE SQLCODE
           WHEN ZERO
               PERFORM PROCESSAR-CONTA
           WHEN +100
               PERFORM TRATAR-NAO-ENCONTRADA
           WHEN OTHER
               PERFORM TRATAR-ERRO-DB2
       END-EVALUATE

COBOL cuida do fluxo procedural e das regras.

Db2 cuida do acesso relacional, dos dados, índices, planos e mecanismos internos.

O programa não precisa saber em qual página física está a linha. Precisa saber:

  • o que solicitou;

  • quais host variables receberão os valores;

  • qual foi o SQLCODE;

  • qual ação tomar.

Dica do Artemus

Nunca trate todo SQLCODE diferente de zero como a mesma coisa.

“Não encontrado”, “aviso”, “deadlock”, “timeout” e “erro estrutural” não significam a mesma situação operacional.

Um agente secreto que chama todos os desconhecidos de “Dr. Loveless” terminará prendendo o condutor do próprio trem.



16. O programa que escrevemos não é exatamente o programa executado

Antes da execução existe uma cadeia:

  1. expansão de copybooks;

  2. processamento de diretivas;

  3. tratamento de SQL, CICS ou outras extensões;

  4. compilação;

  5. geração do objeto;

  6. link-edit ou bind;

  7. criação do módulo de carga;

  8. carregamento;

  9. execução.

Quando escrevemos:

       COPY CPYCONTA.

o copybook é incorporado durante a preparação do fonte.

Quando escrevemos:

       ADD WS-VALOR TO WS-TOTAL

a CPU não executa a palavra inglesa ADD. O compilador gera instruções adequadas à arquitetura e às representações envolvidas.

COBOL descreve a intenção; o compilador produz a mecânica.

Compiladores modernos também podem otimizar o código para explorar recursos atuais do IBM Z. Portanto, um fonte com aparência antiga não significa necessariamente execução com técnicas de 1965.

O trem pode ser clássico. A locomotiva não precisa ser a vapor.


17. Antigo não significa automaticamente simples

Programas COBOL antigos podem conter:

  • REDEFINES;

  • OCCURS DEPENDING ON;

  • arquivos VSAM;

  • múltiplos índices;

  • chamadas dinâmicas;

  • SQL;

  • CICS;

  • IMS;

  • MQ;

  • tabelas complexas;

  • copybooks aninhados;

  • lógica gerada;

  • regras acumuladas por décadas.

Veja um REDEFINES:

       01  WS-RESPOSTA.
           05 WS-RESPOSTA-BRUTA       PIC X(20).

       01  WS-RESPOSTA-DETALHADA
           REDEFINES WS-RESPOSTA.
           05 WS-CODIGO               PIC XX.
           05 WS-MENSAGEM             PIC X(18).

As duas estruturas interpretam a mesma área de armazenamento.

Artemus Gordon continua sendo o mesmo homem, mas agora aparece com outro disfarce.

O recurso é poderoso. Também pode ficar difícil de rastrear quando usado sem disciplina.

OCCURS: a lista de passageiros

       01  WS-TABELA-TAXAS.
           05 WS-TAXA OCCURS 10 TIMES.
               10 WS-CODIGO-TAXA      PIC XX.
               10 WS-PERCENTUAL       PIC 9V9999.

Isso cria uma tabela com dez ocorrências.

Pode ser acessada assim:

       MOVE 'TX' TO WS-CODIGO-TAXA(1)

Em estruturas maiores, podem existir índices, pesquisas sequenciais e SEARCH ALL.

O iniciante deve entender que uma tabela COBOL não é um banco de dados. É uma estrutura repetida dentro de uma área de dados.



18. COBOL não é confiável por encantamento

A linguagem favorece descrições explícitas e processamento empresarial. Seu ecossistema amadureceu durante décadas. Porém, nenhum programa se torna confiável apenas por terminar suas frases com ponto.

COBOL também pode sofrer:

  • S0C7 por dado decimal inválido;

  • S0C4 por referência indevida à memória;

  • S0CB por divisão por zero;

  • falhas de arquivo;

  • erros Db2;

  • deadlocks;

  • timeouts;

  • truncamentos;

  • perda de precisão;

  • loops;

  • commits incorretos;

  • regras de negócio erradas.

O compilador pode aceitar perfeitamente:

       ADD TAXA TO SALDO

Mesmo que a regra correta fosse:

       SUBTRACT TAXA FROM SALDO

Sintaticamente correto.

Financeiramente desastroso.

Clareza também não vem automaticamente

Compare:

       IF X = 'S'
           PERFORM 9000
       END-IF

com:

       IF CLIENTE-ELEGIVEL
           PERFORM CALCULAR-LIMITE
       END-IF

O segundo código apresenta intenção.

Use nomes que revelem o negócio:

  • VALIDAR-LIMITE-DA-CONTA;

  • CALCULAR-JUROS;

  • GRAVAR-OPERACAO-REJEITADA;

  • TRATAR-CONTA-ENCERRADA.

Evite transformar a PROCEDURE DIVISION num mapa desenhado pelo Dr. Loveless depois de três garrafas de bourbon.



19. Passo a passo para ler um programa desconhecido

Passo 1 — Descubra a missão

Leia:

  • PROGRAM-ID;

  • comentários funcionais;

  • nome do membro;

  • JCL que executa o programa;

  • documentação relacionada.

Pergunte: qual problema empresarial ele resolve?

Passo 2 — Mapeie entradas e saídas

Procure:

  • SELECT;

  • FD;

  • READ;

  • WRITE;

  • REWRITE;

  • LINKAGE SECTION;

  • PROCEDURE DIVISION USING;

  • EXEC SQL;

  • EXEC CICS;

  • comandos MQ;

  • CALL.

Desenhe as fronteiras antes de estudar todos os detalhes.

Passo 3 — Ache o fluxo principal

Procure nomes como:

  • MAIN;

  • PRINCIPAL;

  • INICIO;

  • INITIALIZE;

  • PROCESS;

  • TERMINATE;

  • FINALIZAR.

Anote os principais PERFORM.

Passo 4 — Encontre as condições de controle

Procure:

  • níveis 88;

  • flags;

  • FILE STATUS;

  • SQLCODE;

  • RESP;

  • RETURN-CODE;

  • indicadores de fim.

Esses elementos mostram como o programa toma decisões.

Passo 5 — Localize as alterações permanentes

Onde ele:

  • grava arquivo?

  • atualiza Db2?

  • reescreve VSAM?

  • envia mensagem?

  • confirma a transação?

  • realiza rollback?

Esses são os pontos de maior risco.

Passo 6 — Siga o caminho infeliz

Não leia somente o cenário de sucesso.

Pergunte:

  • e se a conta não existir?

  • e se o arquivo não abrir?

  • e se o dado não for numérico?

  • e se houver deadlock?

  • e se a operação chegar duas vezes?

  • e se a resposta se perder depois do commit?

Passo 7 — Confirme o contrato físico

Confira:

  • tamanho dos campos;

  • PIC;

  • USAGE;

  • sinal;

  • casas decimais;

  • alinhamento;

  • copybooks;

  • encoding;

  • definição no sistema externo.

Passo 8 — Só então aprofunde cada parágrafo

Depois de compreender o mapa, siga as rotinas em detalhe.

Ler um programa grande da linha 1 até a linha 20.000 sem criar um mapa é como procurar o Dr. Loveless revistando cada parafuso do trem.



20. Curiosidades escondidas no vagão de bagagens

Curiosidade 1 — A série e o COBOL pertencem à mesma era cultural

COBOL surgiu no final dos anos 1950 e se consolidou nos anos 1960. The Wild Wild West estreou em 1965.

Os dois refletem, de maneiras diferentes, uma era fascinada por organizações, máquinas, automação, espionagem e tecnologia.

Curiosidade 2 — O tema musical também é híbrido

A música de Richard Markowitz combinava elementos de jazz e do faroeste. A série precisava soar simultaneamente clássica e moderna.

COBOL também é uma combinação curiosa:

  • palavras quase naturais;

  • layouts rígidos;

  • representação binária e decimal;

  • regras comerciais;

  • execução em hardware extremamente sofisticado.

Curiosidade 3 — Artemus Gordon usou dezenas de disfarces

Ross Martin transformou o personagem num mestre de caracterização. Em COBOL, REDEFINES permite que uma mesma área seja interpretada de maneiras diferentes.

Não significa que REDEFINES foi inspirado por Artemus. Mas o Easter egg é bom demais para ser desperdiçado.

Curiosidade 4 — O primeiro ano foi em preto e branco

A primeira temporada da série foi filmada em preto e branco; as seguintes passaram para cores.

O fonte COBOL também pode parecer monocromático numa listagem antiga, mas ferramentas modernas oferecem navegação, análise, refatoração assistida, integração com Git e depuração visual.

Curiosidade 5 — O ponto pode ser mais perigoso que o revólver

Em COBOL, o ponto encerra uma sentença e pode terminar escopos implícitos.

Código moderno costuma preferir terminadores explícitos:

       IF CONDICAO
           PERFORM ACAO
       ELSE
           PERFORM OUTRA-ACAO
       END-IF

Use períodos com consciência. Um ponto colocado no local errado pode alterar o fluxo de uma estrutura.

Easter egg número 2

Se encontrar isto:

       88 LOVELESS-ESTA-PRESENTE VALUE 'S'.

não execute:

       SET IGNORAR-FILE-STATUS TO TRUE

O vilão já entrou no programa.



21. O mapa mental definitivo

A versão simples é:

Definir dados → processar → obter resultado

A versão profissional é:

Identificar o programa
        ↓
Estabelecer contratos externos
        ↓
Descrever dados e representações
        ↓
Inicializar o estado
        ↓
Receber ou ler informações
        ↓
Validar estrutura e conteúdo
        ↓
Aplicar regras de negócio
        ↓
Alterar o estado de forma controlada
        ↓
Tratar condições e exceções
        ↓
Confirmar ou desfazer
        ↓
Gerar resultado, auditoria e código de retorno

COBOL não trabalha apenas com valores.

Trabalha com contratos e consequências.

Uma data não é somente PIC 9(8).

Precisamos saber:

  • está em AAAAMMDD?

  • zero significa ausência?

  • a data deve existir no calendário?

  • aceita data futura?

  • qual fuso horário está envolvido?

Um valor não é somente PIC S9(11)V99 COMP-3.

Precisamos saber:

  • qual moeda?

  • qual limite?

  • pode ser negativo?

  • como arredondar?

  • débito e crédito usam o mesmo sinal?

  • um estorno deve inverter ou criar nova operação?

O layout diz como ler os bytes.

A regra de negócio diz o que esses bytes significam.



Epílogo — A noite em que o mainframe não improvisou

James West encontrou o Dr. Loveless no último vagão.

Diante dele havia uma máquina gigantesca, engrenagens, luzes e um cartão perfurado com uma única instrução:

       MOVE WS-SALDO-DO-BANCO
         TO WS-CONTA-DO-LOVELESS.

— Um plano brilhante — disse Loveless. — Em poucos minutos, todo o dinheiro estará em minha conta!

Artemus Gordon examinou o programa.

— Receio que exista um problema, doutor.

— Impossível!

— O senhor não declarou corretamente o campo receptor. Também ignorou o FILE STATUS, não verificou o SQLCODE, não criou controle de duplicidade e tentou atualizar o saldo fora de uma unidade de trabalho.

James West sorriu:

— Além disso, o job terminou com COND CODE 0012.

A trilha de Richard Markowitz acelerou.

Loveless puxou uma alavanca.

O trem começou a tremer.

Igor, escondido atrás da WORKING-STORAGE, gritou:

— Eu avisei que PIC 9(3) não comportava um milhão!

O jovem padawan finalmente compreendeu.

As quatro divisões não representavam quatro pensamentos executados sequencialmente. Eram quatro maneiras de organizar o conhecimento necessário para construir o programa:

  • identidade;

  • ambiente;

  • dados;

  • procedimento.

Mas o verdadeiro “pensamento” do COBOL acontecia na interação entre:

  • registros;

  • estados;

  • condições;

  • regras;

  • operações;

  • códigos de retorno;

  • commits;

  • rollbacks.

COBOL não adivinha.

Não improvisa.

Não olha para 000001250 e conclui que provavelmente significa R$12,50.

Alguém precisa declarar a escala, o sinal, a representação e a regra.

É justamente essa disciplina que continua ensinando algo valioso depois de mais de seis décadas:

Em sistemas críticos, clareza não é enfeite colocado depois que o programa funciona. Clareza faz parte do mecanismo que impede o trem de descarrilar.

James West cuidava da ação.

Artemus Gordon compreendia os disfarces.

O JCL preparava os trilhos.

O z/OS controlava a ferrovia.

E o jovem programador COBOL, agora um pouco menos padawan, finalmente aprendeu a regra fundamental do Oeste Selvagem Digital:

Antes de sacar o WRITE, verifique o FILE STATUS. Antes de atualizar o saldo, conheça o contrato. E, quando o Dr. Loveless oferecer um GO TO para uma rotina que ninguém encontra, peça primeiro o mapa do fluxo.



 

☕ Gostou deste café?
Siga o Bellacosa Mainframe e acompanhe os próximos artigos.
SEGUIR O BLOG

Sem comentários:

Enviar um comentário

De Fã para Fã. Conteúdo não oficial produzido como homenagem, comentário, análise ou paródia. Personagens, marcas e obras eventualmente mencionados pertencem aos seus respectivos titulares.
Vagner Renato Bellacosa, IBM Champion e especialista em IBM Mainframe
IBM Z17 SYSTEM ONLINE
Sobre o autor

Vagner Renato Bellacosa

IBM Champion 2026 • Especialista em IBM Mainframe

Vagner Renato Bellacosa trabalha com IBM Mainframe desde 1988 , é IBM Champion e especialista em COBOL, CICS, Db2, z/OS e IBM Z. Compartilha experiências profissionais, conhecimento técnico, história da computação e práticas do universo mainframe para aproximar novas gerações das tecnologias que sustentam empresas, bancos e governos ao redor do mundo.

IBM Champion IBM Z COBOL CICS Db2 z/OS Mainframe desde 1988
GitHub LinkedIn
Inicializando conteúdo...