Translate

quinta-feira, 21 de julho de 2022

🚨 Alerta Vermelho na Enterprise: Descobrimos Que Não Era o COBOL 5... Era o 6.4!

Bellacosa Mainframe e atencao ao compilar uma nova função intrinseca


🚨 Alerta Vermelho na Enterprise: Descobrimos Que Não Era o COBOL 5... Era o 6.4!

Adendo — Em qual versão do Enterprise COBOL as funções definidas pelo usuário estão disponíveis?

Antes de avançarmos para a sala de máquinas, precisamos corrigir uma informação importante do artigo original:

As User-Defined Functions com FUNCTION-ID não foram introduzidas no Enterprise COBOL 5. Elas chegaram oficialmente ao IBM Enterprise COBOL for z/OS 6.4.

O suporte faz parte da implementação IBM de recursos definidos pelo padrão COBOL 2002. No Enterprise COBOL 6.4, o programador passou a poder criar funções próprias, declarar parâmetros, retornar um valor e invocá-las por meio de um identificador de função. (IBM)

🖖 Adendo do Capitão Kirk

Enterprise COBOL 6.4, compilação e JCL para User-Defined Functions

Intrínseca ou definida pelo usuário?

Existe uma diferença importante de terminologia.

Uma função como:

FUNCTION CURRENT-DATE
FUNCTION LENGTH
FUNCTION UPPER-CASE
FUNCTION NUMVAL

é uma função intrínseca, pois já vem implementada no compilador COBOL.

Uma função criada com:

FUNCTION-ID. CALCULA-DESCONTO.

é uma User-Defined Function, ou função definida pelo usuário.

Ela pode ser usada de maneira parecida com uma função intrínseca, mas não passa a fazer parte do compilador. Ela continua sendo um componente da aplicação que precisa ser compilado e disponibilizado corretamente.

Portanto, tecnicamente, não estamos adicionando uma nova função intrínseca ao compilador IBM. Estamos criando uma função de aplicação que pode ser invocada com uma sintaxe semelhante.


A partir de qual versão está disponível?

No ambiente IBM Z, o suporte a User-Defined Functions foi introduzido no:

IBM Enterprise COBOL for z/OS 6.4

O recurso utiliza o parágrafo:

FUNCTION-ID

e o delimitador:

END FUNCTION

A função também deve possuir obrigatoriamente uma cláusula RETURNING no cabeçalho da PROCEDURE DIVISION. (IBM)

Resumo de compatibilidade

Versão do Enterprise COBOLUser-Defined Function com FUNCTION-ID
Enterprise COBOL 4.xNão
Enterprise COBOL 5.1Não
Enterprise COBOL 5.2Não
Enterprise COBOL 6.1Não
Enterprise COBOL 6.2Não
Enterprise COBOL 6.3Não
Enterprise COBOL 6.4Sim

Em alguns ambientes, o Enterprise COBOL 6.4 pode precisar estar com os PTFs recomendados pela IBM instalados para que correções e recursos complementares, como protótipos de função, estejam disponíveis.

O suporte básico a User-Defined Functions pertence ao 6.4. Já o suporte ampliado a function prototypes, relacionado ao padrão COBOL 2014, foi fornecido por manutenção do compilador 6.4, incluindo o APAR/PTF associado ao suporte documentado pela IBM.


Programa completo para treinamento

Neste exemplo, criaremos a função:

CALCULA-IMPOSTO

Ela receberá:

  • valor da operação;

  • alíquota percentual;

E retornará:

  • valor do imposto.

A função e o programa principal serão colocados no mesmo membro-fonte para facilitar o laboratório.


Fonte COBOL completo

       IDENTIFICATION DIVISION.
       FUNCTION-ID. CALCULA-IMPOSTO.

       DATA DIVISION.
       LINKAGE SECTION.

       01  LK-VALOR             PIC S9(09)V99 COMP-3.
       01  LK-ALIQUOTA          PIC S9(03)V99 COMP-3.
       01  LK-IMPOSTO           PIC S9(09)V99 COMP-3.

       PROCEDURE DIVISION
           USING BY REFERENCE LK-VALOR
                              LK-ALIQUOTA
           RETURNING LK-IMPOSTO.

           COMPUTE LK-IMPOSTO ROUNDED =
               LK-VALOR * LK-ALIQUOTA / 100

           GOBACK.

       END FUNCTION CALCULA-IMPOSTO.


       IDENTIFICATION DIVISION.
       PROGRAM-ID. MAINPROG.

       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.

       REPOSITORY.
           FUNCTION CALCULA-IMPOSTO.

       DATA DIVISION.
       WORKING-STORAGE SECTION.

       01  WS-VALOR             PIC S9(09)V99 COMP-3
                                VALUE 1000.
       01  WS-ALIQUOTA          PIC S9(03)V99 COMP-3
                                VALUE 18.50.
       01  WS-IMPOSTO           PIC S9(09)V99 COMP-3.

       01  WS-VALOR-EDITADO     PIC ZZZ,ZZZ,ZZ9.99-.
       01  WS-ALIQ-EDITADA      PIC ZZ9.99-.
       01  WS-IMPOSTO-EDITADO   PIC ZZZ,ZZZ,ZZ9.99-.

       PROCEDURE DIVISION.

           DISPLAY "========================================"
           DISPLAY " BELLACOSA MAINFRAME - TESTE DE FUNCAO"
           DISPLAY "========================================"

           COMPUTE WS-IMPOSTO =
               CALCULA-IMPOSTO(
                   WS-VALOR
                   WS-ALIQUOTA
               )

           MOVE WS-VALOR    TO WS-VALOR-EDITADO
           MOVE WS-ALIQUOTA TO WS-ALIQ-EDITADA
           MOVE WS-IMPOSTO  TO WS-IMPOSTO-EDITADO

           DISPLAY "VALOR DA OPERACAO : " WS-VALOR-EDITADO
           DISPLAY "ALIQUOTA           : " WS-ALIQ-EDITADA "%"
           DISPLAY "IMPOSTO CALCULADO  : " WS-IMPOSTO-EDITADO

           IF WS-IMPOSTO = 185
               DISPLAY "RESULTADO CORRETO. MISSAO CUMPRIDA."
           ELSE
               DISPLAY "RESULTADO INESPERADO. CHAME O SPOCK."
           END-IF

           GOBACK.

       END PROGRAM MAINPROG.

Por que a função aparece antes do programa?

Quando a função e o programa chamador são compilados no mesmo grupo de compilação, sem o uso de um protótipo separado, a definição da função deve aparecer antes da unidade que a utiliza.

A IBM recomenda, para projetos maiores, que a função seja mantida em arquivo separado e que um protótipo seja usado no programa chamador. Entretanto, para treinamento, colocar a função e o programa no mesmo membro é uma maneira direta de compreender o mecanismo. (IBM)

Há uma consequência importante:

A primeira unidade encontrada pelo compilador pode tornar-se o ponto de entrada padrão do módulo.

Como nossa primeira unidade é CALCULA-IMPOSTO, precisamos informar ao Binder que o verdadeiro programa inicial é:

MAINPROG

Por isso usaremos:

ENTRY MAINPROG

durante a linkedição.

Sem essa instrução, a nave pode tentar decolar pela porta da engenharia em vez de sair pela ponte de comando.


JCL completo: compilar, linkeditar e executar

O exemplo abaixo apresenta um fluxo tradicional com três etapas:

  1. COBOL — compilação;

  2. LKED — linkedição;

  3. RUN — execução.

Os nomes das bibliotecas precisam ser adaptados à instalação da sua empresa.

//BLCOBUDF JOB (ACCT),'COBOL UDF',
//             CLASS=A,
//             MSGCLASS=X,
//             MSGLEVEL=(1,1),
//             NOTIFY=&SYSUID
//*
//* ==========================================================
//* BELLACOSA MAINFRAME
//* COMPILACAO DE USER-DEFINED FUNCTION - COBOL 6.4
//* ==========================================================
//*
//COBOL    EXEC PGM=IGYCRCTL,
// PARM='LIB,OBJECT,RENT,APOST,LIST,MAP,XREF,OFFSET'
//STEPLIB  DD DISP=SHR,
//            DSN=IGY.V6R4M0.SIGYCOMP
//SYSIN    DD DISP=SHR,
//            DSN=SEU.USUARIO.COBOL(CALCUDF)
//SYSLIN   DD DSN=&&OBJETO,
//            DISP=(NEW,PASS),
//            UNIT=SYSDA,
//            SPACE=(TRK,(5,5)),
//            DCB=(RECFM=FB,LRECL=80,BLKSIZE=0)
//SYSPRINT DD SYSOUT=*
//SYSOUT   DD SYSOUT=*
//SYSUT1   DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT2   DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT3   DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT4   DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT5   DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT6   DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT7   DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT8   DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT9   DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT10  DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT11  DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT12  DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT13  DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT14  DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//SYSUT15  DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//*
//LKED     EXEC PGM=IEWL,
// PARM='LIST,MAP,XREF,LET,RENT'
//SYSLIB   DD DISP=SHR,
//            DSN=CEE.SCEELKED
//         DD DISP=SHR,
//            DSN=CEE.SCEELKEX
//SYSLMOD  DD DISP=SHR,
//            DSN=SEU.USUARIO.LOAD(MAINPROG)
//SYSLIN   DD DISP=(OLD,DELETE),
//            DSN=&&OBJETO
//         DD *
  ENTRY MAINPROG
  NAME MAINPROG(R)
/*
//SYSPRINT DD SYSOUT=*
//SYSUT1   DD UNIT=SYSDA,SPACE=(CYL,(1,1))
//*
//RUN      EXEC PGM=MAINPROG,
//            COND=(0,NE)
//STEPLIB  DD DISP=SHR,
//            DSN=SEU.USUARIO.LOAD
//         DD DISP=SHR,
//            DSN=CEE.SCEERUN
//         DD DISP=SHR,
//            DSN=CEE.SCEERUN2
//SYSOUT   DD SYSOUT=*
//CEEDUMP  DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//

Bibliotecas que devem ser adaptadas

Biblioteca do compilador

No exemplo:

DSN=IGY.V6R4M0.SIGYCOMP

Esse nome varia de instalação para instalação.

Você poderá encontrar algo parecido com:

IGY.V6R4M0.SIGYCOMP
IGY640.SIGYCOMP
SYS1.IGY640.SIGYCOMP
CBC.SIGYCOMP

Não copie cegamente o nome do exemplo.

Pergunte ao sysprog, consulte um JCL COBOL já utilizado na empresa ou verifique a PROC oficial de compilação.


Biblioteca de runtime do Language Environment

Normalmente são utilizadas:

CEE.SCEERUN
CEE.SCEERUN2

Para a linkedição, podem aparecer:

CEE.SCEELKED
CEE.SCEELKEX

Os nomes e concatenações dependem da configuração do z/OS e do Language Environment.


Biblioteca de load modules

No exemplo:

DSN=SEU.USUARIO.LOAD

Ela precisa existir como uma PDS ou PDSE adequada para módulos executáveis.

Uma definição típica poderia ser criada por meio do ISPF 3.2 ou por JCL, usando atributos compatíveis com a instalação.

Em ambientes modernos, normalmente é preferível utilizar uma PDSE para a biblioteca de carga.


Versão mais curta usando uma PROC catalogada

Muitos ambientes IBM Z possuem procedures catalogadas como:

IGYWCL
IGYWCLG
IGYWC

Os nomes representam, em geral:

  • C: compile;

  • L: link-edit;

  • G: go ou execute.

Um exemplo conceitual seria:

//BLCOBUDF JOB (ACCT),'COBOL UDF',
//             CLASS=A,
//             MSGCLASS=X,
//             NOTIFY=&SYSUID
//*
//COBCLG   EXEC IGYWCLG,
//         PARM.COBOL='LIB,RENT,APOST,LIST,MAP,XREF'
//COBOL.SYSIN DD DISP=SHR,
//         DSN=SEU.USUARIO.COBOL(CALCUDF)
//LKED.SYSLMOD DD DISP=SHR,
//         DSN=SEU.USUARIO.LOAD(MAINPROG)
//LKED.SYSIN DD *
  ENTRY MAINPROG
  NAME MAINPROG(R)
/*
//GO.STEPLIB DD DISP=SHR,
//         DSN=SEU.USUARIO.LOAD
//GO.SYSOUT DD SYSOUT=*
//GO.CEEDUMP DD SYSOUT=*

Entretanto, há um alerta vermelho piscando na ponte:

As procedures catalogadas não são idênticas em todas as empresas.

A PROC pode:

  • possuir outro nome;

  • utilizar outros qualificadores;

  • não aceitar os mesmos overrides;

  • já incluir bibliotecas adicionais;

  • ter parâmetros obrigatórios;

  • possuir nomes internos diferentes para as etapas.

Antes de utilizá-la, execute no ISPF:

TSO ISRDDN

ou consulte os JCLs-padrão da instalação.

Também é possível procurar a PROC nas bibliotecas de procedures, normalmente concatenadas em JES2 PROCLIB.


Entendendo o REPOSITORY

O programa chamador possui:

       ENVIRONMENT DIVISION.
       CONFIGURATION SECTION.

       REPOSITORY.
           FUNCTION CALCULA-IMPOSTO.

Isso informa ao compilador que CALCULA-IMPOSTO é uma função conhecida pelo programa.

Com essa declaração, podemos escrever:

COMPUTE WS-IMPOSTO =
    CALCULA-IMPOSTO(WS-VALOR WS-ALIQUOTA)

A IBM documenta que a declaração no REPOSITORY permite invocar a função sem repetir a palavra reservada FUNCTION. (IBM)

Dependendo da forma de declaração e do contexto, uma referência explícita também pode assumir a forma:

FUNCTION CALCULA-IMPOSTO(
    WS-VALOR
    WS-ALIQUOTA
)

No exemplo apresentado, utilizamos o REPOSITORY para deixar a expressão mais limpa.


Saída esperada no SYSOUT

O resultado deverá ser semelhante a:

========================================
 BELLACOSA MAINFRAME - TESTE DE FUNCAO
========================================
VALOR DA OPERACAO :       1,000.00
ALIQUOTA           :          18.50%
IMPOSTO CALCULADO  :         185.00
RESULTADO CORRETO. MISSAO CUMPRIDA.

Return codes esperados

Em uma missão bem-sucedida, procure:

COBOL RC=0000
LKED  RC=0000
RUN   RC=0000

Dependendo das opções e dos avisos encontrados, a compilação pode terminar com:

RC=0004

Isso significa que houve advertências, não necessariamente um erro fatal. Mesmo assim, analise todas as mensagens.

Interpretação tradicional

Return codeSignificado geral
0000Processamento concluído sem diagnóstico relevante
0004Advertências
0008Erros que normalmente impedem o uso seguro
0012Erros graves
0016Erro muito grave ou falha de processamento

A interpretação exata deve considerar as mensagens emitidas pelo compilador e pelo Binder.


Erro: FUNCTION-ID não reconhecido

Caso o compilador apresente mensagens indicando que:

FUNCTION-ID

não é reconhecido, as causas mais prováveis são:

  1. O JCL está chamando um compilador anterior ao Enterprise COBOL 6.4.

  2. A STEPLIB aponta para outra versão do compilador.

  3. A PROC catalogada ainda referencia COBOL 6.2 ou 6.3.

  4. O produto 6.4 está instalado, mas não é a versão selecionada pelo JCL.

  5. O fonte está sendo processado por uma ferramenta intermediária incompatível.

  6. O editor ou analisador local conhece uma gramática COBOL antiga.

Verifique no listing de compilação a identificação da versão.

Você deverá encontrar uma indicação semelhante a:

IBM Enterprise COBOL for z/OS 6.4

Não confie apenas no nome da PROC.

Uma PROC chamada COBOL64 pode ter sido alterada, enquanto uma PROC chamada apenas COBOL pode estar usando o compilador mais recente.

Como Spock diria:

“O nome de um membro não constitui evidência lógica do conteúdo de sua STEPLIB.”


Erro de linkedição: ponto de entrada incorreto

Como a função aparece primeiro no grupo de compilação, o Binder pode selecionar a entrada errada caso não seja informado explicitamente.

Por isso usamos:

ENTRY MAINPROG

Para compilações AMODE 31 com LP(32), a IBM orienta que seja fornecida uma instrução ENTRY para o programa principal quando uma compilação contém funções e programas e a função aparece antes do programa. (IBM)

Se o ENTRY estiver ausente ou incorreto, poderão ocorrer:

  • início da execução no componente errado;

  • erro de entrada não encontrada;

  • comportamento imprevisível;

  • falha de linkedição;

  • abend durante a inicialização.


Não use CALL para invocar a função

Uma User-Defined Function deve ser utilizada como função:

COMPUTE WS-IMPOSTO =
    CALCULA-IMPOSTO(WS-VALOR WS-ALIQUOTA)

Não faça:

CALL "CALCULA-IMPOSTO"

A documentação IBM alerta que invocar uma User-Defined Function por meio da instrução CALL produz comportamento imprevisível. (IBM)

Se o componente foi projetado para ser chamado com CALL, escreva-o como subprograma com:

PROGRAM-ID

Se foi projetado como função, escreva-o com:

FUNCTION-ID

Não misture as duas interfaces.


ENTRY-INTERFACE

O FUNCTION-ID também pode controlar a forma de geração e invocação por meio de ENTRY-INTERFACE.

As User-Defined Functions podem ser estruturadas para diferentes formas de ligação, incluindo:

  • estática;

  • dinâmica;

  • DLL.

O padrão documentado para ENTRY-INTERFACE é STATIC. (IBM)

Para o primeiro laboratório, mantenha a configuração padrão.

A invocação estática reduz a quantidade de peças móveis e facilita:

  • compilação;

  • linkedição;

  • testes;

  • diagnóstico;

  • implantação inicial.

Só avance para modelos dinâmicos depois de dominar:

  • protótipos;

  • external names;

  • binder;

  • load libraries;

  • Language Environment;

  • convenções de interface.


Cuidado com BY REFERENCE

No exemplo, os parâmetros são recebidos com:

USING BY REFERENCE

Isso significa que a função recebe referências aos itens do programa chamador.

Embora uma boa função de cálculo não deva modificar seus argumentos, o uso de referência exige disciplina.

Evite comandos como:

MOVE ZERO TO LK-VALOR

Isso poderia alterar dados pertencentes ao chamador, dependendo da interface e do argumento utilizado.

Para obter um comportamento semelhante ao BY CONTENT, o Enterprise COBOL 6.4 disponibiliza a função CONTENT-OF. Nesse modelo, a definição formal continua usando BY REFERENCE, mas o argumento é protegido por uma cópia temporária criada na invocação. (IBM)

Exemplo conceitual:

REPOSITORY.
    FUNCTION CONTENT-OF INTRINSIC
    FUNCTION CALCULA-IMPOSTO.

Invocação:

COMPUTE WS-IMPOSTO =
    CALCULA-IMPOSTO(
        CONTENT-OF(WS-VALOR)
        CONTENT-OF(WS-ALIQUOTA)
    )

Isso é especialmente útil quando você deseja deixar claro que a função não deve alterar os argumentos fornecidos.


Dicas de compilação do Scotty

1. Comece sem otimização agressiva

Durante os primeiros testes, prefira opções que facilitem diagnóstico.

Por exemplo:

LIST,MAP,XREF,OFFSET

Depois que o programa estiver estabilizado, avalie as opções de otimização adotadas pela instalação.


2. Use TEST em ambiente de desenvolvimento

Caso a empresa utilize IBM Debug for z/OS, as opções apropriadas de depuração podem ajudar a acompanhar:

  • entrada na função;

  • conteúdo dos parâmetros;

  • valor retornado;

  • fluxo de execução.

As opções exatas dependem das ferramentas e padrões locais.


3. Verifique o listing

No listing de compilação, confirme:

  • versão do compilador;

  • opções efetivamente utilizadas;

  • definição da função;

  • referências à função;

  • mensagens de severidade;

  • offsets;

  • informações do objeto gerado.


4. Não esconda erros com COND inadequado

No laboratório, a execução deve ocorrer apenas quando as etapas anteriores forem bem-sucedidas.

Uma alternativa moderna é usar:

//RUN EXEC PGM=MAINPROG,
// IF (COBOL.RC LE 4 AND LKED.RC LE 4) THEN

ou estruturas IF/THEN/ELSE/ENDIF do JCL, conforme o padrão da empresa.

Evite executar um módulo quando a compilação terminou com erro grave.


5. Teste limites numéricos

Não teste apenas:

1000 × 18,5%

Teste também:

  • valor zero;

  • alíquota zero;

  • valor negativo, se permitido;

  • alíquota com muitas casas;

  • valor máximo do PIC;

  • resultado próximo de overflow;

  • arredondamento;

  • sinal;

  • casas decimais;

  • truncamento.


Checklist de lançamento da função

Antes de Kirk autorizar a partida, confirme:

[ ] Enterprise COBOL 6.4 está realmente sendo utilizado
[ ] FUNCTION-ID foi reconhecido
[ ] A função possui RETURNING
[ ] A função termina com END FUNCTION
[ ] O programa termina com END PROGRAM
[ ] A função aparece antes do chamador no mesmo grupo
[ ] O REPOSITORY declara a função
[ ] ENTRY MAINPROG foi fornecido ao Binder
[ ] A load library existe
[ ] CEE.SCEERUN está disponível na execução
[ ] Os parâmetros possuem formatos compatíveis
[ ] O valor de retorno cabe no campo receptor
[ ] Não existe CALL para a User-Defined Function
[ ] O listing foi revisado
[ ] Os testes de limite foram executados

Diário de bordo do Capitão Kirk

Criar uma função definida pelo usuário no Enterprise COBOL 6.4 não é apenas aprender uma nova sintaxe.

É aprender que o COBOL também evolui.

A linguagem que processava cartões perfurados agora pode organizar regras em funções reutilizáveis, oferecer interfaces mais expressivas e aproximar sistemas críticos de práticas modernas de engenharia de software.

Mas o Padawan precisa compreender toda a cadeia:

FONTE
  ↓
COMPILADOR COBOL 6.4
  ↓
OBJETO
  ↓
BINDER
  ↓
LOAD MODULE
  ↓
LANGUAGE ENVIRONMENT
  ↓
EXECUÇÃO

A função não “se instala” como um plugin.

Ela é:

  1. escrita;

  2. compilada;

  3. linkedita;

  4. armazenada em uma load library;

  5. disponibilizada ao programa que a utilizará.

Na ponte da Enterprise, Kirk conclui:

“Não basta descobrir um novo recurso. É preciso saber como colocá-lo em produção sem explodir os motores.”

Spock examina o listing e responde:

“Compilação RC zero, linkedição RC zero e resultado igual a 185. A missão é logicamente satisfatória.”

E Scotty, olhando para o Binder, acrescenta:

“Desde que ninguém esqueça o ENTRY MAINPROG, capitão.”

Esse pequeno detalhe resume uma grande verdade do mundo mainframe:

O código pode estar perfeito, mas a missão só termina quando compilação, linkedição e execução trabalham como uma única tripulação.

 

quarta-feira, 20 de julho de 2022

Criando Sua Própria Função Intrínseca no COBOL

 

Bellacosa Mainframe crie sua propria função intrinseca no Cobol Mainframe

☕ Um Café no Bellacosa Mainframe

Criando Sua Própria Função Intrínseca no COBOL

O Guia do Programador COBOL Padawan para Expandir os Poderes da Linguagem com a Ajuda do Capitão Kirk

"O universo não se expande porque alguém pediu permissão. Ele se expande porque alguém teve coragem de explorar o desconhecido."

— Capitão James T. Kirk (adaptado para Bellacosa Mainframe)


Introdução — "Mas... eu posso criar uma nova FUNCTION no COBOL?"

Essa é uma das perguntas que quase nenhum curso responde.

Durante décadas, programadores COBOL aprenderam algo parecido com isto:

  • FUNCTION CURRENT-DATE

  • FUNCTION UPPER-CASE

  • FUNCTION LOWER-CASE

  • FUNCTION LENGTH

  • FUNCTION RANDOM

E a conclusão natural era:

"Essas funções fazem parte da linguagem. Não posso criar outras."

Durante muitos anos isso realmente era verdade.

Mas a IBM resolveu mudar isso.

Hoje, no Enterprise COBOL moderno, você pode criar suas próprias funções, reutilizáveis exatamente como uma FUNCTION nativa da linguagem.

É quase como ensinar novos truques ao compilador.

Se você já trabalhou com:

  • Java (methods)

  • C (functions)

  • Python (def)

  • C# (methods)

vai perceber que finalmente o COBOL ganhou algo semelhante.

E a melhor parte?

Isso continua extremamente eficiente para ambientes bancários.

Hoje vamos descobrir como.

E, como sempre, o Capitão Kirk nos acompanhará nessa missão.


A ponte da Enterprise

Imagine a USS Enterprise.

Cada oficial possui uma especialidade.

Spock calcula.

Scotty cuida do motor.

McCoy resolve problemas médicos.

Kirk apenas chama quem precisa.

Ele não faz tudo.

Ele reutiliza especialistas.

Uma User-Defined Function faz exatamente isso.

Você cria um especialista.

Depois qualquer programa COBOL pode chamá-lo.


Antes disso...

Durante mais de 50 anos havia apenas dois caminhos.

Opção 1

Escrever código repetido.

CALCULA-JUROS.

CALCULA-DESCONTO.

CALCULA-IDADE.

Copiado dezenas de vezes.


Opção 2

Criar um subprograma

CALL "JUROS"

Funciona.

Mas possui custo.

Existe:

  • parameter list

  • linkage

  • transferência de controle

  • convenções de chamada

Embora eficiente, ainda existe overhead.


As User Defined Functions diminuem bastante esse problema.


O que é uma User-Defined Function?

É uma função escrita pelo próprio programador.

Ela recebe parâmetros.

Executa lógica.

Retorna um único valor.

Exemplo imaginário:

FUNCTION CALCULA-CPF()

ou

FUNCTION REMOVE-ESPACOS()

ou

FUNCTION SOMA-IMPOSTOS()

Ela parece uma função da linguagem.

Mas foi você quem escreveu.


Desde quando isso existe?

No mundo IBM Mainframe, o suporte chegou com o IBM Enterprise COBOL 5 (introduzido em 2013), quando a linguagem passou a incorporar recursos modernos alinhados aos padrões mais recentes do COBOL. As capacidades foram ampliadas e refinadas nas versões 6.1, 6.2, 6.3, 6.4 e 6.5, que hoje são as mais encontradas em ambientes z/OS corporativos.

Na prática, é nas versões Enterprise COBOL 5.x e, principalmente, 6.x que esse recurso se tornou realmente utilizável em projetos modernos.


Precisa instalar alguma coisa?

Boa notícia.

Não.

Nada.

Se o compilador suporta User-Defined Functions, elas já fazem parte do compilador.

Você apenas compila normalmente.

Não existe:

  • DLL

  • Plugin

  • Biblioteca externa


Como funciona?

A arquitetura é simples.

Programa A

↓

FUNCTION MINHA-FUNCTION()

↓

User Defined Function

↓

Retorna resultado

Muito parecido com isto:

resultado =
FUNCTION JUROS(valor)


Estrutura geral

Ela lembra um programa COBOL.

IDENTIFICATION DIVISION

FUNCTION-ID.

ENVIRONMENT DIVISION.

DATA DIVISION.

PROCEDURE DIVISION.

END FUNCTION.

Observe algo curioso.

Não usamos

PROGRAM-ID

Usamos

FUNCTION-ID

Esse é o detalhe que transforma um programa em uma função.


Exemplo 1

Dobrando um número

IDENTIFICATION DIVISION.
FUNCTION-ID. DOBRO.

DATA DIVISION.

LINKAGE SECTION.

01 L-VALOR PIC S9(9) COMP-5.

01 L-RETORNO PIC S9(9) COMP-5.

PROCEDURE DIVISION USING L-VALOR
                   RETURNING L-RETORNO.

    COMPUTE L-RETORNO = L-VALOR * 2

    GOBACK.

END FUNCTION DOBRO.

Bonito.

Limpo.

Pequeno.


Agora o programa principal.

DISPLAY FUNCTION DOBRO(15)

Saída

30

Muito elegante.


Exemplo 2

Maior entre dois números

FUNCTION MAIOR(A,B)

Dentro:

IF A > B
   MOVE A TO RETORNO
ELSE
   MOVE B TO RETORNO
END-IF

Depois:

DISPLAY FUNCTION MAIOR(25 19)

Resultado

25


Exemplo 3

Calcular idade

FUNCTION IDADE(DATA-NASCIMENTO)

Internamente:

CURRENT-DATE

Subtrai

Retorna idade.

Depois:

DISPLAY FUNCTION IDADE(19980412)

Muito mais legível.


Onde declarar parâmetros?

Na

LINKAGE SECTION

Exemplo

01 PARAM1.

01 PARAM2.

Depois

PROCEDURE DIVISION USING
PARAM1
PARAM2
RETURNING RESULTADO

Muito parecido com um subprograma.


Como chamar?

COMPUTE WS-TOTAL =
FUNCTION JUROS(1000 15)

Ou

MOVE FUNCTION DOBRO(5)
TO WS-VALOR

Ou

DISPLAY FUNCTION TEXTO()


Posso chamar outras FUNCTIONS?

Sim.

Inclusive funções intrínsecas.

FUNCTION UPPER-CASE()

Dentro da sua função.

Exemplo

FUNCTION UPPER-CASE(cliente)

Retorna

JOÃO


Posso chamar um CALL?

Também.

CALL "ROTINA"

Nada impede.

Mas cuidado.

Funções devem ser pequenas.


O Capitão Kirk explica

Imagine que Kirk pede um café.

Ele não desmonta o replicador.

Ele apenas diz:

CAFÉ()

O replicador faz todo o trabalho.

Isso é encapsulamento.


Performance

Excelente.

Muito melhor do que copiar código.

Muito melhor para manutenção.

Além disso:

✔ reutilização

✔ cache de instruções

✔ otimização do compilador

✔ menor duplicação


Um detalhe importante

Funções devem retornar UM único valor.

Não dez.

Se precisa retornar muitas estruturas:

Use

CALL

Não FUNCTION.


Posso acessar arquivos VSAM?

Tecnicamente pode.

Mas...

Não deveria.

Funções devem ser previsíveis.


Boa função:

CALCULA

Ruim:

ABRE VSAM

FAZ I/O

ATUALIZA DB2

ENVIA MQ


O perigo dos efeitos colaterais

Imagine:

FUNCTION SALDO()

Você espera apenas consultar.

Mas internamente:

UPDATE DB2

Isso é perigoso.

Uma função deve produzir sempre o mesmo resultado para a mesma entrada, sempre que possível.


Erros comuns

1 Repetir lógica

Ao invés de:

FUNCTION IMPOSTO()

o programador copia:

COMPUTE...

100 vezes.


2 Fazer função enorme

Ruim

900 linhas

Boa

20

40

60 linhas


3 Muitos parâmetros

FUNCTION CALCULA(
A
B
C
D
E
F
G
H)

Já virou um monstro.


4 Fazer I/O

Evite.


5 Alterar estado global

Funções devem ser independentes.


Truques interessantes

Criar biblioteca matemática

FUNCTION MEDIA()

FUNCTION DESVIO()

FUNCTION MEDIANA()


Biblioteca financeira

JUROS

IOF

IR

TAXA


Biblioteca bancária

VALIDA-CPF

VALIDA-CNPJ

MOD11

DIGITO


Biblioteca texto

REMOVE-ESPACOS

NORMALIZA

CAPITALIZA


Organização recomendada

COPYBOOKS

FUNCTIONS

SUBPROGRAMAS

PROGRAMAS

Cada função em seu próprio membro.

Muito semelhante à organização de uma biblioteca reutilizável.


Boas práticas

✔ Nomeie funções de forma descritiva (CALCULA-JUROS, VALIDA-CPF, NORMALIZA-NOME).

✔ Mantenha apenas uma responsabilidade por função.

✔ Evite acessar arquivos, filas MQ ou banco de dados dentro de funções de cálculo.

✔ Prefira funções determinísticas: mesma entrada, mesma saída.

✔ Documente parâmetros e tipo de retorno.

✔ Teste cada função de forma isolada antes de utilizá-la em produção.

✔ Centralize funções reutilizáveis em bibliotecas compartilhadas pela equipe.

✔ Utilize compilação otimizada nas versões atuais do Enterprise COBOL para aproveitar as melhorias do compilador.


Quando usar FUNCTION e quando usar CALL?

SituaçãoFUNCTIONCALL
Cálculos rápidos✅ Excelente✔ Possível
Manipulação de texto✅ Excelente✔ Possível
Validação de CPF/CNPJ✅ Ideal✔ Possível
Retornar um único valor✅ Melhor escolha✔ Possível
Atualizar Db2❌ Evite✅ Recomendado
Processar VSAM❌ Evite✅ Recomendado
Enviar mensagens MQ❌ Evite✅ Recomendado
Processamento complexo com vários retornos❌ Não indicado✅ Ideal

Um exemplo prático: função para calcular desconto

Imagine uma empresa que aplica um desconto de 10% sobre qualquer valor informado. Em vez de repetir o cálculo em dezenas de programas, criamos uma função reutilizável.

Função

IDENTIFICATION DIVISION.
FUNCTION-ID. CALC-DESCONTO.

DATA DIVISION.

LINKAGE SECTION.
01 LK-VALOR     PIC S9(7)V99 COMP-3.
01 LK-RETORNO   PIC S9(7)V99 COMP-3.

PROCEDURE DIVISION
    USING LK-VALOR
    RETURNING LK-RETORNO.

    COMPUTE LK-RETORNO =
        LK-VALOR * 0.90

    GOBACK.

END FUNCTION CALC-DESCONTO.

Programa chamador

IDENTIFICATION DIVISION.
PROGRAM-ID. TESTE.

DATA DIVISION.
WORKING-STORAGE SECTION.

01 WS-VALOR     PIC S9(7)V99 VALUE 1000.
01 WS-FINAL     PIC S9(7)V99.

PROCEDURE DIVISION.

    MOVE FUNCTION CALC-DESCONTO(WS-VALOR)
        TO WS-FINAL

    DISPLAY "Valor original : " WS-VALOR
    DISPLAY "Valor final    : " WS-FINAL

    STOP RUN.

Saída esperada:

Valor original : 1000.00
Valor final    :  900.00

Perceba como o programa principal permanece limpo. Toda a regra de negócio fica encapsulada em um único lugar. Se amanhã o desconto passar para 12%, basta recompilar a função.


A visão do Capitão Kirk

No final da missão, Kirk reúne sua tripulação na ponte da Enterprise.

Spock observa:

"Capitão, seria lógico repetir o mesmo algoritmo em 147 programas?"

Kirk sorri.

"Claro que não, Spock. Criamos uma função, compartilhamos conhecimento e seguimos explorando."

Scotty complementa:

"Quanto menos motores improvisados, menos explosões na sala de máquinas."

McCoy, olhando para um enorme programa COBOL cheio de código duplicado, comenta:

"Ele está vivo... mas não por muito tempo."

Essa é a verdadeira filosofia das User-Defined Functions: transformar conhecimento reutilizável em componentes pequenos, claros e confiáveis.

Cuidados e atenção 

Como compilar e ajustar sua função intrinseca no Cobol 6.4

https://eljefemidnightlunch.blogspot.com/2022/07/alerta-vermelho-na-enterprise.html

O que são Funções Intrincsecas no Cobol

https://eljefemidnightlunch.blogspot.com/2022/09/funcoes-intrinsecas-no-enterprise-cobol.html



Conclusão — Seu próximo passo como Padawan COBOL

As User-Defined Functions representam uma das evoluções mais elegantes do COBOL moderno. Elas aproximam a linguagem das práticas de engenharia de software utilizadas em linguagens contemporâneas, sem abrir mão da robustez que tornou o COBOL o alicerce de bancos, seguradoras e grandes empresas por décadas.

Para um Padawan COBOL, dominar esse recurso significa deixar de escrever programas monolíticos e começar a construir bibliotecas reutilizáveis de regras de negócio. Isso reduz duplicação de código, facilita testes, melhora a manutenção e torna o desenvolvimento muito mais organizado.

No universo Bellacosa Mainframe, criar uma nova função é como adicionar um novo oficial especializado à tripulação da USS Enterprise. Cada função tem uma missão específica, executa seu trabalho com excelência e permite que o programa principal permaneça simples, elegante e focado em coordenar a missão.

Porque, no fim das contas, os melhores sistemas corporativos não são aqueles que possuem mais linhas de código, mas aqueles em que cada componente conhece exatamente seu papel — assim como cada oficial da Frota Estelar conhece sua estação na ponte de comando.


terça-feira, 19 de julho de 2022

DB2 Utilities sem Mistérios : O Guia do Programador COBOL Padawan para Entender REBUILD, REORG, COPY, RUNSTATS e o JCL por Trás da Tela Verde

 

Bellacosa Mainframe e o db2 utilies sem misterios

☕ Um Café no Bellacosa Mainframe

DB2 Utilities sem Mistérios 

O Guia do Programador COBOL Padawan para Entender REBUILD, REORG, COPY, RUNSTATS e o JCL por Trás da Tela Verde

Imagine a seguinte cena.

Você está diante de um terminal 3270. A tela preta parece silenciosa, quase imóvel. No alto aparece a inscrição:

DB2 UTILITIES

À direita, surge o nome do subsistema:

SSID: DB9G

No centro da tela, alguns campos aparentemente simples:

FUNCTION  ==> EDITJCL
JOB ID    ==> TEMP
UTILITY   ==> REBUILD
RESTART   ==> NO
LISTDEF   ==> NO
TEMPLATE  ==> NO

Para um programador COBOL Padawan, essa tela pode parecer apenas mais um formulário antigo do ISPF. Talvez algo criado em uma era na qual os monitores eram pesados, os teclados faziam barulho e os programadores carregavam manuais do tamanho de listas telefônicas.

Mas não se deixe enganar pela simplicidade visual.

Essa tela é como o painel de controle de uma enorme estação orbital. Por trás de poucos campos existe um conjunto de programas capazes de copiar, reorganizar, validar, reconstruir, descarregar e recuperar bancos de dados que podem armazenar bilhões de registros.

É aqui que o Db2 deixa de ser apenas o lugar onde seu programa COBOL executa um SELECT ou um UPDATE e revela sua verdadeira natureza: um sistema vivo que precisa de manutenção, estatísticas, cópias de segurança, reorganização e monitoramento constante.

Hoje vamos abrir esse painel, desmontar seus componentes e entender a engenharia escondida por trás de cada opção.


Bellacosa Mainframe e a tela do db2 para comandos de administracao

1. A tela não executa a mágica: ela gera as ordens

O primeiro conceito importante é compreender que o painel do Db2 Utilities não é, por si só, o utilitário.

Ele funciona como uma interface de preparação.

O fluxo normalmente é:

Usuário
   |
   v
Painel ISPF
   |
   v
Parâmetros informados
   |
   v
Geração de JCL
   |
   v
Submissão ao JES2
   |
   v
Execução do utilitário Db2
   |
   v
Mensagens no spool

O painel pergunta:

  • Qual utilitário deseja executar?

  • Qual subsistema Db2 será utilizado?

  • Onde estão os comandos do utilitário?

  • Deseja apenas editar o JCL ou submetê-lo?

  • A execução será nova ou continuará uma execução anterior?

  • Serão utilizadas listas automáticas?

  • Serão utilizados templates para datasets?

Com essas respostas, ele monta o JCL necessário.

Essa filosofia é muito comum no mainframe: a interface não tenta esconder completamente o que está acontecendo. Ela ajuda, orienta e gera o material operacional, mas o profissional ainda consegue examinar o JCL, alterar parâmetros e analisar o resultado.


2. SSID: escolhendo o universo Db2 correto

Na imagem temos:

SSID: DB9G

SSID significa:

Subsystem Identifier

É o identificador do subsistema Db2.

Uma instalação z/OS pode executar vários subsistemas Db2. Cada um representa um ambiente independente, com seu próprio catálogo, logs, buffer pools, planos, packages e objetos.

Exemplos:

DB2D  - Desenvolvimento
DB2T  - Testes
DB2H  - Homologação
DB2P  - Produção
DB9G  - Ambiente de laboratório ou treinamento

O nome não possui uma regra universal. Cada organização define seu padrão.

Essa escolha é crítica.

Executar um REBUILD INDEX em desenvolvimento é uma coisa.

Executar no subsistema de produção, durante o horário de pico, é outra completamente diferente.

Um erro no SSID pode transformar uma atividade rotineira em um incidente.

Easter egg operacional

Muitos profissionais experientes confirmam o SSID várias vezes antes de submeter um utilitário. Não é paranoia. É memória histórica.

Um DBA pode ter duas sessões abertas:

Sessão 1: DB2D
Sessão 2: DB2P

As telas são praticamente idênticas.

Um comando correto no ambiente errado continua sendo um comando errado.


3. FUNCTION: o que fazer com o JCL

Na tela aparece:

FUNCTION ==> EDITJCL

Esse campo define o destino da operação.

As opções normalmente incluem:

SUBMIT
EDITJCL
DISPLAY
TERMINATE

3.1 EDITJCL

A opção EDITJCL gera o JCL e abre o resultado no editor ISPF.

É uma das opções mais seguras, pois permite revisar tudo antes da execução.

Você pode conferir:

  • JOBNAME;

  • CLASS;

  • MSGCLASS;

  • subsistema Db2;

  • datasets;

  • comandos SYSIN;

  • parâmetros de SORT;

  • nomes de tablespaces e índices;

  • opções de paralelismo;

  • espaço temporário;

  • instruções de restart.

Fluxo:

Painel
   |
   v
Geração do JCL
   |
   v
ISPF Edit
   |
   v
Revisão humana
   |
   v
SUBMIT

Para produção, essa revisão é importantíssima.

3.2 SUBMIT

A opção SUBMIT gera o JCL e o envia diretamente ao JES2.

É prática e rápida, mas elimina a oportunidade de revisão manual.

Pode ser adequada em ambientes controlados, especialmente quando:

  • o procedimento já foi testado;

  • o JCL segue um padrão;

  • os datasets são gerados por template;

  • o objeto já foi validado;

  • o usuário conhece o impacto da operação.

Para um Padawan, EDITJCL é a escolha mais educativa.

3.3 DISPLAY

DISPLAY permite consultar utilitários em execução ou pendentes.

Um utilitário Db2 mantém informações sobre seu estado.

Por exemplo:

UTILID = REORGP01
PHASE  = RELOAD
STATUS = ACTIVE

Isso permite saber:

  • qual utilitário está executando;

  • qual objeto está sendo processado;

  • em qual fase está;

  • se está parado;

  • se aguarda algum recurso;

  • se pode ser reiniciado.

3.4 TERMINATE

TERMINATE encerra o estado registrado de uma utility.

Mas cuidado: terminar uma utility não significa simplesmente “cancelar um job”.

Existe uma diferença entre:

CANCEL do job no JES2

e:

TERM UTILITY no Db2

Quando um job é cancelado, o Db2 pode manter informações de restart.

A utility continua registrada como incompleta.

O comando de término informa ao Db2 que aquela execução não será retomada.

Essa operação deve ser feita com conhecimento, porque pode eliminar a possibilidade de restart daquela utility.


4. JOB ID: identificando a missão

Na imagem:

JOB ID ==> TEMP

Esse campo serve como identificador para a geração ou para a execução.

Dependendo do painel e do modelo utilizado, ele pode participar da criação de:

  • JOBNAME;

  • utility ID;

  • nomes temporários;

  • membros;

  • datasets de trabalho.

Exemplos mais descritivos:

REBLIDX
REORGCAD
COPYFIN
RUNSTPRD
LOADCLI

Em produção, nomes claros ajudam muito.

Compare:

TEMP

com:

RBCUST01

O segundo nome já sugere:

RB = Rebuild
CUST = Customer
01 = Execução ou partição

Quando dezenas de jobs aparecem no SDSF, uma boa nomenclatura reduz confusão.


5. UTILITY: escolhendo a ferramenta certa

Na imagem, a opção selecionada é:

UTILITY ==> REBUILD

O painel lista vários utilitários:

CHECK DATA
CHECK INDEX
CHECK LOB
COPY
DIAGNOSE
LOAD
MERGE
MODIFY
QUIESCE
REBUILD
RECOVER
REORG INDEX
REORG LOB
REORG TABLESPACE
REPORT
REPAIR
RUNSTATS
STOSPACE
UNLOAD

Cada um resolve um problema diferente.

Vamos entender os principais.


6. REBUILD INDEX: reconstruindo a árvore

Um índice Db2 normalmente utiliza uma estrutura semelhante a uma árvore B+.

Ele permite localizar rapidamente linhas sem ler toda a tabela.

Imagine uma tabela:

TB_CLIENTE

com as colunas:

ID_CLIENTE
CPF
NOME
CIDADE
SALDO

E um índice:

IX_CLIENTE_CPF

Ao executar:

SELECT NOME
  FROM TB_CLIENTE
 WHERE CPF = '12345678900';

o Db2 pode consultar o índice e localizar diretamente a página correspondente.

Com o tempo, porém, o índice sofre alterações:

  • inserções;

  • exclusões;

  • splits de páginas;

  • movimentação de chaves;

  • páginas parcialmente vazias;

  • perda de organização;

  • inconsistência após determinadas falhas.

O REBUILD INDEX recria a estrutura.

Fluxo conceitual

Leitura dos dados ou das chaves
          |
          v
Ordenação das chaves
          |
          v
Criação de nova estrutura
          |
          v
Gravação das páginas do índice
          |
          v
Validação e disponibilização

Exemplo de comando Db2

REBUILD INDEX
  (DBFIN.IXCLIENT)
  SHRLEVEL REFERENCE
  SORTDEVT SYSDA
  SORTNUM 8
  STATISTICS

Explicando cada linha

REBUILD INDEX

Solicita a reconstrução de um índice.

(DBFIN.IXCLIENT)

Identifica o indexspace ou objeto que será reconstruído. A sintaxe exata pode variar conforme o tipo de objeto e a convenção utilizada.

SHRLEVEL REFERENCE

Permite determinado nível de acesso concorrente, geralmente leitura, enquanto restringe alterações durante partes da execução.

SORTDEVT SYSDA

Indica o tipo genérico de dispositivo a ser utilizado para arquivos temporários de sort.

SORTNUM 8

Solicita uma quantidade de datasets de trabalho para ordenação.

STATISTICS

Pede a coleta de estatísticas durante ou após o processo, quando suportado pela utility e configuração.


7. Exemplo completo de JCL para REBUILD INDEX

//RBIDX01  JOB (ACCT),'REBUILD INDEX',
//             CLASS=A,
//             MSGCLASS=X,
//             NOTIFY=&SYSUID
//*
//STEP01   EXEC PGM=DSNUTILB,
//             REGION=0M,
//             PARM='DB9G,RBIDX01'
//STEPLIB   DD DISP=SHR,DSN=DB2.V13.SDSNLOAD
//SYSPRINT  DD SYSOUT=*
//UTPRINT   DD SYSOUT=*
//SYSUDUMP  DD SYSOUT=*
//SORTDEVT  DD DUMMY
//SYSIN     DD *
  REBUILD INDEX
    (DBFIN.IXCLIENT)
    SHRLEVEL REFERENCE
    SORTDEVT SYSDA
    SORTNUM 8
/*
//

Agora vamos desmontar esse JCL como um engenheiro desmontaria um processador antigo.


7.1 JOB statement

//RBIDX01 JOB (ACCT),'REBUILD INDEX',

O nome do job é:

RBIDX01

Ele será exibido no JES2 e no SDSF.

(ACCT)

Representa informações contábeis ou administrativas. O formato depende da instalação.

'REBUILD INDEX'

É uma descrição humana da execução.


7.2 CLASS

//            CLASS=A,

A classe determina como o JES2 tratará o job.

Pode influenciar:

  • prioridade;

  • initiator;

  • ambiente de execução;

  • limite de recursos;

  • janela operacional.

Cada empresa configura suas classes.


7.3 MSGCLASS

//            MSGCLASS=X,

Define onde as mensagens e listagens do job serão direcionadas.

Normalmente controla a classe de saída no spool.


7.4 NOTIFY

//            NOTIFY=&SYSUID

Pede que o usuário seja notificado quando o job terminar.

&SYSUID é uma variável simbólica que representa o usuário que submeteu o job.


7.5 EXEC PGM=DSNUTILB

//STEP01 EXEC PGM=DSNUTILB,

Aqui está o programa que executa a utility.

DSNUTILB é o batch utility program do Db2 for z/OS.

Ele recebe os comandos, conversa com o subsistema Db2 e coordena a operação.


7.6 REGION=0M

//            REGION=0M,

Solicita que o step utilize a quantidade de memória permitida pelas políticas do sistema, sem um limite artificial pequeno definido no JCL.

Isso não significa memória infinita.

O z/OS, o WLM e as configurações de instalação continuam impondo limites.


7.7 PARM

//            PARM='DB9G,RBIDX01'

O primeiro parâmetro identifica o subsistema Db2:

DB9G

O segundo funciona como utility ID:

RBIDX01

A utility ID precisa ser administrada com cuidado.

Se uma utility falhar e permanecer registrada, uma nova execução com a mesma ID pode encontrar conflito ou tentar continuar uma execução anterior, dependendo dos parâmetros.


7.8 STEPLIB

//STEPLIB DD DISP=SHR,DSN=DB2.V13.SDSNLOAD

Aponta para a biblioteca onde se encontram os módulos executáveis do Db2.

DISP=SHR

Permite compartilhar a biblioteca com outros jobs.

Em algumas instalações, a biblioteca já está no LINKLIST ou definida em um procedimento catalogado. Nesse caso, o STEPLIB pode não ser necessário.


7.9 SYSPRINT

//SYSPRINT DD SYSOUT=*

Recebe as mensagens principais da utility.

É um dos primeiros lugares que você deve consultar no spool.

Ali podem aparecer:

  • parâmetros reconhecidos;

  • objetos processados;

  • fases executadas;

  • mensagens de erro;

  • return code;

  • estatísticas;

  • tempos de execução.


7.10 UTPRINT

//UTPRINT DD SYSOUT=*

Recebe mensagens relacionadas ao processamento da utility.

Dependendo do utilitário e da versão, pode conter informações adicionais importantes.


7.11 SYSUDUMP

//SYSUDUMP DD SYSOUT=*

Solicita um dump caso ocorra uma falha anormal.

Esse dump pode ser enorme, mas é muito útil para diagnóstico técnico.

Em ambientes de produção, dumps podem ser direcionados a datasets específicos ou sistemas de gerenciamento de dumps.


7.12 SYSIN

//SYSIN DD *

Aqui começam os comandos da utility.

O asterisco indica que os dados estão embutidos no próprio JCL.

  REBUILD INDEX
    (DBFIN.IXCLIENT)

O conteúdo termina com:

/*

Também seria possível armazenar os comandos em um membro de PDS:

//SYSIN DD DISP=SHR,
//          DSN=IBMUSER.WORKBOOK.DB2.ERG(ERGREBL)

Esse formato corresponde ao campo mostrado na imagem:

STATEMENT DATA SET
IBMUSER.WORKBOOK.DB2.ERG(ERGREBL)

8. STATEMENT DATA SET: separando o JCL do comando

Na tela aparece um dataset semelhante a:

IBMUSER.WORKBOOK.DB2.ERG(ERGREBL)

Esse é um membro de uma biblioteca particionada.

Podemos dividir o nome assim:

IBMUSER
WORKBOOK
DB2
ERG
ERGREBL

O trecho entre parênteses é o membro:

ERGREBL

Dentro dele provavelmente existe algo semelhante a:

REBUILD INDEX
  (DBFIN.IXCLIENT)
  SHRLEVEL REFERENCE
  SORTDEVT SYSDA
  SORTNUM 8

A vantagem de armazenar o comando separadamente é a reutilização.

O mesmo JCL pode apontar para comandos diferentes:

ERGREBL  - REBUILD
ERGREOG  - REORG
ERGRUNS  - RUNSTATS
ERGCOPY  - COPY

Isso também melhora o controle de mudanças.


9. RESTART: começando de novo ou retomando a jornada

Na imagem:

RESTART ==> NO

Utilitários Db2 podem ser longos.

Um REORG de um tablespace gigantesco pode durar horas. Durante esse tempo, podem ocorrer:

  • falha de energia;

  • cancelamento operacional;

  • falta de espaço;

  • erro de sort;

  • indisponibilidade de dataset;

  • falha de dispositivo;

  • interrupção do Db2;

  • timeout;

  • erro de autorização.

Para evitar que todo o trabalho seja perdido, algumas utilities mantêm pontos de controle.

As opções apresentadas incluem:

NO
CURRENT
PHASE
PREVIEW

NO

RESTART = NO

Indica uma nova execução.

Não deseja retomar uma execução anterior.

CURRENT

Tenta continuar a utility a partir do ponto atual registrado.

PHASE

Permite reiniciar a partir de uma fase específica suportada.

PREVIEW

Permite visualizar ou avaliar informações da execução sem realizar todo o processamento normal, dependendo da utility e do contexto.

Exemplo conceitual

Uma utility REORG pode passar por fases como:

UTILINIT
UNLOAD
RELOAD
SORT
BUILD
LOG
SWITCH
UTILTERM

Se houver falha durante BUILD, o restart pode evitar a repetição completa das fases anteriores.

Cuidado

Nunca altere parâmetros de restart aleatoriamente.

O estado registrado no Db2 precisa corresponder ao comando informado. Alterações incompatíveis podem impedir a retomada ou gerar resultados inesperados.


10. RUNSTATS: ensinando o otimizador a enxergar

Agora vamos falar de uma utility indispensável.

O otimizador do Db2 escolhe caminhos de acesso com base em estatísticas.

Ele precisa saber:

  • quantidade de linhas;

  • número de páginas;

  • cardinalidade das colunas;

  • distribuição dos valores;

  • quantidade de valores distintos;

  • organização dos dados;

  • níveis do índice;

  • clustering;

  • frequência de determinados valores.

Sem estatísticas atualizadas, o otimizador toma decisões com informações antigas.

Imagine que uma tabela possuía 10 mil registros quando o último RUNSTATS foi executado.

Hoje ela possui 500 milhões.

O catálogo ainda diz:

CARDF = 10000

O otimizador pode escolher um caminho de acesso adequado para uma pequena tabela, mas desastroso para uma tabela gigantesca.

Exemplo de JCL para RUNSTATS

//RUNST01  JOB (ACCT),'RUNSTATS',
//             CLASS=A,
//             MSGCLASS=X,
//             NOTIFY=&SYSUID
//STEP01   EXEC PGM=DSNUTILB,
//             REGION=0M,
//             PARM='DB9G,RUNST01'
//STEPLIB   DD DISP=SHR,DSN=DB2.V13.SDSNLOAD
//SYSPRINT  DD SYSOUT=*
//UTPRINT   DD SYSOUT=*
//SYSIN     DD *
  RUNSTATS TABLESPACE DBFIN.TSCLIENT
    TABLE(ALL)
    INDEX(ALL)
    SHRLEVEL CHANGE
    UPDATE ALL
    REPORT YES
/*
//

Explicação

RUNSTATS TABLESPACE DBFIN.TSCLIENT

Solicita estatísticas do tablespace.

TABLE(ALL)

Processa todas as tabelas relevantes existentes naquele tablespace.

INDEX(ALL)

Coleta estatísticas de todos os índices associados.

SHRLEVEL CHANGE

Permite que aplicações continuem alterando os dados, dentro das regras e limitações da utility.

UPDATE ALL

Atualiza as estatísticas correspondentes no catálogo.

REPORT YES

Solicita relatório das informações coletadas.


11. COPY: criando uma linha do tempo para recuperação

A utility COPY cria uma image copy de um tablespace ou indexspace.

Não pense nela apenas como um “backup de arquivo”.

Ela faz parte da estratégia de recuperação do Db2.

Fluxo simplificado:

Image Copy
    +
Active Logs
    +
Archive Logs
    =
Recuperação até um ponto desejado

Exemplo

//COPY01   JOB (ACCT),'COPY TABLESPACE',
//             CLASS=A,
//             MSGCLASS=X,
//             NOTIFY=&SYSUID
//STEP01   EXEC PGM=DSNUTILB,
//             REGION=0M,
//             PARM='DB9G,COPY01'
//STEPLIB   DD DISP=SHR,DSN=DB2.V13.SDSNLOAD
//SYSPRINT  DD SYSOUT=*
//UTPRINT   DD SYSOUT=*
//SYSIN     DD *
  COPY TABLESPACE DBFIN.TSCLIENT
    FULL YES
    SHRLEVEL CHANGE
    COPYDDN COPYDD
/*
//COPYDD   DD DSN=BACKUP.DBFIN.TSCLIENT.D20260713,
//            DISP=(NEW,CATLG,DELETE),
//            UNIT=SYSDA,
//            SPACE=(CYL,(500,100),RLSE),
//            DCB=(RECFM=FB,LRECL=4096,BLKSIZE=0)
//

FULL YES

Cria uma cópia completa.

SHRLEVEL CHANGE

Permite alterações concorrentes durante grande parte do processo.

COPYDDN COPYDD

Liga o comando Db2 ao DD statement chamado COPYDD.

DISP

DISP=(NEW,CATLG,DELETE)

Significa:

NEW    - o dataset será criado;
CATLG  - se o step terminar normalmente, será catalogado;
DELETE - se o step falhar, será excluído.

SPACE

SPACE=(CYL,(500,100),RLSE)

Solicita:

Unidade de alocação: cilindros
Primária: 500
Secundária: 100
RLSE: liberar espaço não utilizado

12. REORG TABLESPACE: colocando a casa em ordem

Com o tempo, os dados podem perder a organização física ideal.

Isso ocorre por:

  • inserts fora da sequência;

  • deletes;

  • updates que aumentam o tamanho da linha;

  • page splits;

  • crescimento irregular;

  • espaços vazios;

  • registros deslocados;

  • baixa correlação com o índice de clustering.

O REORG TABLESPACE reorganiza os dados.

Exemplo

//REORG01  JOB (ACCT),'REORG TABLESPACE',
//             CLASS=A,
//             MSGCLASS=X,
//             NOTIFY=&SYSUID
//STEP01   EXEC PGM=DSNUTILB,
//             REGION=0M,
//             PARM='DB9G,REORG01'
//STEPLIB   DD DISP=SHR,DSN=DB2.V13.SDSNLOAD
//SYSPRINT  DD SYSOUT=*
//UTPRINT   DD SYSOUT=*
//SYSIN     DD *
  REORG TABLESPACE DBFIN.TSCLIENT
    LOG YES
    SHRLEVEL CHANGE
    SORTDEVT SYSDA
    SORTNUM 12
    STATISTICS
      TABLE(ALL)
      INDEX(ALL)
/*
//

LOG YES

Registra as alterações necessárias nos logs conforme as regras do utilitário.

SHRLEVEL CHANGE

Busca manter o objeto disponível para leitura e alteração durante boa parte da execução.

Isso não significa ausência absoluta de impacto.

Pode existir uma fase curta de troca ou sincronização na qual bloqueios são necessários.

SORTNUM 12

Solicita até doze datasets de sort.

Mais datasets não significam automaticamente mais desempenho. É necessário considerar:

  • tamanho do objeto;

  • memória;

  • paralelismo;

  • configuração do DFSORT;

  • disponibilidade de discos;

  • limites do sistema.


13. LISTDEF: selecionando objetos por regras

Na imagem:

LISTDEF? ==> NO

LISTDEF permite definir uma lista de objetos de forma lógica.

Sem LISTDEF:

REORG TABLESPACE DB01.TS001
REORG TABLESPACE DB01.TS002
REORG TABLESPACE DB01.TS003
REORG TABLESPACE DB01.TS004

Com LISTDEF, você pode criar uma regra:

LISTDEF LISTFIN
  INCLUDE TABLESPACE DBFIN.*

Depois:

RUNSTATS LIST LISTFIN

ou, conforme a utility e sintaxe suportada:

COPY LIST LISTFIN

O grande benefício aparece em ambientes com centenas ou milhares de objetos.

Exemplo conceitual

LISTDEF LISTAPPL
  INCLUDE TABLESPACE DBAPP.*
  EXCLUDE TABLESPACE DBAPP.TSTEMP*

A lista inclui todos os tablespaces do banco DBAPP, exceto os temporários.

Isso permite automação sem manter uma lista manual interminável.


14. TEMPLATE: fabricando nomes de datasets automaticamente

Na imagem:

TEMPLATE? ==> NO

O TEMPLATE permite definir padrões para datasets utilizados pelas utilities.

Sem TEMPLATE, cada COPY precisa de um DD statement:

//COPY01 DD DSN=BACKUP.DB1.TS1...
//COPY02 DD DSN=BACKUP.DB1.TS2...
//COPY03 DD DSN=BACKUP.DB1.TS3...

Com TEMPLATE, o Db2 pode gerar os nomes dinamicamente.

Exemplo conceitual:

TEMPLATE COPYTMP
  DSN 'BACKUP.&DB..&TS..D&DATE..T&TIME.'
  UNIT SYSDA
  DISP (NEW,CATLG,DELETE)
  SPACE CYL
  PCTPRIME 20

Depois:

COPY LIST LISTFIN
  COPYDDN COPYTMP

Os símbolos podem representar elementos como:

  • database;

  • tablespace;

  • data;

  • hora;

  • partição;

  • utility ID;

  • sequência.

O resultado pode ser:

BACKUP.DBFIN.TSCLIENT.D20260713.T231500

Isso reduz drasticamente o tamanho do JCL.


15. CHECK INDEX e CHECK DATA: o exame médico do banco

CHECK INDEX verifica a consistência entre o índice e os dados.

Ele procura situações como:

  • chave no índice sem linha correspondente;

  • linha existente sem chave no índice;

  • problemas estruturais;

  • inconsistências lógicas.

Exemplo:

//CHKIDX01 JOB (ACCT),'CHECK INDEX',
//             CLASS=A,
//             MSGCLASS=X
//STEP01   EXEC PGM=DSNUTILB,
//             REGION=0M,
//             PARM='DB9G,CHKIDX01'
//STEPLIB   DD DISP=SHR,DSN=DB2.V13.SDSNLOAD
//SYSPRINT  DD SYSOUT=*
//UTPRINT   DD SYSOUT=*
//SYSIN     DD *
  CHECK INDEX
    (DBFIN.IXCLIENT)
/*
//

CHECK DATA verifica relacionamentos e consistência de dados, especialmente em situações envolvendo constraints e dependências.

Esses utilitários não devem ser confundidos com consultas SQL de validação funcional.

Eles atuam no nível estrutural e operacional do Db2.


16. LOAD e UNLOAD: a doca de carga do Db2

UNLOAD

Extrai dados de uma tabela ou tablespace para um dataset sequencial.

Exemplo conceitual:

UNLOAD TABLESPACE DBFIN.TSCLIENT
  FROM TABLE FINANCEIRO.CLIENTE
  UNLDDN SYSREC

JCL:

//SYSREC DD DSN=EXPORT.CLIENTE.D20260713,
//          DISP=(NEW,CATLG,DELETE),
//          UNIT=SYSDA,
//          SPACE=(CYL,(100,50),RLSE),
//          DCB=(RECFM=VB,LRECL=32756,BLKSIZE=0)

LOAD

Carrega grandes volumes de dados.

Exemplo:

LOAD DATA
  INDDN SYSREC
  INTO TABLE FINANCEIRO.CLIENTE

A utility LOAD é muito mais eficiente que executar milhões de comandos INSERT individualmente.

Mas ela exige planejamento.

Dependendo das opções utilizadas, pode:

  • substituir dados;

  • acrescentar dados;

  • deixar índices em estado pendente;

  • exigir reconstrução;

  • afetar constraints;

  • gerar ou não logs detalhados;

  • exigir cópia posterior.


17. RECOVER: quando o treinamento vira batalha real

RECOVER restaura um objeto usando image copies e logs.

Imagine que alguém executou:

DELETE FROM FINANCEIRO.CLIENTE;
COMMIT;

O ROLLBACK já não pode ajudar porque houve COMMIT.

Uma estratégia de recuperação pode utilizar:

Image Copy anterior
+
Logs posteriores
+
Ponto no tempo antes do erro

Exemplo conceitual:

RECOVER TABLESPACE DBFIN.TSCLIENT
  TORBA X'00000000123456789012'

ou outra opção de point-in-time recovery suportada no ambiente.

Essa não é uma operação improvisada.

Antes de recuperar, a equipe precisa responder:

  • Qual foi o horário do erro?

  • Há image copy válida?

  • Os archive logs estão disponíveis?

  • Existem objetos relacionados?

  • Há integridade referencial?

  • Outros tablespaces precisam voltar ao mesmo ponto?

  • Quais aplicações devem ser interrompidas?

  • Como os dados posteriores serão reconciliados?

Um recovery tecnicamente bem-sucedido pode ainda produzir inconsistência de negócio se objetos relacionados forem recuperados para momentos diferentes.


18. Como acompanhar o job no SDSF

Depois de submeter o JCL, você normalmente abre o SDSF.

Comandos comuns:

ST

Mostra jobs ativos e concluídos conforme seus filtros.

Localize:

RBIDX01

Abra o job com S.

Você verá DDs como:

JESMSGLG
JESJCL
JESYSMSG
SYSPRINT
UTPRINT
SYSUDUMP

JESMSGLG

Contém mensagens do JES e informações gerais da execução.

JESJCL

Mostra o JCL expandido.

É especialmente útil quando foram utilizados:

  • procedures catalogadas;

  • símbolos;

  • includes;

  • overrides.

JESYSMSG

Contém mensagens do sistema, alocações e término dos steps.

SYSPRINT

Normalmente contém a narrativa principal da utility Db2.


19. Return codes: nem todo zero conta a história completa

Os códigos de retorno mais comuns são:

RC=0000
RC=0004
RC=0008
RC=0012
RC=0016

RC 0000

Execução normal.

Mesmo assim, leia as mensagens.

RC 0004

Aviso.

A utility pode ter terminado, mas algo merece atenção.

RC 0008

Erro relevante.

Parte do processamento pode não ter ocorrido.

RC 0012 ou superior

Erro grave.

A operação provavelmente falhou ou foi interrompida.

Nunca analise apenas o número final.

Procure mensagens Db2 com prefixos como:

DSNU
DSN
IEC
IGD
ICE
ICH

Cada família pode indicar uma origem diferente:

  • Db2 utility;

  • sistema;

  • dataset;

  • SMS;

  • sort;

  • segurança.


20. Passo a passo seguro para o Padawan

Antes de executar uma utility, siga uma sequência disciplinada.

Passo 1 — Confirme o ambiente

Verifique:

SSID
LPAR
Usuário
Qualificador dos datasets
Banco
Tablespace
Índice

Passo 2 — Entenda o motivo

Não execute REORG apenas porque “sempre executamos”.

Pergunte:

  • Há fragmentação?

  • As estatísticas indicam necessidade?

  • Existe impacto de desempenho?

  • O objeto está em estado pendente?

  • Houve LOAD?

  • O índice está inconsistente?

  • Existe recomendação de manutenção?

Passo 3 — Estime o impacto

Considere:

  • tamanho do objeto;

  • duração;

  • CPU;

  • I/O;

  • espaço de sort;

  • logs;

  • concorrência;

  • bloqueios;

  • janela de manutenção.

Passo 4 — Confira a recuperação

Antes de uma operação destrutiva ou de grande impacto, confirme:

  • última image copy;

  • disponibilidade dos logs;

  • estratégia de rollback;

  • procedimento de restart;

  • contato da equipe responsável.

Passo 5 — Use EDITJCL

Revise o JCL gerado.

Passo 6 — Valide o SYSIN

Um pequeno erro no objeto muda tudo.

Compare:

DBFIN.TSCLIENT

com:

DBFIM.TSCLIENT

Uma letra pode apontar para outro banco ou causar falha.

Passo 7 — Submeta e acompanhe

Não envie o job e abandone a sessão.

Observe:

  • início;

  • consumo;

  • mensagens;

  • fases;

  • locks;

  • tempo;

  • espaço;

  • término.

Passo 8 — Valide o resultado

Depois da utility:

  • confira o return code;

  • leia o SYSPRINT;

  • valide estados pendentes;

  • confirme disponibilidade;

  • execute consultas funcionais;

  • atualize documentação;

  • registre duração e consumo.


21. Curiosidades e easter eggs do mundo Db2

A tela simples esconde um sistema distribuído de responsabilidades

O painel ISPF coleta parâmetros.

O JES2 agenda o job.

O z/OS gerencia memória e recursos.

O Db2 controla catálogo, logs e objetos.

O DFSORT pode ordenar dados.

O SMS aloca datasets.

O RACF valida autorizações.

O WLM decide prioridades.

Uma única execução de REORG pode envolver quase todo o ecossistema do mainframe.

DSNUTILB parece apenas um programa, mas é um maestro

Ele não “faz tudo sozinho”.

Ele coordena serviços do Db2, acessa objetos, solicita sort, gerencia fases e registra estados de restart.

O nome da utility ID é mais importante do que parece

Uma utility ID não é apenas uma etiqueta estética.

Ela pode estar associada ao controle de execução e restart.

Reutilizar IDs sem compreender o estado anterior pode gerar confusão.

REORG não é um ritual religioso

Em algumas empresas, utilities são executadas em calendários fixos herdados de décadas anteriores.

Por exemplo:

Todo sábado: REORG em tudo.

Isso pode ser desnecessário e caro.

A abordagem moderna deve considerar indicadores reais e políticas inteligentes.

RUNSTATS pode melhorar ou piorar um plano

Estatísticas novas ajudam o otimizador, mas também podem provocar mudança de access path.

Por isso ambientes críticos costumam combinar RUNSTATS com:

  • análise de EXPLAIN;

  • gerenciamento de packages;

  • avaliação de regressão;

  • controles de estabilidade;

  • monitoramento pós-implantação.


Conclusão: a Utility é a oficina do Db2

Para o programador COBOL Padawan, o Db2 começa com comandos como:

SELECT
INSERT
UPDATE
DELETE

Mas o banco de dados não sobrevive apenas de SQL.

Ele precisa de manutenção.

Precisa saber como os dados estão distribuídos.

Precisa reorganizar estruturas.

Precisa reconstruir índices.

Precisa criar cópias.

Precisa recuperar informações.

Precisa validar sua própria integridade.

É exatamente isso que as Db2 Utilities oferecem.

A tela mostrada parece modesta:

FUNCTION ==> EDITJCL
UTILITY  ==> REBUILD

Entretanto, por trás dela existe uma cadeia poderosa:

ISPF
  |
  v
JCL
  |
  v
JES2
  |
  v
DSNUTILB
  |
  v
Db2
  |
  v
Catálogo + Logs + Tablespaces + Índices

O grande aprendizado não é simplesmente decorar que REBUILD reconstrói um índice ou que RUNSTATS atualiza estatísticas.

O verdadeiro aprendizado é entender que cada utility participa de uma estratégia maior de disponibilidade, desempenho, integridade e recuperação.

No mainframe, a tela verde raramente conta toda a história.

Ela mostra apenas a porta.

Atrás dela existe uma engenharia construída durante décadas, refinada por milhões de execuções e responsável por manter sistemas bancários, governamentais, industriais e corporativos funcionando enquanto o restante do mundo dorme.

E quando o Padawan finalmente entende o JCL, as mensagens do spool, as fases da utility e o motivo de cada parâmetro, aquela velha tela deixa de parecer antiga.

Ela passa a parecer exatamente o que sempre foi:

um console de manutenção de uma das plataformas de dados mais resilientes do planeta.

segunda-feira, 18 de julho de 2022

Muito Além do IBM Z: A Anatomia Completa de um Datacenter Mainframe

 

Bellacosa Mainframe e a anatomia de um datacenter mainframe ibm z

☕ Um Café no Bellacosa Mainframe

Muito Além do IBM Z: A Anatomia Completa de um Datacenter Mainframe

O Guia Definitivo para um Programador COBOL Padawan Entender Como Cada Cabo, Tubo, Rack e Equipamento Trabalha em Harmonia para Manter Bancos, Cartões de Crédito e Bolsas de Valores Funcionando 24 Horas por Dia

"Um programa COBOL nunca executa sozinho. Antes que uma única instrução MOVE seja processada, existe um verdadeiro ecossistema de engenharia trabalhando silenciosamente para que tudo aconteça."


Introdução

Existe uma cena clássica em filmes de ficção científica: o herói entra em uma enorme sala repleta de luzes, armários metálicos, tubos coloridos, cabos grossos, ventiladores gigantes e quilômetros de equipamentos.

Para a maioria das pessoas aquilo parece apenas uma sala cheia de máquinas.

Para um programador COBOL experiente...

Aquilo é praticamente uma cidade.

A imagem que analisamos representa exatamente isso.

Embora seja uma renderização artística, ela retrata com bastante fidelidade como funciona a infraestrutura de um datacenter corporativo moderno onde vivem os grandes IBM Z.

Quando um programador COBOL escreve:

EXEC SQL
SELECT SALDO
FROM CONTA
END-EXEC

ele normalmente imagina apenas:

Programa → Banco de Dados

Mas, na realidade, essa simples consulta percorre dezenas de equipamentos.

Hoje faremos uma verdadeira visita guiada pelo coração de um datacenter IBM Mainframe.

Pegue seu café.

Vamos entrar.


Bellacosa Mainframe e um moderno cpd centro de processamento de dados

Vista Geral da Sala

Imagine que estamos entrando nesta sala.

A primeira impressão é de organização absoluta.

Nada está ali por acaso.

Cada tubo possui uma função.

Cada cabo tem identificação.

Cada rack possui redundância.

Cada equipamento conversa com dezenas de outros equipamentos.

É exatamente como um grande programa COBOL bem escrito.

Se retirar uma instrução importante...

todo o restante pode parar.


O Teto: Onde Começa a Engenharia

Muitos iniciantes olham apenas para os computadores.

Os veteranos olham primeiro para o teto.

Por quê?

Porque boa parte da infraestrutura passa justamente acima dos equipamentos.

Ali encontramos:

  • barramentos elétricos

  • fibra óptica

  • tubulações

  • sensores

  • detectores de fumaça

  • iluminação

  • sistema anti-incêndio

  • monitoramento ambiental

É praticamente um "JCL da infraestrutura".


Painéis de LED

Os painéis brancos não servem apenas para iluminar.

Eles possuem:

  • baixo consumo

  • pouca emissão de calor

  • longa vida útil

  • alimentação redundante

Em alguns datacenters críticos, até a iluminação possui dupla alimentação.

Se uma UPS falhar...

a sala continua iluminada.


As Grandes Bandejas Porta-Cabos

Observe aquelas estruturas metálicas horizontais.

Elas são chamadas de:

Cable Tray

ou

Cable Ladder.

Ali passam centenas de quilômetros de cabos.

Sim.

Quilômetros.

Em grandes bancos não é raro existir mais de 100 km de cabeamento.

Essas bandejas carregam:

  • fibra óptica

  • Ethernet

  • alimentação

  • gerenciamento

  • SAN

  • FICON

  • cabos de sincronismo

Existe uma regra importante:

Energia nunca deve viajar junto com dados.

Isso reduz interferências eletromagnéticas.


Os Barramentos Elétricos (Busway)

Ao invés de milhares de cabos grossos...

utiliza-se um grande barramento.

Imagine uma avenida principal.

Dela saem pequenas ruas alimentando cada rack.

Subestação

↓

UPS

↓

Busway

↓

Tap Box

↓

Rack IBM Z

É uma solução muito mais segura.


Os Tubos Coloridos

Talvez sejam o detalhe mais interessante da imagem.

Eles fazem parte do sistema hidráulico do datacenter.

Sim.

Existe hidráulica dentro da sala.

E muita.

Os tubos podem transportar:

Água gelada

Água de retorno

Água industrial

Água para trocadores de calor

Circuitos secundários

Em um IBM z17, centenas de quilowatts de calor precisam ser removidos continuamente.


Easter Egg Bellacosa ☕

Todo iniciante acredita que um computador "esquenta um pouco".

Na realidade...

Um único IBM Z pode dissipar mais calor do que dezenas de aparelhos de ar-condicionado domésticos funcionando simultaneamente.

Por isso existe uma verdadeira usina de refrigeração.


Os Flexíveis Pretos

Cada conjunto preto descendo até os racks provavelmente representa conduítes.

Dentro deles passam:

  • fibras ópticas

  • alimentação redundante A

  • alimentação redundante B

  • cabos de gerenciamento

  • sensores ambientais

Tudo separado.

Tudo identificado.

Tudo documentado.


Descidas Individuais

Nenhum rack recebe apenas um cabo.

Normalmente encontramos:

Energia A

Energia B

Fibra A

Fibra B

Rede administrativa

Rede de monitoramento

Aterramento

Tudo redundante.


O Piso Elevado

Embora não apareça na imagem...

quase certamente existe.

Imagine um piso falso com cerca de 60 centímetros.

Debaixo dele passam:

energia

fibras

água

aterramento

ar frio

É praticamente uma segunda cidade escondida.


Os Racks

Agora chegamos à parte mais visível.

Os gabinetes pretos.

Eles podem conter praticamente qualquer equipamento.

Em um datacenter IBM normalmente encontramos:

IBM z17

IBM z16

LinuxONE Emperor

Storage DS8900F

SAN Switch

OSA Express

Crypto Express

Open Systems Servers

Appliances

HMC


IBM z17

O protagonista.

Ali vivem:

CPs

zIIPs

zAAPs (histórico)

IFLs

SAPs

RAIM

Memória

Cache

Canal I/O

Processadores criptográficos

Tudo redundante.


Hardware Management Console (HMC)

Sem ela praticamente não existe IBM Z.

A HMC permite:

IPL

Shutdown

LPAR

Monitoramento

Capacity Planning

Firmware

Diagnóstico

É o painel de controle da nave espacial.


Storage IBM DS8900F

Ao lado do IBM Z quase sempre existe um storage.

Os dados não ficam "dentro" do mainframe.

Eles ficam aqui.

Dentro dele existem:

NVMe

Flash

Cache

RAID

Processadores próprios

Compressão

Deduplicação

Criptografia


SAN Directors

Eles são as grandes rotatórias do armazenamento.

Utilizam:

Fibre Channel

FICON

NVMe over FC

Conectam:

IBM Z

Storage

Backup

Tape


OSA Express

É a placa de rede do IBM Z.

Pode oferecer:

10 Gb

25 Gb

100 Gb

TCP/IP

IPv6

OSA-Express Integrated


Crypto Express

Pouca gente sabe...

O IBM Z possui placas dedicadas para criptografia.

Elas executam:

AES

RSA

ECC

SHA

TLS

PIN bancário

PIX

Open Banking

Tudo acelerado por hardware.


FICON

O COBOL acessa um arquivo VSAM.

O VSAM está no DS8900F.

Como chegam os dados?

Pelos canais FICON.

Eles substituíram os antigos ESCON.

São verdadeiras autoestradas ópticas.


Tape Library

Mesmo em 2026...

fitas continuam existindo.

IBM TS4500

TS7700

LTO

3592

Porque:

backup

retenção

compliance

baixo custo


UPS

Nenhum IBM Z fica ligado diretamente na concessionária.

Entre a rua e o computador existem:

UPS

Bancos de baterias

Inversores

Retificadores

Filtros

Transformadores


Geradores

Quando acaba a energia:

0 segundos

Baterias.

Poucos segundos depois:

Entram os geradores diesel.

O IBM Z nem percebe.


CRAH

Computer Room Air Handler.

Ele recebe água gelada.

Remove calor.

Empurra ar frio.

Tudo continuamente.


Chiller

Fica normalmente fora do prédio.

É o responsável por produzir água gelada.

Sem ele...

nenhum datacenter sobrevive.


Sensores

Espalhados pela sala existem centenas deles.

Temperatura

Umidade

Fumaça

Vibração

Água

Pressão

Energia

Fluxo de ar

Todos ligados ao BMS.


BMS

Building Management System.

É o "z/OS" do prédio.

Controla:

ar

energia

portas

alarmes

incêndio

temperatura

bombas

geradores


Sistema Anti-incêndio

Jamais utilize água.

Os sistemas modernos usam:

FM-200

Novec 1230

Inergen

Eles retiram o oxigênio suficiente para apagar o fogo sem danificar os equipamentos.


Detectores VESDA

Muito antes da fumaça aparecer...

eles detectam partículas microscópicas.

É um dos sistemas mais impressionantes de um datacenter.


Segurança Física

Cartão RFID

Biometria

Reconhecimento facial

Mantrap

CFTV

Guarda 24x7

Registro de acesso

Nada entra sem autorização.


O Caminho de um Simples Programa COBOL

Imagine que você executa:

JOB
 ↓
JES2
 ↓
z/OS
 ↓
COBOL
 ↓
Db2
 ↓
FICON
 ↓
SAN
 ↓
DS8900F
 ↓
SSD Flash
 ↓
Retorno

Tudo isso acontece em milissegundos.

Enquanto isso:

✔ CRAH remove calor

✔ UPS estabiliza energia

✔ Busway distribui alimentação

✔ Chiller produz água gelada

✔ HMC monitora processadores

✔ RMF coleta desempenho

✔ SMF registra estatísticas

✔ RACF protege acessos

✔ WLM prioriza cargas

✔ GDPS pode manter um site de contingência sincronizado

E o programador apenas vê:

DISPLAY "PROCESSAMENTO OK".

A Grande Lição para um Programador COBOL Padawan

Existe uma tendência natural entre iniciantes de acreditar que a programação começa e termina no editor de código. Porém, um sistema corporativo executado em um IBM Z depende de uma infraestrutura gigantesca: energia redundante, climatização de precisão, armazenamento de altíssimo desempenho, redes ópticas, segurança física, monitoramento ambiental e dezenas de componentes especializados trabalhando de forma sincronizada.

Compreender essa arquitetura transforma a maneira como enxergamos o desenvolvimento. Um SELECT no Db2, uma leitura em VSAM ou uma transação CICS percorrem uma cadeia sofisticada de hardware e software antes de retornar o resultado ao usuário.

Essa é uma das maiores lições do universo mainframe: programar bem significa entender o ecossistema completo. Quanto mais o programador COBOL conhece a infraestrutura que sustenta suas aplicações, mais preparado estará para escrever sistemas eficientes, diagnosticar problemas e dialogar com equipes de operações, redes, armazenamento e administração do z/OS.

No mundo IBM Mainframe, o código é apenas a ponta visível de um iceberg de engenharia construído para entregar disponibilidade, desempenho e confiabilidade ininterruptos. É essa combinação de software e infraestrutura que permite aos grandes bancos, seguradoras, companhias aéreas e bolsas de valores processarem milhões de transações por segundo, todos os dias, sem que a maioria das pessoas sequer perceba que um IBM Z está trabalhando silenciosamente nos bastidores.


domingo, 17 de julho de 2022

De C++ ao COBOL no IBM Z : Você Não Está Trocando de Linguagem. Está Descobrindo um Novo Conceito de Engenharia de Software.

 

Bellacosa Mainframe do c++ ao cobol no zos

☕ Um Café no Bellacosa Mainframe

De C++ ao COBOL no IBM Z

Você Não Está Trocando de Linguagem. Está Descobrindo um Novo Conceito de Engenharia de Software.

"Quem domina C++ já aprendeu a controlar memória, desempenho e arquitetura. Aprender COBOL no IBM Z significa descobrir como aplicar essa disciplina ao software que movimenta bancos, bolsas de valores, seguradoras, governos e companhias aéreas há mais de meio século."

Existe um mito que acompanha praticamente todo desenvolvedor C++ quando ouve a palavra COBOL.

"É uma linguagem antiga."

"Não tem orientação a objetos."

"Não tem templates."

"Não tem STL."

"Não tem RAII."

"Não tem ponteiros."

Curiosamente...

Nenhuma dessas características explica por que bilhões de transações financeiras continuam sendo processadas diariamente em IBM Z.

Porque o IBM Z nunca foi uma competição de linguagens.

Sempre foi uma competição de confiabilidade.

E esse é justamente o ponto onde muitos programadores C++ descobrem que já possuem muito mais em comum com o mundo Mainframe do que imaginavam.


O programador C++ já pensa como um engenheiro

Quem programa em C++ normalmente desenvolveu algumas virtudes raras.

Ele sabe que desempenho importa.

Ele entende custo de memória.

Conhece pilha (stack) e heap.

Sabe que concorrência é difícil.

Entende compilação.

Conhece linkedição.

Sabe que ABI existe.

Já ouviu falar em alignment.

Conhece cache.

Sabe otimizar algoritmos.

Entende estruturas de dados.

Aprendeu que software não é apenas escrever código.

É construir sistemas.

E adivinhe?

Essa filosofia é extremamente compatível com o IBM Z.


A maior diferença não é COBOL

A maior mudança será perceber que no Mainframe o protagonista não é a linguagem.

É o ambiente.

No Windows você pensa em:

  • aplicação

  • executável

  • DLL

  • usuário

No IBM Z você passa a pensar em:

  • Job

  • Dataset

  • Região

  • CICS

  • IMS

  • DB2

  • RACF

  • JES2

  • Workload

  • Segurança

  • Disponibilidade

Você deixa de desenvolver apenas programas.

Passa a desenvolver partes de um ecossistema gigantesco.


Bellacosa Mainframe c++ versus cobol no zos

C++ e COBOL possuem mais semelhanças do que parece

À primeira vista parecem opostos.

Mas compare.

Ambos são compilados

Não existe interpretação.

Existe compilador.

Existe otimização.

Existe geração de código objeto.

Existe linkedição.

Existe build.

Tudo isso será familiar.


Ambos valorizam desempenho

No desktop você mede milissegundos.

No Mainframe mede milhões de transações por hora.

A preocupação é a mesma.

Executar rapidamente.

Consumir poucos recursos.

Não desperdiçar CPU.


Ambos valorizam estabilidade

Em C++ um ponteiro inválido pode derrubar um processo.

No Mainframe um erro pode impedir milhões de pagamentos.

A consequência muda.

A responsabilidade também.


Ambos vivem muitos anos

Aplicações C++ frequentemente permanecem décadas.

O mesmo acontece com COBOL.

Você aprenderá rapidamente que software corporativo envelhece muito mais lentamente do que aplicações web.


Ambos exigem disciplina

C++ não perdoa descuidos.

COBOL também não.

A diferença é que os erros costumam aparecer em regras de negócio.

Não em segmentation faults.


Onde tudo muda

Agora começam as diferenças.


Memória

Em C++ você administra memória.

new

delete

smart pointers

RAII

ownership

No COBOL praticamente toda memória já está definida.

Você declara estruturas.

O runtime administra tudo.

Não existe malloc para o desenvolvedor comum.

Você passa menos tempo gerenciando memória.

E muito mais tempo modelando dados.


Dados são o centro do universo

No C++ muitos desenvolvedores começam pensando em objetos.

No COBOL começa-se pensando em registros.

Campos.

Layouts.

Arquivos.

Tabelas.

Copys.

Estruturas.

A pergunta muda.

Em vez de:

"Qual classe criar?"

Você pergunta:

"Como esse registro representa o negócio?"


Legibilidade acima de tudo

Em C++ frequentemente vemos código extremamente compacto.

Templates.

Metaprogramação.

Lambdas.

Concepts.

Operator overloading.

No COBOL o objetivo sempre foi outro.

Código que qualquer desenvolvedor consiga ler daqui vinte anos.

Você rapidamente perceberá que clareza vale ouro.


Regras de negócio

Aqui acontece uma mudança importante.

Grande parte do código COBOL não implementa algoritmos complexos.

Implementa decisões empresariais.

Calcular juros.

Validar CPF.

Fechar folha.

Liquidar títulos.

Atualizar contas.

Emitir boletos.

Processar seguros.

Calcular impostos.

É programação.

Mas profundamente ligada ao negócio.


Batch é uma mudança de mentalidade

Quem veio do Windows costuma pensar em aplicações interativas.

No Mainframe você aprende Batch.

Recebe arquivos.

Valida.

Ordena.

Consolida.

Atualiza bancos.

Gera relatórios.

Tudo cuidadosamente orquestrado.

Muitos iniciantes subestimam Batch.

Depois descobrem que ele continua sendo uma das maiores forças do IBM Z.


Online também existe

Não pense que tudo é Batch.

Você conhecerá o CICS.

Ali surgem conceitos familiares.

Sessões.

Transações.

Chamadas.

Programas.

Controle de fluxo.

Mas com disponibilidade muito maior do que normalmente encontramos em aplicações tradicionais.


Banco de Dados

Se você conhece PostgreSQL, SQL Server ou Oracle, já possui uma excelente base.

Aprender DB2 será muito mais simples.

Você encontrará:

SELECT

INSERT

UPDATE

DELETE

JOIN

CURSOR

COMMIT

ROLLBACK

Índices.

Plano de acesso.

A sintaxe muda pouco.

A engenharia por trás é impressionante.


Arquivos ainda são importantes

Enquanto muitos ambientes modernos vivem exclusivamente de bancos relacionais, o IBM Z continua dominando processamento de arquivos gigantescos.

VSAM.

Sequential Files.

GDG.

Flat Files.

Isso surpreende muitos desenvolvedores.

Mas faz sentido quando milhões de registros precisam ser processados continuamente.


Segurança não é um detalhe

Em muitos ambientes segurança aparece no fim do projeto.

No IBM Z ela nasce junto.

RACF.

Perfis.

Grupos.

Permissões.

Auditoria.

Controle de acesso.

Tudo extremamente integrado.


A melhor trilha para um programador C++

Se eu estivesse orientando um excelente desenvolvedor C++, faria exatamente este caminho.


Etapa 1

Não aprenda COBOL primeiro.

Aprenda IBM Z.

Entenda:

  • o que é um Mainframe

  • por que existe

  • quais problemas resolve

  • disponibilidade

  • redundância

  • processamento de missão crítica

Sem isso COBOL parecerá apenas uma linguagem antiga.


Etapa 2

Aprenda z/OS

Entenda:

  • Dataset

  • PDS

  • PDSE

  • Sequential

  • VSAM

  • Catalog

  • Volume

  • Job

  • Step

Esses conceitos aparecerão diariamente.


Etapa 3

Aprenda TSO/ISPF

Aprenda a navegar.

Editar.

Compilar.

Executar.

Comparar arquivos.

Pesquisar membros.

Como um programador Linux aprende Bash.


Etapa 4

Aprenda JCL

Esse é provavelmente o maior choque.

JCL não é linguagem de programação.

É descrição de execução.

Quem entende JCL entende o Mainframe.


Etapa 5

Agora sim...

COBOL.

Comece apenas com:

IDENTIFICATION DIVISION

DATA DIVISION

WORKING-STORAGE

PROCEDURE DIVISION

IF

PERFORM

EVALUATE

READ

WRITE

MOVE

COMPUTE

Nada mais.


Etapa 6

Arquivos

Aprenda:

Sequential

VSAM

KSDS

ESDS

READ

WRITE

START

REWRITE

DELETE


Etapa 7

SQL

COBOL + DB2.

Aqui você descobrirá onde grande parte dos sistemas corporativos realmente vivem.


Etapa 8

CICS

Aprenda:

COMMAREA

MAP

Pseudo Conversação

LINK

XCTL

RETURN

RESP

Depois Channels e Containers.


Etapa 9

Debug

SDSF

JES2

Spool

Abends

Dump

Mensagens

SYSOUT

SYSUDUMP

SYSABOUT

Aprenda a investigar problemas.


Etapa 10

Modernização

Somente depois disso avance para:

REST

JSON

XML

z/OS Connect

MQ

Kafka

Java

Python

OpenAPI

Git

VS Code

Zowe

Ansible

OpenShift

Porque agora você compreenderá onde essas tecnologias entram.


O que treinar diariamente

Sugiro uma rotina simples.

Segunda

Resolver pequenos exercícios COBOL.

Terça

Ler JCL.

Quarta

Executar Batch.

Quinta

SQL no DB2.

Sexta

Ler código legado.

Sábado

Refatorar programas COBOL.

Domingo

Estudar arquitetura IBM Z.

Em poucos meses você terá construído uma visão muito superior à de quem apenas decorou comandos.


O maior erro de quem vem do C++

O desenvolvedor tenta transformar COBOL em C++.

Não faça isso.

COBOL resolve outro tipo de problema.

Quanto antes aceitar isso, mais rápido aprenderá.


O maior desafio

Não será aprender comandos.

Será aprender o domínio bancário.

Seguros.

Cartões.

Folha.

Tributos.

Previdência.

Liquidação financeira.

No IBM Z, entender o negócio vale tanto quanto dominar a linguagem.


O que um programador C++ aprende com o Mainframe

Depois de algum tempo algo curioso acontece.

Você volta ao C++ diferente.

Mais disciplinado.

Mais cuidadoso.

Mais preocupado com rastreabilidade.

Mais atento à estabilidade.

Mais consciente do impacto de uma mudança.

Porque o IBM Z ensina uma lição rara.

Software não existe apenas para impressionar desenvolvedores.

Existe para manter empresas funcionando.

Existe para pagar salários.

Existe para processar aposentadorias.

Existe para autorizar cartões.

Existe para movimentar bolsas de valores.

Existe para garantir que um avião possa decolar porque milhares de reservas foram processadas corretamente.

Essa responsabilidade muda completamente a forma como enxergamos programação.


Conclusão

Se você domina C++, já possui uma base extraordinária.

Você entende algoritmos, compilação, desempenho e arquitetura. Agora chegou a hora de aprender algo que poucas universidades ensinam: como grandes organizações constroem sistemas capazes de operar 24 horas por dia, sete dias por semana, durante décadas, com confiabilidade quase absoluta.

COBOL no IBM Z não substitui o C++.

Ele complementa sua formação.

Você continuará pensando como engenheiro, mas passará a enxergar software por outra perspectiva: continuidade, governança, auditoria, integridade dos dados e estabilidade operacional.

No Bellacosa Mainframe costumo dizer que aprender IBM Z é como visitar uma usina hidrelétrica depois de anos construindo geradores portáteis.

Os dois produzem energia.

Mas em escalas completamente diferentes.

O mesmo vale para C++ e COBOL.

Você não está abandonando a programação moderna.

Está descobrindo onde muitos dos sistemas mais importantes do planeta aprenderam a nunca falhar.

E essa é uma experiência que transforma qualquer desenvolvedo

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...