| Bellacosa Mainframe e o CALL em programas COBOL Parte I |
☕💥 A Jornada do Padawan COBOL – Parte 1
Desvendando o Universo dos CALLs no Mainframe
Ou como descobrir que chamar um programa em COBOL é quase tão importante quanto saber preparar café às 3 da manhã durante uma janela de produção
Por Vagner Bellacosa – Bellacosa Mainframe
Introdução
Todo desenvolvedor COBOL passa por um momento de iluminação.
Normalmente acontece quando ele abre um programa de produção com 30 mil linhas e encontra algo parecido com isto:
CALL 'PROG0001'
USING WS-AREA.
CALL WS-PROGRAMA
USING WS-COMMAREA.
CALL 'VALIDA01'
USING BY CONTENT WS-DATA.
CALL 'ROTINA99'
USING BY REFERENCE WS-BLOCO.
Neste momento surge a dúvida existencial:
Por que existem tantos tipos de CALL?
Qual é o mais rápido?
Qual gasta menos memória?
O que acontece dentro do z/OS?
O compilador faz mágica?
O Load Module engorda?
Como um banco executa milhões de CALLs por segundo sem explodir?
Prepare seu café.
Vamos abrir a tampa do motor do z/OS.
O que é um CALL?
Simplificando:
CALL significa pedir ajuda para outro programa.
Em vez de colocar 100 mil linhas em um único fonte, quebramos o sistema em pequenas peças reutilizáveis.
Por exemplo:
Programa principal
PROCESSA-CLIENTES
chama
VALIDA-CPF
CALCULA-JUROS
GERA-BOLETO
ENVIA-MQ
ATUALIZA-DB2
Cada um especializado.
É praticamente microserviços.
Só que inventados em 1960.
Por que IBM fez isso?
Porque memória custava uma fortuna.
Década de 70
Memória podia custar mais que um carro.
Era necessário:
reutilizar código
economizar memória
compartilhar lógica
facilitar manutenção
Assim nasceu o CALL.
Anatomia de um programa COBOL
Um programa COBOL compilado produz:
Objeto
↓
Binder
↓
Load Module
↓
PDs Loadlib
↓
Execução
Exemplo:
SYS1.LOADLIB
PROCESSA
VALIDA
JUROS
CPFCHK
O Padawan descobre o Static CALL
Exemplo
CALL 'VALIDA'
Simples.
Mas o compilador já conhece VALIDA.
Ele avisa o Binder:
Inclua VALIDA aqui.
O que acontece no LinkEdit
Binder faz:
PROCESSA
+
VALIDA
+
CPFCHK
+
JUROS
=
EXECUTÁVEL FINAL
Na memória
Antes:
PROCESSA
Depois:
PROCESSA
VALIDA
CPFCHK
JUROS
Tudo junto.
Tudo carregado.
Vantagens
Performance
Excelente.
Não precisa procurar.
Não precisa abrir bibliotecas.
Não precisa localizar módulo.
É praticamente:
BALR
Menor CPU
Menos instruções.
Menos overhead.
Menos I/O.
Desvantagens
Executável cresce.
Muito.
Exemplo
Programa principal
1 MB
Subrotinas
500 KB
Total
1,5 MB
Imagine 200 subrotinas.
Seu módulo vira um Godzilla.
Problema clássico
Padawan:
"Troquei VALIDA"
Produção:
Ainda usa antiga.
Porque precisa relinkar.
Quando usar?
Sempre que:
Programa nunca muda
Alta performance
Rotina crítica
Batch pesado
Exemplo:
Juros
Cálculo tributário
Validação interna
O Dynamic CALL aparece
Padawan evolui.
Descobre:
01 WS-PGM PIC X(8).
MOVE 'VALIDA' TO WS-PGM.
CALL WS-PGM.
O que acontece?
COBOL não sabe quem será chamado.
Somente em execução.
Busca do módulo
zOS procura:
STEPLIB
JOBLIB
LPA
LINKLIST
Exemplo
CALL CPFCHK
Sistema:
Existe?
Não.
Próximo.
Existe?
Sim.
Carrega.
Executa.
Vantagens
Flexibilidade absurda.
Pode trocar programas.
Sem recompilar.
Sem binder.
Sem relink.
Plugins COBOL
Exemplo
Cartão VISA
MOVE 'VISA0001'
Master
MOVE 'MASTER01'
PIX
MOVE 'PIX00001'
Mesmo sistema.
Rotinas diferentes.
Desvantagens
Procura programa.
Mais CPU.
Mais I/O.
Mais tempo.
Mas é lento?
Depende.
Primeira chamada.
Sim.
Segunda.
Muito rápida.
Porque pode ficar residente.
O segredo da residência
zOS é esperto.
Se programa está em memória.
Reutiliza.
Não busca novamente.
Comparação
Static
Casa própria
Dynamic
Airbnb
O executável cresce?
Static
Sim.
Dynamic
Não.
Executável principal fica pequeno.
Exemplo
Static
PROCESSA
1.5 MB
Dynamic
PROCESSA
600 KB
Subrotinas externas.
O que é mais performático?
Resposta curta.
Static.
Fim.
Mas...
O que é melhor?
Depende.
Banco.
Static.
Framework.
Dynamic.
Produtos.
Dynamic.
Rotinas financeiras.
Static.
Como o CALL funciona internamente?
Imagine isto.
Programa principal
00001000
PROCESSA
Subrotina
00025000
VALIDA
CALL executa
Guardar endereço retorno
Ir para 25000
Executar
Voltar
É praticamente um GOTO sofisticado.
Só que elegante.
Erros clássicos
S806
Programa não encontrado.
Mensagem
IEC806I
Causa
Módulo ausente.
STEPLIB errada.
Nome inválido.
S0C1
Executou lixo.
Programa corrompido.
S0C4
Endereço inválido.
Muito comum em parâmetros errados.
Como descobrir
SDSF
JESMSGLG
SYSOUT
Verificar:
STEPLIB
SYSLIB
LOADLIB
Easter Egg IBM
Muitos bancos possuem:
PROG0001
PROG0002
PROG0003
Ninguém sabe o que fazem.
Autor aposentou em 1998.
Documentação desapareceu.
Programa continua funcionando.
Todos têm medo de alterar.
É chamado:
Código Arqueológico Mainframe™
Dicas Bellacosa Mainframe
Dica 1
Static para alta frequência.
Dica 2
Dynamic para produtos.
Dica 3
Nunca fazer:
MOVE WS-USUARIO TO WS-PGM
CALL WS-PGM
Sem validar.
Pode chamar qualquer coisa.
Inclusive algo inexistente.
Dica 4
Validar sempre.
EVALUATE WS-PGM
WHEN 'CPFCHK'
WHEN 'JUROS01'
WHEN 'PIX0001'
WHEN OTHER
DISPLAY 'INVALIDO'
END-EVALUATE
Dica 5
Logar chamadas.
DISPLAY 'CALL=' WS-PGM
Ajuda muito.
A Filosofia Jedi do CALL
O Padawan iniciante pensa:
CALL serve apenas para executar outro programa.
O desenvolvedor intermediário pensa:
CALL serve para reutilizar código.
O Mestre Mainframe entende:
CALL é uma decisão arquitetural.
Ele impacta:
CPU
Memória
Tempo de resposta
Tamanho do Load Module
Facilidade de manutenção
Segurança
Escalabilidade
Observabilidade
Estratégia de deploy
E é exatamente por isso que, cinquenta anos depois, os sistemas bancários que movimentam bilhões de dólares diariamente ainda utilizam a mesma instrução COBOL que um programador digitou em um terminal verde na década de 1970:
CALL 'SUBPGM'
Na próxima etapa da jornada, o Padawan descobrirá que o verdadeiro poder do COBOL não está apenas em chamar programas, mas em como os dados atravessam a fronteira entre eles, mergulhando nos mistérios de BY REFERENCE, BY CONTENT, BY VALUE, ponteiros, Work-Storage, Local-Storage e Language Environment, onde vivem os temidos S0C4, os buffers compartilhados e os segredos que fazem alguns programas parecerem mágicos aos olhos dos desenvolvedores mais jovens.