| Bellacosa Mainframe e o caso do programa COBOL com varios pgms aninhados |
Programas COBOL Aninhados: Os Holocrons Secretos Escondidos Dentro de um Único Load Module
Quando o Padawan Descobre que um Programa COBOL Pode Conter Outros Programas COBOL em Seu Interior
Por Bellacosa Mainframe
"Nem todo programa precisa viver sozinho. Alguns mestres escondem seus aprendizes dentro do próprio templo."
Mestre Bellacosa Sysprog Jedi
Durante décadas, boa parte dos desenvolvedores COBOL aprendeu uma arquitetura bastante simples:
Programa A
↓
CALL Programa B
↓
CALL Programa C
↓
GOBACK
Fim.
Era o modelo clássico.
Cada programa em um membro.
Cada módulo separado.
Cada compilação independente.
Cada load module vivendo sua própria vida no PDS ou PDSE.
Mas então o jovem Padawan encontra algo estranho em um código legado:
IDENTIFICATION DIVISION.
PROGRAM-ID. CLIENTES.
...
IDENTIFICATION DIVISION.
PROGRAM-ID. VALIDA-CPF.
...
IDENTIFICATION DIVISION.
PROGRAM-ID. CALCULA-IDADE.
Ele arregala os olhos.
Pensa:
Mestre...
Tem três programas no mesmo fonte...
Isso é magia negra?
Não.
É COBOL.
E existe há muito tempo.
Poucos desenvolvedores modernos utilizam essa funcionalidade.
Menos ainda entendem completamente como ela funciona.
E alguns veteranos passam a carreira inteira sem escrever um único programa aninhado.
Hoje vamos abrir esse antigo holocron.
O que é um Programa Aninhado?
Em COBOL, um programa pode conter outros programas.
Algo semelhante a:
Programa principal
Programa filho A
Programa filho B
Programa filho C
Tudo dentro do mesmo fonte.
Exemplo:
PROGRAMA PRINCIPAL
PROGRAMA FILHO
PROGRAMA NETO
Hierarquia.
Muito parecido com:
Java
Inner Class
Python
Nested Function
Pascal
Nested Procedures
COBOL possui conceito semelhante.
Quando Surgiu?
Programas aninhados apareceram nas especificações modernas do COBOL.
Principalmente:
COBOL 85
Posteriormente aprimorados em:
Enterprise COBOL V3
V4
V5
V6
Hoje são totalmente suportados.
COBOL 6.5
IBM z16
IBM z17
Estrutura Básica
Exemplo.
Programa Principal
IDENTIFICATION DIVISION.
PROGRAM-ID. CLIENTE.
Programa interno
IDENTIFICATION DIVISION.
PROGRAM-ID. VALIDA.
Outro
IDENTIFICATION DIVISION.
PROGRAM-ID. CALCULA.
Tudo junto.
Exemplo Completo
Programa Pai
IDENTIFICATION DIVISION.
PROGRAM-ID. CLIENTE.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-CPF.
PIC X(11).
PROCEDURE DIVISION.
MOVE '12345678901'
TO WS-CPF
CALL 'VALIDA'
DISPLAY "FIM"
STOP RUN.
Programa Filho
IDENTIFICATION DIVISION.
PROGRAM-ID. VALIDA.
PROCEDURE DIVISION.
DISPLAY 'VALIDANDO'
EXIT PROGRAM.
Fim.
Exemplo Realista
Vamos construir.
Sistema cadastro.
Programa principal
CADASTRO
Filhos
VALIDA-CPF
VALIDA-DATA
CALCULA-IDADE
GERA-LOG
Passo 1
Programa principal
PROGRAM-ID. CADASTRO.
Passo 2
WS
01 WS-CPF.
01 WS-DATA.
01 WS-IDADE.
Passo 3
Chamar programas internos
CALL 'VALIDA-CPF'
CALL 'VALIDA-DATA'
CALL 'CALCULA-IDADE'
Passo 4
Definir programa interno
IDENTIFICATION DIVISION.
PROGRAM-ID. VALIDA-CPF.
Passo 5
Lógica
IF CPF NUMERIC
DISPLAY 'OK'
ELSE
DISPLAY 'ERRO'
Passo 6
Encerrar
EXIT PROGRAM.
Passo 7
Novo programa
PROGRAM-ID. CALCULA-IDADE.
Tudo dentro do mesmo fonte.
Como COBOL Enxerga Isso?
COBOL vê:
Programa Pai
↓
Programa Filho
↓
Programa Neto
Estrutura hierárquica.
Como é Chamado?
Nested Program
Programa Interno
Contained Program
Outer Program
Inner Program
Como Funciona na Memória?
Aqui a magia começa.
Suponha:
CADASTRO
contém
VALIDA
contém
LOG
Carregamento
LOAD MODULE
CADASTRO
VALIDA
LOG
Tudo junto.
Mesmo módulo.
Não existe:
Busca catálogo
Load library
Fetch
Link
Já está residente.
Vantagem
Muito rápida.
Visualmente
Programa separado
CALL
LOAD
FETCH
EXECUTA
Programa interno
CALL
EXECUTA
Menos overhead.
Compartilhamento de Variáveis
Esse é o recurso mais poderoso.
Programa interno pode acessar dados externos.
Exemplo
Programa pai
01 WS-NOME.
PIC X(30).
Filho
DISPLAY WS-NOME.
Sem USING.
Sem linkage.
Sem parâmetro.
Sem copiar.
Mágica?
Não.
Escopo léxico.
Exemplo
Pai
MOVE 'BELLACOSA'
TO WS-NOME
Filho
DISPLAY WS-NOME
Resultado
BELLACOSA
Por Que Isso Existe?
Reduzir acoplamento.
Criar rotinas privadas.
Encapsulamento.
Organização.
É semelhante a:
Método privado Java
Função interna Python
Classe interna
Curiosidade
Muitos programadores COBOL nem sabem que isso existe.
Porque nos bancos normalmente vemos:
CALL externo
PDS
Loadlib
Arquitetura tradicional.
Exemplo de Encapsulamento
Programa externo
Atendimento.
Internos
Valida
Log
Criptografa
Audita
Ninguém pode chamar diretamente.
Somente programa pai.
Segurança
Excelente vantagem.
Programa externo:
QUALQUER UM CHAMA
Interno
SÓ O PAI CHAMA
Maior controle.
Performance
Muito boa.
Programa já está carregado.
Sem I/O.
Sem busca.
Sem FETCH.
Pode economizar milhares de chamadas.
Existe Desvantagem?
Sim.
Grande.
Fonte gigantesco.
50000 linhas.
100000 linhas.
Difícil manutenção.
Problema do Monstro Cósmico
Exemplo
CADASTRO
VALIDA
IDADE
LOG
EMAIL
TOKEN
PIX
SMS
AUDITORIA
JSON
XML
MQ
DB2
Tudo junto.
Virou um kaiju.
Dificuldade de Reuso
Programa interno não pode ser facilmente reutilizado.
Outro sistema quer usar.
Não consegue.
Terá que copiar.
Ou refatorar.
Debug
Pode confundir.
Call stack enorme.
Nested levels.
IBM Debug Tool ajuda.
Fault Analyzer também.
Cuidados
1 Não exagerar
Máximo recomendado:
3 níveis
Pai
Filho
Neto
Mais que isso:
Dor.
2 Documentar
Quem chama quem.
3 Evitar dependência excessiva
Filho acessando 500 WS.
Ruim.
4 Preferir USING
Mesmo podendo acessar WS externa.
Melhor:
USING WS-CPF
Mais claro.
5 Não esconder regras críticas
Exemplo
Cálculo juros.
Pode dificultar auditoria.
Como Compilar?
Normal.
IGYCRCTL
Enterprise COBOL
Sem segredo.
Compilador entende estrutura.
Gera módulo único.
Programa Recursivo Aninhado
Sim.
É possível.
Filho pode ser:
RECURSIVE
Exemplo
PROGRAM-ID. FATORIAL.
RECURSIVE.
Dentro do pai.
Muito elegante.
Pouco usado.
CALL Estático Interno
Muito eficiente.
CALL 'VALIDA-CPF'
Sem carga.
Sem fetch.
Comparação
| Característica | Programa Externo | Programa Interno |
|---|---|---|
| Reuso | Excelente | Baixo |
| Segurança | Média | Alta |
| Performance | Boa | Excelente |
| Encapsulamento | Médio | Excelente |
| Debug | Fácil | Médio |
| Organização | Boa | Boa |
| Manutenção | Excelente | Pode degradar |
| Distribuição | Fácil | Limitada |
Quando Vale a Pena?
Eu costumo ensinar aos Padawans uma regra simples.
Use programas aninhados quando a rotina fizer sentido apenas dentro daquele programa principal.
Exemplos:
✅ Validação interna
✅ Máscara
✅ Auditoria
✅ Log
✅ Conversão local
✅ Parser pequeno
Evite para:
❌ Acesso DB2
❌ MQ
❌ APIs
❌ Serviços compartilhados
❌ Criptografia corporativa
❌ Regras usadas por dezenas de sistemas
O Conselho Final do Mestre Bellacosa
Programas aninhados em COBOL são quase como compartimentos secretos escondidos em um gigantesco cruzador estelar IBM Z. Eles oferecem encapsulamento, velocidade, organização e um nível de proteção natural contra reutilização indevida.
Mas, assim como qualquer artefato poderoso do universo dos Sysprogs Jedi, devem ser usados com sabedoria.
Um pequeno programa interno de validação pode tornar um sistema elegante e fácil de entender.
Dez programas internos profundamente dependentes das variáveis do pai podem transformar um módulo em um labirinto digno de um antigo datacenter abandonado, onde cada alteração provoca medo, regressões e longas noites analisando dumps.
A filosofia Bellacosa Mainframe é simples:
Aninhe comportamentos, não sistemas inteiros.
Encapsule segredos, não complexidade desnecessária.
E lembre-se sempre: se o Padawan precisar de três cafés, dois dumps e um Fault Analyzer para entender a estrutura do programa, talvez o lado sombrio da manutenção já tenha vencido.
Sem comentários:
Enviar um comentário