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

Translate

Mostrar mensagens com a etiqueta VSAM. Mostrar todas as mensagens
Mostrar mensagens com a etiqueta VSAM. Mostrar todas as mensagens

sexta-feira, 18 de setembro de 2026

⚔️ RICK GLADIATOR E AS TRÊS DUNGEONS DA ARQUITETURA

 

☕ Um Café no Bellacosa Mainframe

⚔️ RICK GLADIATOR E AS TRÊS DUNGEONS DA ARQUITETURA

Monolith, Microservices, Serverless, COBOL, CICS, Db2, VSAM, MQ, APIs, eventos, consistência distribuída, observabilidade — e o dia em que um programador iniciante descobriu que quebrar um programa em 47 pedaços não o transformava automaticamente em arquiteto.

Sob a tutela de Rick Gladiator, de Shinmai Ossan Boukensha.


🎬 PRÓLOGO — VOCÊ TEM 30 ANOS E AINDA USA UM MONÓLITO?

Rick Gladiator conhece muito bem aquela sensação.

Você chega à Guilda dos Aventureiros e encontra uma turma de jovens prodígios.

Um lança magia.

Outro derrota monstros gigantescos.

Outro provavelmente nasceu com KUBERNETES-SKILL LEVEL 99.

Então alguém olha para o velho programador COBOL e pergunta:

— Você ainda trabalha com monólito?

Silêncio.

O programador olha para o terminal.

Rick coloca a espada sobre a mesa.

E responde:

— Antes de chamar alguma coisa de velha, descubra por que ela ainda está funcionando.

Bem-vindo à dungeon.

Hoje não vamos simplesmente comparar três caixas coloridas de um diagrama:

MONOLITH
MICROSERVICES
SERVERLESS

Vamos descobrir o que realmente muda, onde cada arquitetura funciona, quais problemas aparecem quando distribuímos uma aplicação e, principalmente, como tudo isso conversa com COBOL, CICS, Db2, VSAM, MQ e o Mainframe.

Porque existe uma primeira armadilha escondida no mapa:

Monolith, Microservices e Serverless não são exatamente três alternativas equivalentes.

Rick já percebeu o monstro.

Vamos entrar.


🏰 CAPÍTULO 1 — A PRIMEIRA DUNGEON: O MONÓLITO

Imagine que precisamos desenvolver um comércio eletrônico.

Temos:

Produtos
Carrinho
Pedidos
Pagamentos
Clientes

Uma arquitetura monolítica poderia ser representada assim:

             CLIENTE
                |
                v
       +----------------+
       |   APLICAÇÃO    |
       |----------------|
       | Produtos       |
       | Carrinho       |
       | Pedidos        |
       | Pagamentos     |
       | Clientes       |
       +----------------+
                |
                v
            DATABASE

Existe uma aplicação contendo diferentes responsabilidades.

A definição simplificada costuma ser:

One application = one deployable unit.

Mas Rick imediatamente ergue a mão.

— Cuidado.

No mundo Mainframe isso precisa de uma explicação adicional.

Um sistema COBOL pode possuir:

PGMAUTH
PGMCUST
PGMLIMIT
PGMPAY
PGMBILL
PGMSTAT

Pode utilizar:

COPYBOOKS
SUBPROGRAMAS
CICS
Db2
VSAM
JCL
PROCEDURES

e possuir centenas ou milhares de módulos.

Mesmo assim, arquiteturalmente, esses componentes podem formar uma grande aplicação fortemente relacionada.

Portanto:

Monólito não significa obrigatoriamente um programa gigantesco com três milhões de linhas.

Essa confusão aparece bastante.


🧱 CAPÍTULO 2 — MONÓLITO NÃO SIGNIFICA CÓDIGO RUIM

Rick encontra o primeiro aventureiro da guilda.

Ele possui uma camiseta:

MICROSERVICES OR DIE

Rick pergunta:

— Por quê?

— Porque monólito é ruim.

— Por quê?

— Porque é monólito.

Rick começa a procurar sua espada.

Um monólito pode ser perfeitamente modular.

Imagine:

+--------------------------------+
| SISTEMA DE CARTÕES             |
|                                |
| AUTHORIZATION MODULE           |
| CUSTOMER MODULE                |
| LIMIT MODULE                   |
| BILLING MODULE                 |
| PAYMENT MODULE                 |
| FRAUD MODULE                   |
+--------------------------------+

Cada responsabilidade pode estar adequadamente separada internamente.

Em COBOL:

CALL 'LIMITCHK' USING CUSTOMER-DATA
                      TRANSACTION-DATA
                      RETURN-DATA.

Uma chamada local entre componentes pode ser extremamente rápida.

Não precisamos necessariamente atravessar:

HTTP
TCP/IP
TLS
API Gateway
JSON
Authentication
Load Balancer
Service Discovery

para calcular o limite de um cartão.

A simplicidade também é uma característica arquitetural.


⚡ CAPÍTULO 3 — RICK DESCOBRE QUE A REDE TEM LATÊNCIA

Imagine isto:

CALL 'CALCLIM' USING WS-CUSTOMER
                     WS-LIMIT.

Agora alguém decide:

— CALCLIM precisa virar microservice!

A arquitetura passa a ser algo semelhante a:

COBOL
  |
  v
HTTP CLIENT
  |
  v
TCP/IP
  |
  v
TLS
  |
  v
API GATEWAY
  |
  v
AUTHENTICATION
  |
  v
LIMIT SERVICE
  |
  v
DATABASE

Arquiteturalmente ganhamos várias possibilidades.

O serviço pode ser implantado independentemente.

Pode escalar independentemente.

Outra aplicação pode reutilizá-lo.

Mas Rick pergunta:

— E quanto custou atravessar essa ponte?

Porque agora temos:

latência
timeout
retry
serialização
desserialização
falha de rede
DNS
autenticação
observabilidade

A operação que antes acontecia dentro do mesmo processo agora atravessa uma rede.

Não significa que microservices sejam ruins.

Significa apenas:

Toda arquitetura compra vantagens pagando com alguma forma de complexidade.


🔵 CAPÍTULO 4 — A SEGUNDA DUNGEON: MICROSERVICES

Agora vamos quebrar nosso comércio eletrônico.

                    CLIENT
                       |
                       v
                 API GATEWAY
                       |
          +------------+------------+
          |            |            |
          v            v            v
       PRODUCT        CART        ORDER
       SERVICE       SERVICE      SERVICE
          |            |            |
          v            v            v
       MongoDB        Redis      PostgreSQL

A ideia é que cada serviço represente uma capacidade de negócio relativamente independente.

Podemos ter:

Customer Service
Order Service
Payment Service
Inventory Service
Fraud Service

Idealmente cada um possui autonomia suficiente para evoluir sem exigir um gigantesco deploy coordenado.

Essa palavra é fundamental:

INDEPENDÊNCIA

Queremos independência de:

desenvolvimento
deploy
escalabilidade
tecnologia
ciclo de vida
equipe
dados

Por exemplo, durante a Black Friday:

Product Service = 20 instâncias
Cart Service    = 80 instâncias
Order Service   = 50 instâncias
Fraud Service   = 30 instâncias

Podemos aumentar apenas aquilo que está sofrendo pressão.

Essa é uma diferença importante em relação a muitos monólitos.


🐉 CAPÍTULO 5 — VOCÊ DERROTOU O MONÓLITO E DESBLOQUEOU 17 NOVOS MONSTROS

Rick abre a próxima porta.

Há uma placa:

Distributed Systems Dungeon

Ele imediatamente percebe que alguma coisa vai dar errado.

Imagine uma compra.

Em uma aplicação centralizada poderíamos ter conceitualmente:

BEGIN TRANSACTION

UPDATE INVENTORY
INSERT ORDER
INSERT PAYMENT

COMMIT

Algo falhou?

ROLLBACK

É claro que sistemas reais são mais complexos, mas o banco de dados fornece mecanismos transacionais poderosos.

Agora distribuímos tudo:

Order Service
      |
      +----> Inventory Service
      |
      +----> Payment Service
      |
      +----> Shipping Service

Resultado:

Inventory = OK
Payment   = OK
Shipping  = ERROR

E agora?

Não existe necessariamente um botão mágico:

ROLLBACK UNIVERSO

Temos vários sistemas, bancos e estados independentes.

Bem-vindo a conceitos como:

Eventual Consistency
Saga
Compensating Transactions
Idempotency
Retry
Timeout
Dead-Letter Queue
Circuit Breaker

Rick olha para o programador iniciante.

— Ainda acha que dividir tudo em serviços automaticamente simplifica a aplicação?


🔁 CAPÍTULO 6 — IDEMPOTÊNCIA: ATAQUE O MONSTRO DUAS VEZES SEM MATAR DOIS CLIENTES

Suponha que um serviço receba:

PAY CUSTOMER 100

Ele processa.

Mas a resposta não retorna por causa de um timeout.

O chamador pensa:

"Não funcionou."

E envia novamente.

Se o sistema não estiver preparado:

Pagamento 1 = R$100
Pagamento 2 = R$100

Temos problema.

Uma operação idempotente procura permitir que repetições controladas não produzam efeitos duplicados indevidos.

Podemos trabalhar com algo como:

TRANSACTION-ID = ABC123

Antes de processar novamente:

ABC123 já foi processada?

Se sim, devolvemos o resultado anterior ou tratamos de acordo com a regra definida.

Em sistemas distribuídos, isso deixa de ser detalhe.

É sobrevivência.


👹 CAPÍTULO 7 — O TERRÍVEL DISTRIBUTED MONOLITH

A guilda comemora.

— Conseguimos! Criamos 27 microservices!

Rick pergunta:

— Eles podem ser implantados independentemente?

Silêncio.

Para instalar PAYMENT, precisamos instalar ORDER.

Para instalar ORDER, precisamos instalar CUSTOMER.

Para instalar CUSTOMER, precisamos atualizar PRODUCT.

Então temos:

27 serviços
27 pipelines
27 APIs
27 logs
27 configurações

mas...

1 deploy coordenado

Criamos um:

DISTRIBUTED MONOLITH

Ou seja:

Pegamos algumas desvantagens do monólito e adicionamos várias dificuldades dos sistemas distribuídos.

Esse é um dos maiores perigos de adotar microservices apenas porque eles estão na moda.


🟣 CAPÍTULO 8 — A TERCEIRA DUNGEON: SERVERLESS

Chegamos ao terceiro bloco do desenho.

Mas existe um segredo.

Serverless não está exatamente no mesmo eixo de Monolith e Microservices.

Monolith e Microservices respondem principalmente:

Como organizamos e dividimos a aplicação?

Serverless responde mais diretamente:

Como determinado código será executado e operacionalizado?

Essa diferença muda tudo.

Podemos ter:

Microservices + Serverless

Podemos ter:

Monolith + Serverless Functions

Podemos ter:

Mainframe + Microservices + Serverless

Portanto não pense:

MONOLITH
   ↓
MICROSERVICES
   ↓
SERVERLESS

como uma linha evolutiva.

Não existe um Pokémon arquitetural chamado:

Monolithmon
   ↓
Microservicemon
   ↓
Serverlessmon

☁️ CAPÍTULO 9 — MAS SERVERLESS TEM SERVIDOR!

Sim.

Rick também ficou decepcionado.

Serverless não significa que os servidores desapareceram em alguma magia ancestral.

Eles continuam existindo.

A diferença é que o desenvolvedor normalmente não administra diretamente toda a infraestrutura necessária para executar aquela função.

Um modelo simplificado:

EVENT
  |
  v
FUNCTION
  |
  v
RESULT

Por exemplo:

HTTP REQUEST
     |
     v
API GATEWAY
     |
     v
CREATE-ORDER FUNCTION
     |
     v
DATABASE

Mas o evento também pode ser:

Queue Message
File Upload
Timer
Database Change
Object Created
Event Stream

Por isso Serverless combina muito bem com arquiteturas orientadas a eventos.


🥶 CAPÍTULO 10 — O DRAGÃO DO COLD START

Uma função pode não estar continuamente ativa.

Chega uma solicitação.

A plataforma talvez precise preparar seu ambiente:

REQUEST
   |
   v
START RUNTIME
   |
   v
LOAD DEPENDENCIES
   |
   v
INITIALIZE
   |
   v
EXECUTE FUNCTION

Essa inicialização pode introduzir latência.

É o famoso:

Cold Start

Isso varia conforme plataforma, linguagem, configuração e modelo operacional.

Para algumas aplicações é irrelevante.

Para outras, alguns milissegundos adicionais podem ser importantes.

A lição é novamente:

Não escolha tecnologia olhando apenas o desenho bonito.

Meça.


🏦 CAPÍTULO 11 — RICK GLADIATOR ENTRA NO CICS

Agora começa a parte que faz o velho programador COBOL sorrir.

Considere:

CLIENT
   |
   v
CICS
   |
   v
TRANSACTION
   |
   v
COBOL PROGRAM
   |
   +----> Db2
   |
   +----> VSAM

O programador COBOL normalmente não precisa escrever do zero toda a infraestrutura necessária para:

gerenciar processos
controlar recursos
coordenar transações
gerenciar milhares de solicitações
proteger recursos

O CICS oferece um ambiente transacional gerenciado.

Isso não significa que CICS seja Serverless no sentido moderno.

Mas existe uma analogia pedagógica deliciosa.

Décadas antes da palavra "serverless" virar assunto de conferência, o Mainframe já trabalhava profundamente com ideias como:

execução gerenciada
workload
transações
eventos
resource management
security
recovery

Rick olha para a arquitetura moderna.

Depois olha para o CICS.

— Eu já vi alguns desses golpes antes...


🌉 CAPÍTULO 12 — O COBOL NÃO PRECISA VIRAR MICROSERVICE

Imagine um banco com:

Mobile Banking
Internet Banking
Open Finance
Parceiros
ATM

Podemos construir:

Mobile
   |
   v
API Gateway
   |
   v
Microservices
   |
   v
z/OS Connect
   |
   v
CICS
   |
   v
COBOL
   |
   +--> Db2
   |
   +--> VSAM

O programa COBOL pode continuar sendo responsável pela lógica transacional crítica.

A modernização ocorre ao redor e através dele.

Essa é uma mudança enorme de perspectiva.

Modernizar não significa obrigatoriamente:

DELETE COBOL.

Pode significar:

ENABLE COBOL.

🔌 CAPÍTULO 13 — z/OS CONNECT ABRE A PORTA DA DUNGEON

Imagine que nosso programa trabalha com:

01 CUSTOMER-REQUEST.
   05 CUSTOMER-ID PIC X(10).

01 CUSTOMER-RESPONSE.
   05 CUSTOMER-NAME  PIC X(40).
   05 CUSTOMER-LIMIT PIC 9(09)V99.

O mundo moderno deseja conversar usando algo semelhante a:

{
  "customerId": "0001234567"
}

e receber:

{
  "name": "RICK GLADIATOR",
  "limit": 15000.00
}

Uma integração pode assumir:

REST / JSON
     |
     v
z/OS Connect
     |
     v
CICS
     |
     v
COBOL

Perceba a beleza.

O programa COBOL não precisa acordar numa terça-feira dizendo:

"Agora sou JavaScript."

Ele continua executando a responsabilidade para a qual foi construído.

Criamos uma nova fronteira de integração.


📨 CAPÍTULO 14 — MQ: RICK DESCOBRE QUE NEM TODA MISSÃO PRECISA ESPERAR RESPOSTA

Outra possibilidade:

ORDER SERVICE
      |
      v
     MQ
      |
      v
COBOL CONSUMER
      |
      v
     Db2

O produtor publica uma mensagem.

Algo como:

ORDER.CREATED

O consumidor processa quando apropriado.

Podemos ter:

ORDER.CREATED
      |
      +----> BILLING
      |
      +----> INVENTORY
      |
      +----> FRAUD
      |
      +----> ANALYTICS

Isso introduz uma distinção essencial.

Comunicação síncrona:

FAÇA ISTO
E EU ESPERO A RESPOSTA

Comunicação assíncrona:

ESTE TRABALHO PRECISA SER PROCESSADO

Essa diferença é fundamental para arquiteturas corporativas.


🌊 CAPÍTULO 15 — EVENT STREAMING: O MONSTRO MORREU E TODO MUNDO FICOU SABENDO

Em arquiteturas orientadas a eventos, podemos publicar:

PAYMENT.APPROVED

Diversos interessados podem reagir:

PAYMENT.APPROVED
        |
        +------> ORDER
        |
        +------> SHIPPING
        |
        +------> ANALYTICS
        |
        +------> FRAUD
        |
        +------> NOTIFICATION

Isso reduz determinados acoplamentos diretos.

O produtor não precisa necessariamente conhecer todos os consumidores.

O conceito muda de:

"Fulano, faça isso."

para:

"Isto aconteceu."

É uma mudança arquitetural poderosa.


🔭 CAPÍTULO 16 — OBSERVABILIDADE: QUEM MATOU O MONSTRO?

No monólito:

Client
  |
Application
  |
Database

Investigar uma falha pode ser relativamente simples.

Agora:

Client
 |
Gateway
 |
Service A
 |
Service B
 |
Queue
 |
Service C
 |
Mainframe
 |
CICS
 |
COBOL
 |
Db2

O usuário reclama:

"Demorou oito segundos."

Onde?

Precisamos correlacionar:

logs
metrics
traces
timestamps
transaction IDs
correlation IDs

Talvez a API tenha consumido:

50 ms

O microservice:

80 ms

MQ:

20 ms

CICS:

40 ms

mas uma consulta esperou:

7.500 ms

por um lock no Db2.

Sem observabilidade distribuída, o diagnóstico vira investigação arqueológica.


📊 CAPÍTULO 17 — O MAPA DE RICK

Guarde esta tabela mental:

AspectoMonolithMicroservicesServerless
Organizaçãoaplicaçãoserviçosfunções/event handlers
Deploymais coordenadoindependentefunção
Comunicaçãofrequentemente localrede/eventoseventos/APIs
Escalaaplicaçãoserviçoexecução/função
Estadomais centralizadodistribuídonormalmente externo
Debugmais simplesdistribuídodistribuído
Operaçãomenor complexidade inicialaltainfraestrutura abstraída
Consistênciamais simplescomplexafrequentemente distribuída
Redemenor dependência internafundamentalfundamental
Observabilidadeconcentradadistribuídadistribuída

Mas Rick acrescentaria:

Não transforme essa tabela em religião.


💰 CAPÍTULO 18 — SERVERLESS NÃO SIGNIFICA BARATO

Imagine uma função utilizada:

100 vezes por dia

Excelente candidata potencial.

Agora imagine:

10.000 requisições/segundo
24 horas/dia
365 dias/ano

A análise econômica muda completamente.

Serverless frequentemente oferece cobrança baseada em utilização, mas isso não significa automaticamente:

SERVERLESS = MAIS BARATO

Você precisa avaliar:

volume
duração
memória
I/O
rede
armazenamento
requisições
picos
previsibilidade
SLA

A arquitetura correta é também uma decisão econômica.


🧭 CAPÍTULO 19 — PASSO A PASSO PARA ESCOLHER

Rick não escolheria uma arma apenas porque alguém colocou "Cloud Native" na embalagem.

Faça perguntas.

Passo 1 — descubra o domínio

O que a aplicação realmente faz?

Pagamento?
Consulta?
Relatório?
Fraude?
Cadastro?
Processamento de imagem?

Passo 2 — descubra o volume

Temos:

100 operações/dia

ou:

10.000 operações/segundo?

Passo 3 — determine a latência

Pode levar:

10 segundos?
1 segundo?
100 ms?
20 ms?

Passo 4 — descubra o estado

Precisamos manter informações entre execuções?

Onde?

Passo 5 — determine consistência

É aceitável que dois sistemas fiquem temporariamente diferentes?

Passo 6 — analise as transações

Precisamos alterar vários recursos atomicamente?

Passo 7 — analise escalabilidade

Qual componente realmente precisa crescer?

Passo 8 — pense em falhas

Pergunte:

E se a rede cair?

E se houver timeout?

E se a mensagem chegar duas vezes?

E se o consumidor ficar indisponível?

E se o banco responder e a confirmação desaparecer?

Essa talvez seja uma das melhores formas de pensar como arquiteto.


🏗️ CAPÍTULO 20 — A ARQUITETURA REAL NÃO CABE NAS TRÊS COLUNAS

Uma arquitetura corporativa moderna pode ser:

                    MOBILE
                       |
                       v
                  API GATEWAY
                       |
            +----------+----------+
            |                     |
            v                     v
      MICROSERVICES          SERVERLESS
            |                     |
            +----------+----------+
                       |
                       v
                 EVENT STREAM
                       |
                       v
                      MQ
                       |
                       v
              +----------------+
              |   IBM Z        |
              |----------------|
              | CICS           |
              | IMS            |
              | COBOL          |
              | Db2            |
              | VSAM           |
              +----------------+

Agora desaparece aquela velha guerra:

MAINFRAME
   VS
CLOUD

Essa pergunta é pobre.

A pergunta melhor é:

Qual workload deve executar onde?

Essa é uma pergunta de arquiteto.


🥚 EASTER EGG — 03:17 DA MADRUGADA

Às 03:17, o telefone toca.

Produção.

O dashboard está verde.

O cliente diz que pagamentos estão sendo duplicados.

O jovem aventureiro verifica Kubernetes.

Tudo verde.

Verifica API Gateway.

Verde.

Microservices.

Verdes.

Serverless.

Verde.

MQ.

Verde.

CICS.

Verde.

Então Rick pergunta:

— Qual é o CORRELATION-ID da transação?

Silêncio.

Descobrem que um timeout fez o cliente repetir uma requisição e o Payment Service não tratava adequadamente a repetição.

A transação foi processada duas vezes.

Rick fecha o notebook.

Não existe arquitetura suficientemente moderna para compensar uma regra transacional mal compreendida.

03:17.

Incidente encerrado.

Quem acompanha o Bellacosa Mainframe sabe que esse horário nunca aparece por acaso. ☕😈


🎓 CAPÍTULO 21 — O QUE O PROGRAMADOR COBOL INICIANTE PRECISA APRENDER

Não abandone COBOL para correr atrás de todas as palavras da moda.

Expanda o mapa.

Comece com:

COBOL
JCL
VSAM
Db2
CICS

Depois acrescente:

TCP/IP
HTTP
REST
JSON
APIs

Depois:

MQ
Mensageria
Eventos
Kafka/Event Streaming

Depois:

Git
CI/CD
Containers
Microservices
Cloud
Serverless

E finalmente conecte tudo:

COBOL
   |
   +------ CICS
   |
   +------ Db2
   |
   +------ VSAM
   |
   +------ MQ
   |
   +------ APIs
   |
   +------ Events
   |
   +------ Microservices
   |
   +------ Cloud

Nesse momento você deixa de enxergar apenas um programa.

Começa a enxergar arquitetura.


⚔️ EPÍLOGO — O OSSAN NÃO PRECISAVA SER O MAIS JOVEM DA GUILDA

Rick Gladiator não é interessante porque começou cedo.

É justamente o contrário.

Ele lembra que experiência, disciplina e treinamento podem alterar completamente aquilo que aparentemente parecia uma desvantagem.

Existe uma bela analogia com Mainframe.

O programador olha para:

COBOL
CICS
VSAM
Db2
JCL

e alguém diz:

— Isso é velho.

Então ele olha para:

transactions
workload management
resource management
messaging
security
high availability
event processing

e percebe:

— Espere um pouco...

Muitos dos problemas que a computação moderna está tentando resolver não são novos.

As ferramentas mudaram.

As abstrações mudaram.

Os nomes ficaram mais bonitos.

Os slides ganharam cores.

Mas continuamos tentando responder perguntas antigas:

Como executar trabalho?

Como dividir responsabilidades?

Como mover dados?

Como sobreviver a falhas?

Como escalar?

Como garantir uma transação?

Como descobrir onde alguma coisa deu errado?

E é por isso que a pergunta definitiva não deveria ser:

Monolith
     VS
Microservices
     VS
Serverless

A pergunta deveria ser:

QUAL ARQUITETURA RESOLVE MELHOR ESTE PROBLEMA?

Às vezes será um monólito modular.

Às vezes serão microservices.

Às vezes serverless.

Às vezes CICS e COBOL.

E, em sistemas empresariais de verdade, frequentemente será:

              +----------------+
              | MICROSERVICES  |
              +-------+--------+
                      |
SERVERLESS -------- EVENTS
                      |
                     MQ
                      |
              +-------+--------+
              |      CICS      |
              +-------+--------+
                      |
                    COBOL
                      |
               +------+------+
               |             |
              Db2           VSAM

O programador iniciante entrou na dungeon procurando descobrir qual arquitetura era "a moderna".

Saiu dela entendendo algo muito mais importante:

Arquitetura não é escolher a tecnologia mais nova. É compreender suficientemente bem o problema para saber onde cada tecnologia pertence.

Rick pega a espada.

O velho COBOL compila.

O CICS continua processando transações.

O microservice publica um evento.

A função serverless acorda.

MQ entrega uma mensagem.

Db2 confirma o COMMIT.

E, em algum canto escuro da dungeon, alguém propõe transformar os 847 programas COBOL em 847 microservices porque viu isso numa apresentação.

Rick olha para o programador.

O programador olha para Rick.

IF ARCHITECTURE-BY-HYPE
    MOVE 'RUN!' TO RECOMMENDATION
END-IF.

☕⚔️ Bem-vindo ao Bellacosa Mainframe. Aqui até o aventureiro Rank F aprende que o monstro mais perigoso da arquitetura continua sendo uma solução procurando um problema.

🧙‍♂️ GANDALF E O VSAM QUE ATRAVESSOU AS ERAS

 

☕ Um Café no Bellacosa Mainframe

🧙‍♂️ GANDALF E O VSAM QUE ATRAVESSOU AS ERAS

COBOL, KSDS, ESDS, RRDS, CI, CA, buffers, LSR, RLS, DFSMS, Extended Format, encryption, zHyperLink, DS8000, IBM z17 — e o dia em que um jovem programador descobriu que o arquivo de 50 anos atrás ainda não estava pronto para se aposentar.

Sob a tutela de Gandalf


🎬 PRÓLOGO — VOCÊ NÃO PASSARÁ... SEM ENTENDER O VSAM!

Imagine um jovem programador COBOL chegando pela primeira vez diante de um IBM z17.

Ele olha para aquela máquina moderna, lê sobre processadores poderosos, criptografia, inteligência artificial, aceleração de I/O, APIs, containers, Linux, cloud e uma quantidade quase assustadora de tecnologias.

Então abre um programa COBOL.

E encontra isto:

SELECT CLIENTES
       ASSIGN TO CLIENTES
       ORGANIZATION IS INDEXED
       ACCESS MODE IS RANDOM
       RECORD KEY IS COD-CLIENTE.

Mais abaixo:

MOVE 123456 TO COD-CLIENTE.

READ CLIENTES
    INVALID KEY
        DISPLAY 'CLIENTE NAO ENCONTRADO'
END-READ.

Ele olha novamente para o z17.

Olha para o programa.

Olha para o z17.

— Gandalf... não está faltando alguma coisa?

O velho mago apoia o cajado no chão.

— Não.

— Mas isso parece o mesmo COBOL que alguém poderia ter escrito décadas atrás!

Gandalf sorri.

Exatamente.

E aqui começa nossa aventura.

Porque talvez a coisa mais impressionante sobre VSAM no IBM z17 seja justamente aquilo que não mudou.

O programa continua dizendo:

READ CLIENTES

Só que o universo existente entre esse READ e os dados tornou-se extraordinariamente sofisticado.

Prepare o café.

Pegue o cajado.

Hoje vamos atravessar a Terra-média do DFSMS.


🧙 CAPÍTULO 1 — A PERGUNTA ERRADA: "QUAL É O NOVO VSAM DO z17?"

Quando uma nova geração IBM Z aparece, é natural perguntar:

O que mudou no VSAM?

Talvez imaginemos algo chamado:

VSAM 17

ou:

VSAM Next Generation

Talvez esperemos encontrar um comando COBOL novo:

READ CLIENTES
    WITH-Z17-TURBO-MODE
END-READ.

Não existe.

E isso não é uma deficiência.

É uma das maiores virtudes da arquitetura.

O IBM z17 não representa uma reinvenção da interface lógica do VSAM.

Continuamos reconhecendo conceitos históricos:

KSDS
ESDS
RRDS
LDS

Control Interval
Control Area

INDEX
AIX
PATH

READ
WRITE
REWRITE
DELETE
START
READ NEXT

Portanto, se você aprendeu VSAM em uma geração anterior do IBM Z, seu conhecimento não virou cinzas quando o z17 apareceu.

Gandalf poderia resumir assim:

"Nem toda tecnologia antiga precisa morrer para que o mundo evolua."

O segredo está nas camadas inferiores.


🗺️ CAPÍTULO 2 — O MAPA DA TERRA-MÉDIA DO VSAM

Quando ensinamos VSAM para iniciantes, geralmente desenhamos:

COBOL
  |
  v
VSAM
  |
  v
DISCO

Isso é útil.

Mas é como representar toda a Terra-média desenhando apenas:

CONDADO
   |
MORDOR

Há muita coisa no caminho.

Em um ambiente moderno, podemos imaginar algo mais próximo disto:

                 APLICAÇÃO
                     |
                   COBOL
                     |
            +--------+--------+
            |                 |
          BATCH              CICS
            |                 |
            +--------+--------+
                     |
                    VSAM
                     |
          +----------+----------+
          |          |          |
         NSR        LSR        RLS
                                |
                             SMSVSAM
                     |
                   DFSMS
                     |
             BUFFER MANAGEMENT
                     |
               MEDIA MANAGER
                     |
                I/O SERVICES
                     |
                  CACHE
                     |
               zHyperLink
                     |
                  DS8000
                     |
                   FLASH

Agora nossa pergunta muda.

Não é apenas:

"VSAM ficou diferente?"

Passa a ser:

"O que aconteceu com todas as camadas que atendem aquele velho READ COBOL?"

Essa é uma pergunta muito mais interessante.


🔑 CAPÍTULO 3 — KSDS: O ANEL CONTINUA SENDO O ANEL

Vamos começar pelo conhecido.

Um KSDS — Key Sequenced Data Set — permite localizar registros através de uma chave.

Imagine:

CUSTOMER.KSDS

contendo:

000001  BILBO BAGGINS
000002  FRODO BAGGINS
000003  SAMWISE GAMGEE
000004  PEREGRIN TOOK
000005  MERIADOC BRANDYBUCK

Seu programa pode fazer:

MOVE 000003 TO CUSTOMER-ID.

READ CUSTOMER-FILE
    KEY IS CUSTOMER-ID
END-READ.

O COBOL não precisa conhecer o endereço físico daquele registro.

É justamente para isso que existe VSAM.

Conceitualmente:

KEY
 |
 v
INDEX
 |
 v
SEQUENCE SET
 |
 v
DATA
 |
 v
RECORD

E aqui aparece uma primeira lição importante.

O programador trabalha com:

KEY -> RECORD

O VSAM resolve o restante.


📦 CAPÍTULO 4 — CONTROL INTERVAL: A CAIXA QUE CARREGA SEUS REGISTROS

Um registro VSAM não está simplesmente flutuando sozinho no storage.

Precisamos conhecer o Control Interval, nosso famoso CI.

Simplificando:

CONTROL INTERVAL
+-----------------------------------+
| RECORD | RECORD | RECORD | FREE   |
+-----------------------------------+

Vários CIs formam uma estrutura maior chamada Control Area, CA.

CONTROL AREA
|
+-- CI 01
+-- CI 02
+-- CI 03
+-- CI 04
+-- CI 05

Portanto:

REGISTRO
   ↓
CONTROL INTERVAL
   ↓
CONTROL AREA
   ↓
VSAM DATA SET

Essa organização continua fundamental.

E ela será importante quando chegarmos ao zHyperLink.

Guarde o CI no bolso.

Voltaremos a ele.


💥 CAPÍTULO 5 — O BALROG CHAMADO CI SPLIT

Imagine:

+-----------------------------+
| A | B | C | D | FREE        |
+-----------------------------+

Há espaço disponível.

Novos registros entram.

Depois temos:

+-----------------------------+
| A | B | C | D | E | F      |
+-----------------------------+

Chega outro registro que precisa ser colocado naquela sequência lógica.

Não existe espaço adequado.

O VSAM pode precisar realizar um:

CI SPLIT.

Em situações maiores podemos chegar a:

CA SPLIT.

E Gandalf aparece diante do Balrog:

"YOU SHALL NOT PASS!"

Infelizmente, o novo registro responde:

"Tenho WRITE autorizado pelo RACF."

E passa.

Brincadeiras à parte, splits podem ter impacto operacional e de performance.

Por isso existem parâmetros como:

FREESPACE

e decisões sobre:

CI SIZE
CA SIZE

Um z17 não elimina magicamente um dataset mal planejado.

Hardware mais rápido não substitui arquitetura.


🧠 CAPÍTULO 6 — O I/O MAIS RÁPIDO É AQUELE QUE NÃO EXISTE

Aqui está uma das dicas mais importantes deste artigo.

Imagine:

READ CUSTOMER
      |
      v
    VSAM
      |
      v
   STORAGE

Talvez você pense:

Precisamos acelerar o storage!

Calma, jovem Hobbit.

Primeiro pergunte:

Por que estamos indo ao storage?

Se a informação necessária já estiver disponível em buffer/cache, podemos evitar determinado acesso físico.

Conceitualmente:

READ
 |
 v
BUFFER?
 |
 +--- HIT ---> RECORD
 |
 +--- MISS --> I/O

Compare:

READ
 ↓
I/O
 ↓
STORAGE
 ↓
RETURN

com:

READ
 ↓
BUFFER HIT
 ↓
RETURN

É por isso que buffering continua tão importante.

Não adianta possuir um storage absurdamente rápido se a aplicação estiver produzindo I/O desnecessário.


🧙‍♂️ CAPÍTULO 7 — NSR, LSR E RLS: TRÊS MAGOS CHEGAM À REUNIÃO

Você encontrará três siglas importantes no universo VSAM:

NSR
LSR
RLS

NSR — Non-Shared Resources

É o modelo convencional em que recursos utilizados no acesso ficam associados ao processamento daquele dataset/contexto.

LSR — Local Shared Resources

Permite compartilhamento de pools de buffers entre datasets VSAM dentro do contexto apropriado. É particularmente conhecido no universo CICS.

RLS — Record Level Sharing

Aqui nossa aventura cresce bastante.

Agora podemos pensar em múltiplos acessos compartilhados:

          CICS A
             |
             |
CICS B ---- VSAM ---- CICS C
             |
             |
          CICS D

E começam a aparecer problemas que não existem quando imaginamos apenas:

PROGRAMA -> ARQUIVO

Agora precisamos pensar em:

locking
serialization
sharing
consistency
recovery

Bem-vindo ao VSAM de produção.


🌍 CAPÍTULO 8 — A SOCIEDADE DO ANEL ENCONTRA O PARALLEL SYSPLEX

Imagine três sistemas:

LPAR A
  |
CICS A
  |
  +-----------+
              |
LPAR B        |
  |           |
CICS B -------+---- VSAM
              |
LPAR C        |
  |           |
CICS C -------+

Não queremos necessariamente limitar determinado dado a uma única região CICS ou sistema.

Em arquiteturas de alta disponibilidade e compartilhamento, RLS torna-se extremamente importante.

Agora aquele inocente:

READ CUSTOMER-FILE

faz parte de um universo distribuído dentro da arquitetura do próprio mainframe.

Isso é algo que surpreende muitos iniciantes.

VSAM não precisa significar:

"Um arquivo usado por um programa."

Pode participar de uma infraestrutura extremamente sofisticada.


🏦 CAPÍTULO 9 — DFSMStvs: QUANDO VSAM APRENDE TRANSAÇÕES MAIS SOFISTICADAS

Agora chegamos a uma tecnologia que muitos programadores COBOL passam anos sem conhecer:

DFSMStvs — Transactional VSAM Services.

Imagine:

             CUSTOMER.KSDS
                  |
          +-------+-------+
          |               |
        CICS             BATCH
          |               |
        UPDATE          UPDATE
          |               |
          +-------+-------+
                  |
               DFSMStvs

O problema já não é simplesmente ler um registro.

Queremos coordenação transacional, recuperação e compartilhamento apropriado entre workloads.

Isso não transforma VSAM em Db2.

Repita comigo:

VSAM não virou Db2.

Mas também mostra como é inadequado chamar VSAM simplesmente de:

"arquivo velho do COBOL".

Existe muita infraestrutura ao redor dele.


⚡ CAPÍTULO 10 — GANDALF DESCOBRE O zHYPERLINK

Agora chegamos a uma das partes mais interessantes da história.

zHyperLink.

Tradicionalmente, pensamos em I/O aproximadamente assim:

CPU
 |
 v
I/O REQUEST
 |
 v
I/O INFRASTRUCTURE
 |
 v
STORAGE
 |
 v
COMPLETION
 |
 v
APPLICATION

A arquitetura assíncrona de I/O é uma das grandes forças históricas do mainframe.

A CPU não deveria simplesmente ficar sentada olhando para um dispositivo lento.

Só que storage mudou dramaticamente.

Memória, cache e flash mudaram as relações de tempo.

Em determinadas situações, tornou-se interessante oferecer um caminho de synchronous I/O de baixíssima latência.

Entra zHyperLink.

Simplificando brutalmente:

             VSAM READ
                 |
                 v
         operação elegível?
                 |
                SIM
                 |
                 v
            zHyperLink
                 |
                 v
          STORAGE CACHE
                 |
                 v
             RESPONSE

E isso pode reduzir significativamente a latência para operações elegíveis.


🧩 CAPÍTULO 11 — O CI QUE GUARDAMOS NO BOLSO VOLTOU

Lembra do Control Interval?

Agora ele volta à história.

Porque existe relação entre quantidade de dados da operação e elegibilidade para determinados caminhos de I/O.

No ambiente moderno, parâmetros relacionados ao zHyperLink permitem controlar limites de leitura e explorar capacidades mais recentes de aceleração.

Portanto algo que aprendemos no primeiro curso de VSAM:

CI SIZE

continua conversando com uma infraestrutura que surgiu décadas depois.

Veja a beleza disso:

         DESIGN VSAM
              |
           CI SIZE
              |
              v
       TAMANHO DA LEITURA
              |
              v
        MEDIA MANAGER
              |
              v
       I/O ELIGIBILITY
              |
              v
         zHyperLink

Um conceito antigo continua relevante em uma máquina moderníssima.

Isso é mainframe.


⚠️ CAPÍTULO 12 — NÃO USE MAGIA SEM SABER O FEITIÇO

Neste momento alguém certamente perguntará:

Então devemos mudar todos os CIs para 16K?

NÃO!

Gandalf bate o cajado no chão.

Esse é exatamente o tipo de tuning que produz desastre:

ALGUÉM DISSE QUE 16K É MAIS RÁPIDO

Logo:

ALTERE TUDO!

Não.

O comportamento depende de:

record size
access pattern
random access
sequential access
insert rate
free space
buffering
RLS
cache
workload

Uma aplicação fazendo:

READ RANDOM
READ RANDOM
READ RANDOM

não possui necessariamente o mesmo perfil de:

START
READ NEXT
READ NEXT
READ NEXT
READ NEXT

E nenhuma das duas é necessariamente equivalente a uma carga massiva de inserções.

Meça antes de mudar.

Essa é uma das regras de ouro do mainframe.


📊 CAPÍTULO 13 — SMF E RMF: AS PALANTÍRI DA PERFORMANCE

Gandalf não faz tuning dizendo:

"Tenho a impressão de que está mais lento."

Ele consulta as Palantíri.

No z/OS temos instrumentos muito melhores:

SMF
RMF

Se você migrou determinada carga para uma plataforma mais nova e deseja saber o que aconteceu, investigue.

Observe coisas como:

CPU
elapsed time
I/O rate
I/O response time
EXCP
cache behavior
buffer behavior
locking
RLS activity
synchronous I/O
CI/CA splits

O método correto é:

BASELINE
   |
   v
MUDANÇA
   |
   v
NOVA MEDIÇÃO
   |
   v
COMPARAÇÃO
   |
   v
CONCLUSÃO

Não:

MIGRAMOS PARA z17
       |
       v
DEVE ESTAR MAIS RÁPIDO

"Deve" é uma palavra perigosa em Capacity Planning.


🏎️ CAPÍTULO 14 — MÁQUINA MAIS RÁPIDA NÃO SIGNIFICA TRANSAÇÃO MAIS RÁPIDA

Considere:

CUSTOMER.KSDS

200.000.000 registros

e:

CICS
8.000 READs/s

Migramos para uma infraestrutura mais nova.

Depois descobrimos:

CPU ↓

Excelente!

Mas:

RESPONSE TIME =

praticamente igual.

Como?

Porque talvez a transação esteja esperando:

I/O

ou:

LOCK

ou:

MQ

ou:

Db2

ou:

NETWORK

ou:

API

ou outra dependência.

Performance é uma corrente.

Acelerar um elo que não é o gargalo não acelera necessariamente a corrente inteira.


🗜️ CAPÍTULO 15 — EXTENDED FORMAT: VSAM GANHOU UMA MOCHILA NOVA

Outro conceito que o iniciante precisa conhecer é Extended Format.

Pense:

VSAM
 |
 +-- Conventional
 |
 +-- Extended Format

Com Extended Format entram possibilidades importantes associadas ao gerenciamento moderno de datasets, incluindo recursos como:

Data Striping
Compression
Extended Addressability
Encryption
System Managed Buffering

Isso significa que dois programas podem enxergar:

CUSTOMER.KSDS

enquanto por baixo existem características bastante diferentes.

O programa continua:

READ CUSTOMER-FILE

A infraestrutura pode estar fazendo muito mais.


📏 CAPÍTULO 16 — 4 GB JÁ FOI O TAMANHO DE SMAUG

Hoje alguém olha para:

4 GB

e pensa:

Só isso?

Historicamente, 4 GB já representou um limite enorme.

À medida que datasets cresceram, mecanismos como Extended Addressability tornaram possível ultrapassar limitações tradicionais.

Essa é outra lição interessante da história do mainframe.

A arquitetura não foi criada prevendo tudo que existiria cinquenta anos depois.

Ela foi evoluída.

Pense na sequência:

VSAM
1970s
 |
1980s
 |
1990s
 |
2000s
 |
2010s
 |
2020s
 |
IBM z17

Pouquíssimas tecnologias de infraestrutura possuem uma linhagem operacional comparável.


🔐 CAPÍTULO 17 — O REGISTRO PODE ESTAR CRIPTOGRAFADO E O COBOL NEM SABE

Agora imagine:

READ CUSTOMER-FILE
END-READ.

O programa não contém:

DECRYPT CUSTOMER

nem:

CALL AES

nem precisa carregar manualmente uma biblioteca criptográfica para cada READ.

A proteção dos dados pode acontecer em camadas inferiores da infraestrutura.

Conceitualmente:

COBOL
  |
 VSAM
  |
DFSMS
  |
ENCRYPTION
  |
STORAGE

Essa separação de responsabilidades é poderosa.

O programador trabalha com:

registro

A plataforma trabalha com:

proteção do dado

Isso permite modernizar requisitos de segurança sem obrigatoriamente reescrever milhões de linhas de aplicação.


🧙‍♀️ CAPÍTULO 18 — SYSTEM MANAGED BUFFERING

Outro conceito importante é o System Managed Buffering — SMB.

O nome praticamente explica a proposta.

Em vez de depender exclusivamente de escolhas estáticas e históricas sobre buffers, permitimos que mecanismos do sistema participem da estratégia.

Voltemos à nossa regra:

O I/O mais rápido é aquele que não precisa acontecer.

Temos:

APPLICATION
     |
    VSAM
     |
   BUFFER
     |
   CACHE
     |
     I/O
     |
  STORAGE

Quanto mais cedo conseguirmos satisfazer a necessidade, melhor.

Mas novamente:

não existe configuração universal perfeita.

Batch sequencial não é CICS random.

Leitura não é inserção.

Arquivo pequeno não é arquivo gigantesco.

Performance engineering exige contexto.


☁️ CAPÍTULO 19 — E O VSAM COMEÇA A OLHAR PARA A CLOUD

Uma das direções interessantes do ecossistema moderno é permitir que dados tradicionalmente residentes no ambiente z/OS participem mais facilmente de outros fluxos.

A evolução do DFSMS e mecanismos de Cloud Data Access aproxima datasets do mundo de object storage e processos modernos de movimentação de dados.

O desenho conceitual começa a parecer:

VSAM
 |
DFSMS
 |
Cloud Data Access
 |
Object Storage

Isso muda nossa maneira de pensar modernização.

Durante anos, muita gente tratou modernização como:

REMOVER O MAINFRAME

Hoje existe uma abordagem muito mais interessante:

MANTER O QUE FUNCIONA
       +
INTEGRAR COM O NOVO

Gandalf aprovaria.

Não precisamos destruir Minas Tirith para instalar Wi-Fi.


🧬 CAPÍTULO 20 — VSAM, JSON E O MUNDO MODERNO

Outra fronteira interessante é a transformação de registros tradicionais em representações modernas.

Imagine um copybook:

01 CUSTOMER.
   05 CUSTOMER-ID    PIC 9(08).
   05 CUSTOMER-NAME  PIC X(40).
   05 CUSTOMER-CITY  PIC X(30).

O mundo COBOL enxerga isso perfeitamente.

Uma aplicação moderna talvez prefira:

{
  "customerId": 317,
  "customerName": "Gandalf",
  "customerCity": "Valfenda"
}

Esses dois universos não precisam necessariamente ser inimigos.

Podemos construir pontes:

COPYBOOK
   |
   v
RECORD
   |
   v
TRANSFORMATION
   |
   v
JSON

Esse é um dos princípios centrais da modernização contemporânea do mainframe:

Modernizar o acesso não significa obrigatoriamente substituir o dado.


🏛️ CAPÍTULO 21 — VSAM NÃO É UM BANCO RELACIONAL

Precisamos colocar uma placa gigantesca aqui.

VSAM != Db2

VSAM possui características extremamente poderosas:

indexed access
sequential access
direct access
buffering
sharing
locking infrastructure
recovery integration

Mas não oferece o modelo relacional do Db2.

No Db2 posso pensar:

SELECT NAME
FROM CUSTOMER
WHERE CITY = 'HOBBITON'
ORDER BY NAME;

Em um KSDS tradicional, a chave e a organização dos dados têm uma importância estrutural enorme.

VSAM é brilhante quando o problema é algo parecido com:

KEY
 |
 v
RECORD

Db2 resolve outra classe de problemas.

Escolher tecnologia significa entender o problema.

Não escolher a tecnologia mais nova.


🧓 CAPÍTULO 22 — "MAS VSAM NÃO É VELHO?"

Sim.

E essa pergunta sozinha não significa absolutamente nada.

Um martelo é velho.

A roda é velha.

SQL é velho.

TCP/IP é velho.

COBOL é velho.

Unix é velho.

A pergunta arquitetural correta é:

Resolve o problema adequadamente?

Imagine:

CICS
 |
COBOL
 |
VSAM KSDS

processando milhares de transações com:

alta disponibilidade
baixo response time
previsibilidade
recuperação
décadas de estabilidade

Qual é o business case para substituí-lo?

"É antigo" não é business case.

Agora, se existem problemas como:

alto custo operacional
dificuldade de integração
limitações funcionais
escassez de conhecimento
problemas de escalabilidade
requisitos novos

a conversa muda.

Arquitetura começa pelo problema.


🔬 CAPÍTULO 23 — PASSO A PASSO: INVESTIGANDO VSAM EM UM AMBIENTE MODERNO

Se você é um Padawan COBOL — ou Hobbit COBOL, já que Gandalf assumiu a aula — siga esta sequência.

Passo 1 — descubra a organização

Pergunte:

KSDS?
ESDS?
RRDS?
LDS?

Passo 2 — descubra como é acessado

Sequential?
Random?
Dynamic?

Passo 3 — descubra quem usa

Batch?
CICS?
Ambos?

Passo 4 — examine a definição

Procure entender:

KEYS
RECORDSIZE
CONTROLINTERVALSIZE
FREESPACE
SHAREOPTIONS
DATACLASS
STORCLAS
MGMTCLAS

Não saia alterando.

Primeiro entenda.

Passo 5 — descubra o buffering

Pergunte:

NSR?
LSR?
RLS?
SMB?

Passo 6 — descubra o comportamento

Observe:

READ
WRITE
REWRITE
DELETE
READ NEXT

Passo 7 — procure sinais de problema

Investigue:

I/O excessivo
splits
lock contention
response time
elapsed time
CPU
buffer misses

Passo 8 — use telemetria

Entre no mundo:

SMF
RMF
CICS statistics
VSAM statistics

Passo 9 — crie baseline

Nunca diga:

"Ficou melhor."

Diga:

ANTES
CPU       = X
I/O       = Y
ELAPSED   = Z
RESPONSE  = W

DEPOIS
CPU       = ...
I/O       = ...
ELAPSED   = ...
RESPONSE  = ...

Agora temos engenharia.

Passo 10 — mude UMA coisa

Não altere simultaneamente:

CI
FREESPACE
buffers
storage
programa
CICS

e depois pergunte qual alteração funcionou.

Você jamais saberá.


🎒 CAPÍTULO 24 — CURIOSIDADES PARA LEVAR NA MOCHILA

Curiosidade 1: VSAM surgiu na década de 1970 e continua operacionalmente relevante em plataformas IBM Z modernas.

Curiosidade 2: conceitos aparentemente antigos, como CI e CA, continuam importantes mesmo quando a infraestrutura utiliza flash, grandes caches e mecanismos modernos de I/O.

Curiosidade 3: um programa COBOL pode continuar usando praticamente a mesma lógica de acesso enquanto hardware, storage, segurança e sistema operacional mudaram várias gerações.

Curiosidade 4: VSAM pode participar de arquiteturas compartilhadas muito mais sofisticadas do que a caricatura "programa abre arquivo".

Curiosidade 5: acelerar CPU não necessariamente reduz response time quando o gargalo está em I/O, locks ou outra dependência.

Curiosidade 6: evitar um I/O geralmente é mais interessante do que simplesmente tornar aquele I/O mais rápido.


🥚 CAPÍTULO 25 — O EASTER EGG DAS 03:17

São 03:17 da madrugada.

O telefone toca.

Produção.

O operador informa:

"O CICS está lento."

O jovem programador pergunta:

— Deve ser CPU?

Gandalf responde:

— Não sabemos.

— Storage?

— Não sabemos.

— VSAM?

— Não sabemos.

— Então o que fazemos?

Gandalf olha para o monitor e responde:

"Um mago não adivinha um gargalo. Ele chega exatamente quando as métricas dizem onde procurar."

Abrimos SMF.

Analisamos RMF.

O processador estava tranquilo.

Storage também.

Depois de muita investigação...

...descobrimos uma aplicação segurando locks muito mais tempo do que deveria.

O jovem olha para Gandalf.

— Então comprar um z17 maior não resolveria?

Gandalf acende o cachimbo.

— Agora você está começando a entender performance.


🧭 CAPÍTULO 26 — O QUE REALMENTE MUDOU?

Finalmente podemos responder à pergunta original.

Para o programador COBOL?

Pouco.

Ele continua conhecendo:

OPEN
READ
WRITE
REWRITE
DELETE
START
READ NEXT
CLOSE

Para a organização lógica?

Continuamos reconhecendo:

KSDS
ESDS
RRDS
LDS
CI
CA
AIX
PATH

Para a infraestrutura?

A história é completamente diferente.

Temos um universo envolvendo:

DFSMS
Extended Format
SMB
RLS
DFSMStvs
compression
encryption
cache
Media Manager
zHyperLink
modern storage
Parallel Sysplex
Cloud Data Access

É aqui que está a evolução.


🧙‍♂️ EPÍLOGO — O VSAM NÃO PRECISOU SE TORNAR OUTRA COISA

Ao final da aventura, nosso jovem programador retorna ao mesmo código:

MOVE CUSTOMER-ID TO WS-CUSTOMER-ID.

READ CUSTOMER-FILE
    INVALID KEY
       DISPLAY 'NOT FOUND'
END-READ.

Agora ele não enxerga apenas quatro linhas de COBOL.

Enxerga:

                   COBOL
                     |
                   READ
                     |
                    VSAM
                     |
             +-------+-------+
             |       |       |
            NSR     LSR     RLS
                             |
                          SMSVSAM
                     |
                   DFSMS
                     |
             EXTENDED FORMAT
                     |
                 BUFFERING
                     |
                MEDIA MANAGER
                     |
                 I/O SERVICES
                     |
                  zHyperLink
                     |
                    CACHE
                     |
                   DS8000
                     |
                 IBM Z17

E finalmente entende por que VSAM ainda é fascinante.

A genialidade não está em permanecer congelado em 1974.

Está em permitir que a interface conhecida pela aplicação sobreviva enquanto praticamente todo o universo existente debaixo dela evolui.

O programa pede:

READ

VSAM responde:

"Deixe comigo."

E entre essas duas frases podem existir cinquenta anos de engenharia.

Gandalf pega o cajado e começa a caminhar em direção ao próximo sistema.

O jovem programador pergunta:

— Mestre, então nunca devemos substituir VSAM?

Gandalf para.

Olha para trás.

— Eu não disse isso.

— Então quando devemos substituir?

O velho mago sorri.

"Quando você conseguir demonstrar qual problema está tentando resolver."

Silêncio no datacenter.

Nenhum Balrog.

Nenhum ABEND.

Apenas o som distante de um job terminando:

IEF142I JOB STEP WAS EXECUTED
COND CODE 0000

E em algum lugar de uma LPAR, um programa escrito décadas atrás executa novamente:

READ CUSTOMER-FILE

sobre uma infraestrutura que seu autor jamais poderia ter imaginado.

☕ Moral da história

No mainframe, compatibilidade não significa ausência de inovação.

Às vezes é justamente o contrário.

A maior demonstração de engenharia é permitir que tudo mude sem obrigar aquilo que funciona a mudar junto.

E antes de sair alterando CISIZE, FREESPACE, buffers ou qualquer outra coisa porque alguém prometeu performance...

lembre-se da primeira regra de Gandalf para o jovem analista de performance:

"Você não passará... para produção sem medir primeiro."

sábado, 29 de agosto de 2026

CRUD Walker — Quando Chuck Norris Auditou um Cadastro COBOL, Encontrou Cinquenta Clientes na WORKING-STORAGE e Descobriu que o UPDATE Fugiu Antes da Compilação

 

Bellacosa Mainframe 

☕ Um Café no Bellacosa Mainframe

CRUD Walker — Quando Chuck Norris Auditou um Cadastro COBOL, Encontrou Cinquenta Clientes na WORKING-STORAGE e Descobriu que o UPDATE Fugiu Antes da Compilação

Ou: o jovem padawan chamou o programa de CRUD, Chuck Norris contou apenas três letras, Igor tentou esconder os clientes dentro de um OCCURS e o mainframe perguntou onde estavam o arquivo, o FILE STATUS e o COMMIT



Prólogo — O cadastro que entrou no saloon com uma letra faltando

O programa compilava.

O menu aparecia.

Clientes podiam ser incluídos, consultados, listados e excluídos. Havia confirmação antes da exclusão, tratamento de opções inválidas e até reorganização da tabela depois que um registro era removido.

Igor olhou para a tela verde, ajeitou o chapéu e anunciou:

— Está pronto! Um CRUD completo de clientes em COBOL!

No fundo da sala, Chuck Norris levantou os olhos do relatório de compilação.

Não disse nada.

Apenas escreveu quatro letras no quadro:

C — CREATE
R — READ
U — UPDATE
D — DELETE

Depois examinou o menu:

1 - INCLUIR CLIENTE
2 - CONSULTAR CLIENTE
3 - LISTAR CLIENTES
4 - EXCLUIR CLIENTE
0 - SAIR

Chuck contou novamente.

Havia CREATE, READ e DELETE. O UPDATE não estava ali.

Igor tentou explicar que “listar” talvez pudesse ser considerado o U, mas o compilador pediu demissão antes de participar daquela discussão.

O projeto não era ruim. Pelo contrário: era um laboratório muito interessante para quem está aprendendo COBOL. Ele reunia estruturas de dados, controle de fluxo, validação, pesquisa, interação pelo terminal e manipulação de registros em memória.

Mas ainda era um CRD, não um CRUD completo.

A boa notícia é que acrescentar o UPDATE não exige demolir o programa. Exige amadurecer sua construção.

E é exatamente nessa evolução que aparecem algumas das lições mais valiosas do desenvolvimento corporativo.



1. Antes do código: o que significa CRUD?

CRUD é um acrônimo criado para representar as quatro operações fundamentais executadas sobre dados persistentes:

LetraPalavraOperação
CCreateCriar um registro
RReadLer ou consultar
UUpdateAlterar um registro existente
DDeleteExcluir um registro

Em um cadastro de clientes:

CREATE → cadastrar Paulo
READ   → consultar Paulo
UPDATE → mudar o telefone de Paulo
DELETE → remover ou inativar Paulo

Embora a sigla tenha ficado muito associada aos bancos de dados, essas operações podem ser simuladas em qualquer estrutura:

  • tabela OCCURS;

  • arquivo sequencial;

  • VSAM KSDS;

  • tabela Db2;

  • fila;

  • memória;

  • aplicação CICS;

  • serviço exposto por API.

O mecanismo muda, mas a intenção permanece.

No protótipo original, os clientes vivem dentro de uma tabela em memória. Isso permite estudar o comportamento do CRUD sem introduzir imediatamente JCL, arquivos, catálogos, VSAM, SQL, locks e unidades de trabalho.

É como aprender a estacionar em um pátio vazio antes de tentar fazê-lo na Avenida Paulista às seis da tarde.

Chuck Norris, naturalmente, estaciona o mainframe em uma vaga de motocicleta. Mas o jovem padawan deve começar com cinquenta registros.




2. Onde os clientes estão guardados?

A estrutura central do protótipo pode ser representada assim:

       01  WS-TABELA-CLIENTES.
           05 WS-CLIENTE OCCURS 50 TIMES.
              10 WS-CODIGO      PIC 9(05).
              10 WS-NOME        PIC X(40).
              10 WS-CPF         PIC X(11).
              10 WS-TELEFONE    PIC X(15).

O OCCURS 50 TIMES cria uma tabela com cinquenta posições.

Mas atenção: ele não cadastra cinquenta clientes.

Ele apenas reserva espaço para até cinquenta ocorrências da estrutura WS-CLIENTE.

Por isso, normalmente existe um contador:

       01  WS-CONTROLE.
           05 WS-TOTAL-CLIENTES     PIC 9(02) VALUE ZERO.
           05 WS-POSICAO            PIC 9(02) VALUE ZERO.
           05 WS-POSICAO-ENCONTRADA PIC 9(02) VALUE ZERO.

A tabela pode possuir cinquenta posições físicas, mas apenas as primeiras posições correspondentes a WS-TOTAL-CLIENTES são consideradas ocupadas.

Por exemplo:

PosiçãoCódigoNomeEstado
100001Ana MariaOcupada
200002Paulo HenriqueOcupada
300003Carla SouzaOcupada
4–50zeros/espaçosLivres

Nesse momento:

WS-TOTAL-CLIENTES = 03

O contador representa a fronteira entre o território ocupado e o deserto.

Se ele estiver incorreto, o programa poderá:

  • ignorar clientes válidos;

  • listar posições vazias;

  • sobrescrever registros;

  • pesquisar além da área útil;

  • tentar acessar uma ocorrência fora do limite.

Uma regra fundamental é:

0WS-TOTAL-CLIENTES500 \leq WS\text{-}TOTAL\text{-}CLIENTES \leq 50

Chuck Norris não ultrapassa o limite de uma tabela. A tabela aumenta o OCCURS quando percebe que ele chegou.



3. PIC: não é decoração, é contrato de dados

Um iniciante pode olhar para:

05 WS-CODIGO PIC 9(05).
05 WS-NOME   PIC X(40).

e pensar que PIC serve apenas para determinar o tamanho do campo.

Mas PICTURE descreve a natureza lógica do dado.

PIC 9(05)

significa um campo numérico com cinco posições.

PIC X(40)

significa um campo alfanumérico de quarenta posições.

Essa escolha deve refletir o significado do dado.

Código do cliente

Se o código sempre tiver cinco algarismos:

05 WS-CODIGO PIC 9(05).

Se puder aceitar letras:

05 WS-CODIGO PIC X(05).

CPF

O CPF contém números, mas não representa uma quantidade.

Não fazemos:

CPF + CPF
CPF / 2
média de CPF
juros sobre CPF

O CPF é um identificador. Por isso, uma representação alfanumérica costuma ser adequada:

05 WS-CPF PIC X(11).

Isso também preserva zeros à esquerda.

Telefone

Telefone também não é quantidade:

05 WS-TELEFONE PIC X(15).

Com PIC X, podemos admitir:

  • zeros à esquerda;

  • código internacional;

  • sinal +;

  • DDD;

  • diferentes tamanhos.

Uma curiosidade importante: dizer que um campo possui apenas dígitos não significa que ele deva ser numericamente armazenado. CEP, número de documento, código de barras e telefone são exemplos clássicos.

O dado pode parecer número sem ser matematicamente numérico.



4. O menu: onde EVALUATE controla o saloon

Uma aplicação textual normalmente apresenta as opções e recebe a escolha do usuário:

       1000-EXIBIR-MENU.
           DISPLAY "=============================="
           DISPLAY "       CADASTRO DE CLIENTES"
           DISPLAY "=============================="
           DISPLAY "1 - INCLUIR CLIENTE"
           DISPLAY "2 - CONSULTAR CLIENTE"
           DISPLAY "3 - LISTAR CLIENTES"
           DISPLAY "4 - ALTERAR CLIENTE"
           DISPLAY "5 - EXCLUIR CLIENTE"
           DISPLAY "0 - SAIR"
           DISPLAY "OPCAO: "
           ACCEPT WS-OPCAO.

Em seguida:

       1100-PROCESSAR-OPCAO.
           EVALUATE WS-OPCAO
               WHEN 1
                   PERFORM 2000-INCLUIR-CLIENTE
               WHEN 2
                   PERFORM 3000-CONSULTAR-CLIENTE
               WHEN 3
                   PERFORM 4000-LISTAR-CLIENTES
               WHEN 4
                   PERFORM 5000-ALTERAR-CLIENTE
               WHEN 5
                   PERFORM 6000-EXCLUIR-CLIENTE
               WHEN 0
                   MOVE "S" TO WS-FIM
               WHEN OTHER
                   DISPLAY "OPCAO INVALIDA"
           END-EVALUATE.

EVALUATE é apropriado porque o usuário escolhe uma alternativa entre várias possibilidades.

Seria possível usar vários IF, mas isso tornaria o fluxo menos legível:

IF WS-OPCAO = 1
   ...
ELSE
   IF WS-OPCAO = 2
      ...
   ELSE
      IF WS-OPCAO = 3

Depois de alguns níveis, Igor precisaria de um mapa, uma lanterna e uma autorização do RACF para encontrar o END-IF correto.



5. Nível 88: quando o número ganha significado

O COBOL permite associar nomes semânticos aos valores:

       01  WS-OPCAO                 PIC 9.
           88 OP-INCLUIR            VALUE 1.
           88 OP-CONSULTAR          VALUE 2.
           88 OP-LISTAR             VALUE 3.
           88 OP-ALTERAR            VALUE 4.
           88 OP-EXCLUIR            VALUE 5.
           88 OP-SAIR               VALUE 0.
           88 OPCAO-VALIDA          VALUE 0 THRU 5.

Agora é possível escrever:

       IF NOT OPCAO-VALIDA
           DISPLAY "OPCAO INVALIDA"
       END-IF

Em vez de perguntar “o valor está entre zero e cinco?”, o programa pergunta “a opção é válida?”.

Esse é um dos poderes discretos do COBOL: aproximar o código da linguagem do negócio.

Outro exemplo:

       01  WS-ENCONTRADO            PIC X VALUE "N".
           88 CLIENTE-ENCONTRADO    VALUE "S".
           88 CLIENTE-NAO-ENCONTRADO VALUE "N".

Então:

       IF CLIENTE-ENCONTRADO
           DISPLAY "CLIENTE LOCALIZADO"
       ELSE
           DISPLAY "CLIENTE NAO LOCALIZADO"
       END-IF

Chuck Norris não compara flags com "S". A flag pergunta a ele qual valor deve assumir.



6. Inclusão: criar não significa jogar dados na primeira vaga

Na inclusão, o programa precisa proteger alguns estados.

Antes de tudo:

       IF WS-TOTAL-CLIENTES >= 50
           DISPLAY "LIMITE DE CLIENTES ATINGIDO"
       END-IF

Depois, deve receber os dados em uma área temporária:

       01  WS-CLIENTE-ENTRADA.
           05 WS-ENT-CODIGO         PIC 9(05).
           05 WS-ENT-NOME           PIC X(40).
           05 WS-ENT-CPF            PIC X(11).
           05 WS-ENT-TELEFONE       PIC X(15).

Por que não gravar diretamente na tabela?

Porque o usuário pode:

  • informar código duplicado;

  • deixar o nome vazio;

  • digitar CPF inválido;

  • cancelar a operação;

  • interromper a entrada no meio.

Se o programa escrever diretamente na tabela, poderá criar um registro parcialmente válido.

O fluxo correto é:

Receber → Validar → Verificar duplicidade → Gravar → Incrementar

Exemplo:

       2000-INCLUIR-CLIENTE.
           IF WS-TOTAL-CLIENTES >= 50
               DISPLAY "TABELA CHEIA"
           ELSE
               INITIALIZE WS-CLIENTE-ENTRADA
               PERFORM 2100-RECEBER-DADOS
               PERFORM 2200-VALIDAR-DADOS

               IF DADOS-VALIDOS
                   MOVE WS-ENT-CODIGO
                     TO WS-CODIGO-PESQUISA

                   PERFORM 7000-LOCALIZAR-CLIENTE

                   IF CLIENTE-ENCONTRADO
                       DISPLAY "CODIGO JA CADASTRADO"
                   ELSE
                       ADD 1 TO WS-TOTAL-CLIENTES

                       MOVE WS-CLIENTE-ENTRADA
                         TO WS-CLIENTE(WS-TOTAL-CLIENTES)

                       DISPLAY "CLIENTE INCLUIDO"
                   END-IF
               END-IF
           END-IF.

O contador deve ser incrementado somente quando o registro estiver aprovado para entrar na tabela.



7. A busca é o coração compartilhado

Consulta, alteração e exclusão começam da mesma forma:

Localize o cliente pelo código.

Em vez de escrever três pesquisas diferentes, o programa deve possuir uma rotina reutilizável:

       7000-LOCALIZAR-CLIENTE.
           SET CLIENTE-NAO-ENCONTRADO TO TRUE
           MOVE ZERO TO WS-POSICAO-ENCONTRADA

           PERFORM VARYING WS-POSICAO FROM 1 BY 1
               UNTIL WS-POSICAO > WS-TOTAL-CLIENTES
                  OR CLIENTE-ENCONTRADO

               IF WS-CODIGO(WS-POSICAO)
                    = WS-CODIGO-PESQUISA
                   SET CLIENTE-ENCONTRADO TO TRUE
                   MOVE WS-POSICAO
                     TO WS-POSICAO-ENCONTRADA
               END-IF
           END-PERFORM.

Essa é uma busca linear.

No pior caso, ela examina todos os registros:

O(n)O(n)

Para cinquenta clientes, isso é mais do que suficiente.

Um iniciante pode ficar tentado a implementar imediatamente uma pesquisa binária com SEARCH ALL. Mas ela exige que a tabela esteja ordenada pela chave.

Sem ordenação garantida, a pesquisa binária pode procurar o cliente com velocidade impressionante no lugar errado.

Dica de Chuck Norris:

Primeiro faça a busca correta. Depois meça. Só então otimize.



8. Consulta e listagem não são a mesma coisa

Ambas pertencem ao READ, mas possuem objetivos diferentes.

Consulta

Procura um cliente específico:

       3000-CONSULTAR-CLIENTE.
           DISPLAY "CODIGO: "
           ACCEPT WS-CODIGO-PESQUISA

           PERFORM 7000-LOCALIZAR-CLIENTE

           IF CLIENTE-ENCONTRADO
               PERFORM 7100-MOSTRAR-CLIENTE
           ELSE
               DISPLAY "CLIENTE NAO ENCONTRADO"
           END-IF.

Listagem

Percorre todos os registros ativos:

       4000-LISTAR-CLIENTES.
           IF WS-TOTAL-CLIENTES = ZERO
               DISPLAY "NENHUM CLIENTE CADASTRADO"
           ELSE
               PERFORM VARYING WS-POSICAO FROM 1 BY 1
                   UNTIL WS-POSICAO > WS-TOTAL-CLIENTES

                   DISPLAY "CODIGO: "
                       WS-CODIGO(WS-POSICAO)
                   DISPLAY "NOME: "
                       WS-NOME(WS-POSICAO)
               END-PERFORM
           END-IF.

A consulta é acesso seletivo. A listagem é varredura.

Essa diferença aparecerá novamente no Db2:

SELECT ... WHERE CODIGO = ?

para consulta individual, e um cursor para múltiplos registros.



9. O UPDATE entra pela porta principal

Agora chegamos à letra desaparecida.

O UPDATE não cria uma nova posição e não remove a existente. Ele altera determinados atributos do cliente na mesma ocorrência.

Antes:

CampoValor
Código00025
NomePaulo Henrique
CPF12345678909
Telefone11999990000

Depois:

CampoValor
Código00025
NomePaulo Henrique Silva
CPF12345678909
Telefone11988887777

Observe:

  • o cliente continua na mesma posição;

  • o código permanece igual;

  • o contador não muda;

  • não há deslocamento de registros;

  • apenas determinados campos são substituídos.

Portanto:

CREATE → WS-TOTAL-CLIENTES aumenta
UPDATE → WS-TOTAL-CLIENTES não muda
DELETE → WS-TOTAL-CLIENTES diminui

Se uma alteração incrementar o total, o programa terá criado uma duplicata em vez de atualizar o registro.



10. A chave não deve ser tratada como um telefone

O código identifica o cliente:

05 WS-CODIGO PIC 9(05).

Nome, CPF e telefone são atributos.

Em geral, o UPDATE deve preservar a chave.

Permitir que o operador altere livremente o código pode causar:

  • duplicidade;

  • perda de referências;

  • quebra da ordenação;

  • inconsistência com outros arquivos;

  • dificuldade de auditoria;

  • relações órfãs em bancos de dados.

No protótipo, ainda não existem contas, contratos ou endereços vinculados. Mesmo assim, proteger a chave ensina a mentalidade correta.

Se realmente fosse necessário trocar o código, essa deveria ser uma operação especial, com verificação de duplicidade e atualização das referências relacionadas.

Curiosidade: em VSAM KSDS, a chave primária não é tratada como um campo comum regravável. Muitas vezes, mudar a chave exige excluir o registro antigo e gravar outro com a nova chave.

Ou seja: até o VSAM olha desconfiado quando Igor diz “vou apenas dar um MOVE na chave”.



11. Antes e depois: o mini-COMMIT do laboratório

A melhor construção para o UPDATE utiliza duas imagens:

       01  WS-CLIENTE-ANTES.
           05 WS-ANTES-CODIGO       PIC 9(05).
           05 WS-ANTES-NOME         PIC X(40).
           05 WS-ANTES-CPF          PIC X(11).
           05 WS-ANTES-TELEFONE     PIC X(15).

       01  WS-CLIENTE-DEPOIS.
           05 WS-DEPOIS-CODIGO      PIC 9(05).
           05 WS-DEPOIS-NOME        PIC X(40).
           05 WS-DEPOIS-CPF         PIC X(11).
           05 WS-DEPOIS-TELEFONE    PIC X(15).

Depois de localizar o cliente:

       MOVE WS-CLIENTE(WS-POSICAO-ENCONTRADA)
         TO WS-CLIENTE-ANTES

       MOVE WS-CLIENTE(WS-POSICAO-ENCONTRADA)
         TO WS-CLIENTE-DEPOIS

Os novos dados são aplicados apenas na imagem DEPOIS.

O registro oficial continua intacto até:

  • os campos serem validados;

  • as duplicidades serem verificadas;

  • o usuário confirmar;

  • o programa decidir efetivar a operação.

Depois da confirmação:

       MOVE WS-CLIENTE-DEPOIS
         TO WS-CLIENTE(WS-POSICAO-ENCONTRADA)

Esse MOVE funciona como uma espécie de commit lógico didático.

Não é um COMMIT real de banco de dados, mas a analogia é útil:

Protótipo em memóriaSistema transacional
Imagem ANTESEstado confirmado
Imagem DEPOISAlteração preparada
ValidaçãoRegras e constraints
ConfirmaçãoAprovação
MOVE finalCommit lógico
Descartar DEPOISRollback lógico

Chuck Norris faz COMMIT olhando para o banco. O Db2 confirma por respeito.



12. Pressionar Enter significa o quê?

Suponha:

NOME ATUAL: PAULO HENRIQUE
NOVO NOME [ENTER=MANTER]:

O usuário apenas pressiona Enter.

Existem duas interpretações:

  1. apagar o nome;

  2. manter o nome atual.

O programa deve definir explicitamente a regra.

Em um cadastro, uma boa escolha é:

Campo vazio mantém o valor anterior.

Exemplo:

       DISPLAY "NOVO NOME [ENTER=MANTER]: "
       ACCEPT WS-NOVO-NOME

       IF WS-NOVO-NOME NOT = SPACES
           MOVE WS-NOVO-NOME
             TO WS-DEPOIS-NOME
       END-IF

O mesmo vale para CPF e telefone.

Mas surge outra pergunta: como o usuário apaga intencionalmente um campo opcional?

Uma solução seria aceitar um comando especial:

ENTER = manter
*     = limpar
valor = substituir

Exemplo:

       EVALUATE TRUE
           WHEN WS-NOVO-TELEFONE = SPACES
               CONTINUE
           WHEN WS-NOVO-TELEFONE = "*"
               MOVE SPACES TO WS-DEPOIS-TELEFONE
           WHEN OTHER
               MOVE WS-NOVO-TELEFONE
                 TO WS-DEPOIS-TELEFONE
       END-EVALUATE.

Esse pequeno detalhe mostra que interface não é apenas ACCEPT e DISPLAY. Ela também é um contrato de significado.



13. O CPF novo pode pertencer a outro cliente

Se o CPF puder ser alterado, o programa precisa verificar duplicidade.

Mas há uma armadilha.

Ao procurar o novo CPF, o sistema encontrará o CPF do próprio cliente. Por isso, a validação deve ignorar a posição que está sendo atualizada:

       MOVE "N" TO WS-CPF-DUPLICADO

       PERFORM VARYING WS-POSICAO FROM 1 BY 1
           UNTIL WS-POSICAO > WS-TOTAL-CLIENTES
              OR WS-CPF-DUPLICADO = "S"

           IF WS-POSICAO NOT = WS-POSICAO-ENCONTRADA
              AND WS-CPF(WS-POSICAO) = WS-DEPOIS-CPF
               MOVE "S" TO WS-CPF-DUPLICADO
           END-IF
       END-PERFORM.

A expressão:

WS-POSICAO NOT = WS-POSICAO-ENCONTRADA

é essencial.

Sem ela, o sistema rejeitaria o CPF atual como duplicado de si mesmo.

É o equivalente cadastral de Chuck Norris ser barrado na porta porque sua fotografia se parece demais com ele.



14. O fluxo completo da alteração

Uma estrutura modular poderia ser:

       5000-ALTERAR-CLIENTE.
           DISPLAY "=== ALTERAR CLIENTE ==="
           DISPLAY "CODIGO: "
           ACCEPT WS-CODIGO-PESQUISA

           PERFORM 7000-LOCALIZAR-CLIENTE

           IF CLIENTE-NAO-ENCONTRADO
               DISPLAY "CLIENTE NAO ENCONTRADO"
           ELSE
               PERFORM 5100-PREPARAR-IMAGENS
               PERFORM 5200-MOSTRAR-DADOS-ATUAIS
               PERFORM 5300-RECEBER-NOVOS-DADOS
               PERFORM 5400-VALIDAR-ALTERACAO

               IF DADOS-VALIDOS
                   PERFORM 5500-MOSTRAR-COMPARACAO
                   PERFORM 5600-CONFIRMAR-ALTERACAO

                   IF ALTERACAO-CONFIRMADA
                       PERFORM 5700-EFETIVAR-ALTERACAO
                   ELSE
                       DISPLAY "ALTERACAO CANCELADA"
                   END-IF
               END-IF
           END-IF.

Essa divisão deixa cada parágrafo com uma responsabilidade.

Preparação

       5100-PREPARAR-IMAGENS.
           MOVE WS-CLIENTE(WS-POSICAO-ENCONTRADA)
             TO WS-CLIENTE-ANTES

           MOVE WS-CLIENTE(WS-POSICAO-ENCONTRADA)
             TO WS-CLIENTE-DEPOIS.

Entrada

       5300-RECEBER-NOVOS-DADOS.
           INITIALIZE WS-NOVO-NOME
                      WS-NOVO-CPF
                      WS-NOVO-TELEFONE

           DISPLAY "NOVO NOME [ENTER=MANTER]: "
           ACCEPT WS-NOVO-NOME

           DISPLAY "NOVO CPF [ENTER=MANTER]: "
           ACCEPT WS-NOVO-CPF

           DISPLAY "NOVO TELEFONE [ENTER=MANTER]: "
           ACCEPT WS-NOVO-TELEFONE.

Efetivação

       5700-EFETIVAR-ALTERACAO.
           MOVE WS-CLIENTE-DEPOIS
             TO WS-CLIENTE(WS-POSICAO-ENCONTRADA)

           DISPLAY "CLIENTE ALTERADO COM SUCESSO".


15. E se nada tiver mudado?

O usuário pode entrar na alteração e manter todos os campos.

Nesse caso:

       IF WS-CLIENTE-ANTES = WS-CLIENTE-DEPOIS
           DISPLAY "NENHUMA ALTERACAO INFORMADA"
           SET DADOS-INVALIDOS TO TRUE
       END-IF.

Isso evita apresentar:

CLIENTE ALTERADO COM SUCESSO

quando nada foi alterado.

Em sistemas corporativos, atualizações vazias também podem gerar efeitos desnecessários:

  • logs;

  • auditoria;

  • locks;

  • escrita em disco;

  • replicação;

  • triggers;

  • mensagens;

  • alteração de timestamp;

  • eventos para outros sistemas.

Uma operação tecnicamente válida pode ainda ser operacionalmente inútil.


16. Exclusão: fechar o buraco deixado na mesa

Considere:

PosiçãoCliente
1Ana
2Bruno
3Carla
4Diego

Ao excluir Bruno, a posição 2 ficaria vazia.

Para manter a tabela compacta, os registros posteriores são deslocados:

       PERFORM VARYING WS-POSICAO
           FROM WS-POSICAO-ENCONTRADA BY 1
           UNTIL WS-POSICAO >= WS-TOTAL-CLIENTES

           MOVE WS-CLIENTE(WS-POSICAO + 1)
             TO WS-CLIENTE(WS-POSICAO)
       END-PERFORM

       INITIALIZE WS-CLIENTE(WS-TOTAL-CLIENTES)
       SUBTRACT 1 FROM WS-TOTAL-CLIENTES

Depois:

PosiçãoCliente
1Ana
2Carla
3Diego
4vazia

O INITIALIZE da última posição é importante. Sem ele, uma cópia residual de Diego poderia permanecer na área livre.

A aplicação talvez não a listasse porque o contador agora seria 3, mas o dado antigo continuaria fisicamente na memória.

Essa é uma curiosidade importante:

Um registro pode deixar de existir logicamente e continuar presente fisicamente.

O mesmo princípio aparece em discos, bancos, caches, filas e arquivos temporários. “Excluir” nem sempre significa destruir imediatamente todos os bytes.



17. Exclusão física ou lógica?

Em sistemas corporativos, o cliente raramente é simplesmente apagado.

Pode haver:

  • contratos;

  • contas;

  • movimentações;

  • obrigações regulatórias;

  • auditorias;

  • investigações;

  • histórico de atendimento.

Por isso, o sistema pode usar um status:

       05 WS-STATUS PIC X.
          88 CLIENTE-ATIVO    VALUE "A".
          88 CLIENTE-INATIVO  VALUE "I".
          88 CLIENTE-BLOQUEADO VALUE "B".

Então o DELETE de negócio seria:

       SET CLIENTE-INATIVO TO TRUE

O registro continua armazenado, mas deixa de participar das operações normais.

A isso damos frequentemente o nome de exclusão lógica.

O problema é que a aplicação precisa lembrar-se de filtrar os inativos. Caso contrário, Igor “exclui” o cliente no menu, mas ele aparece novamente na listagem cinco minutos depois como um fantasma do Db2.



18. ACCEPT e DISPLAY não são CICS por encantamento

O protótipo usa:

ACCEPT
DISPLAY

Isso oferece uma interface textual, mas não comprova que o sistema seja uma transação CICS nem uma verdadeira tela 3270.

Dependendo do ambiente:

  • ACCEPT pode ler da entrada padrão;

  • DISPLAY pode escrever na saída padrão;

  • em GnuCOBOL, pode ser um terminal Windows ou Linux;

  • em batch z/OS, a entrada pode vir de SYSIN;

  • a saída pode aparecer em SYSOUT;

  • em CICS, a interação normalmente envolve EXEC CICS e mapas BMS.

Uma execução batch poderia receber:

//SYSIN DD *
1
00001
PAULO HENRIQUE
12345678909
11999990000
0
/*

Isso não representa um operador navegando por uma tela 3270. É um job consumindo dados previamente fornecidos.

Em CICS, a construção seria diferente. A aplicação normalmente envia a tela, encerra a task e volta quando o usuário responde. Esse é o modelo pseudoconversacional.

A lição é simples:

COBOL é a linguagem. z/OS é o sistema operacional. CICS é o monitor transacional. 3270 é o modelo de terminal. Eles convivem, mas não são sinônimos.



19. Memória não é persistência

Todos os clientes do protótipo vivem na WORKING-STORAGE.

Quando o programa termina, os dados desaparecem.

Isso significa que o cadastro atual oferece:

  • manipulação de registros;

  • estado durante a execução;

  • regras de validação;

  • experiência didática.

Mas ainda não oferece:

  • persistência;

  • recuperação;

  • acesso simultâneo;

  • auditoria;

  • compartilhamento;

  • backup;

  • restart;

  • histórico.

A memória é como a prancheta do atendente.

VSAM ou Db2 são o arquivo oficial da empresa.

Chuck Norris memoriza todos os clientes. O restante da equipe precisa de persistência.



20. Primeiro degrau: arquivo sequencial

Uma próxima versão poderia utilizar um arquivo:

       SELECT CLIENTES-FILE
           ASSIGN TO CLIENTES
           ORGANIZATION IS SEQUENTIAL
           FILE STATUS IS WS-FILE-STATUS.

E:

       FD CLIENTES-FILE.
       01 CLIENTES-RECORD.
          05 CLIENTE-CODIGO    PIC 9(05).
          05 CLIENTE-NOME      PIC X(40).
          05 CLIENTE-CPF       PIC X(11).
          05 CLIENTE-TELEFONE  PIC X(15).

Agora aparecem:

OPEN
READ
WRITE
CLOSE

E também:

FILE STATUS

O arquivo sequencial traz persistência, mas a atualização fica mais trabalhosa.

Para alterar um cliente:

  1. abrir o arquivo original;

  2. abrir um arquivo temporário;

  3. ler cada registro;

  4. gravar todos no temporário;

  5. quando encontrar o cliente, gravar a versão alterada;

  6. fechar os arquivos;

  7. substituir o original de maneira controlada.

É trabalhoso, mas ensina processamento batch real.



21. Segundo degrau: VSAM KSDS

Para acesso direto por código:

       SELECT CLIENTES-FILE
           ASSIGN TO CLIENTES
           ORGANIZATION IS INDEXED
           ACCESS MODE IS DYNAMIC
           RECORD KEY IS CLIENTE-CODIGO
           FILE STATUS IS WS-FILE-STATUS.

O CRUD passa a corresponder a:

OperaçãoVSAM
CriarWRITE
ConsultarREAD
AlterarREWRITE
ExcluirDELETE

Exemplo do UPDATE:

       READ CLIENTES-FILE
           KEY IS CLIENTE-CODIGO
       END-READ

       IF WS-FILE-STATUS = "00"
           MOVE WS-NOVO-NOME
             TO CLIENTE-NOME

           REWRITE CLIENTES-RECORD
           END-REWRITE

           IF WS-FILE-STATUS = "00"
               DISPLAY "CLIENTE ALTERADO"
           ELSE
               DISPLAY "ERRO NO REWRITE: "
                   WS-FILE-STATUS
           END-IF
       ELSE
           DISPLAY "CLIENTE NAO ENCONTRADO"
       END-IF.

Aqui, o FILE STATUS deixa de ser um detalhe e se torna parte da lógica.

Não basta executar REWRITE. É preciso perguntar ao sistema se ele conseguiu.



22. Terceiro degrau: Db2

No Db2:

UPDATE CLIENTE
   SET NOME     = :HV-NOME,
       CPF      = :HV-CPF,
       TELEFONE = :HV-TELEFONE
 WHERE CODIGO   = :HV-CODIGO

No COBOL:

       EXEC SQL
           UPDATE CLIENTE
              SET NOME     = :HV-NOME,
                  CPF      = :HV-CPF,
                  TELEFONE = :HV-TELEFONE
            WHERE CODIGO   = :HV-CODIGO
       END-EXEC.

Depois, o programa verifica SQLCODE:

       EVALUATE TRUE
           WHEN SQLCODE = ZERO
               EXEC SQL
                   COMMIT
               END-EXEC
               DISPLAY "CLIENTE ALTERADO"

           WHEN SQLCODE = 100
               DISPLAY "CLIENTE NAO ENCONTRADO"

           WHEN OTHER
               EXEC SQL
                   ROLLBACK
               END-EXEC
               DISPLAY "ERRO SQL: " SQLCODE
       END-EVALUATE.

Aqui aparece uma observação importante: dependendo do comando e da forma usada, “nenhuma linha atualizada” deve ser confirmado por diagnóstico apropriado, incluindo a quantidade de linhas afetadas. Não se deve imaginar que todo sucesso técnico corresponde a uma alteração de negócio.

O Db2 também introduz:

  • locks;

  • isolamento;

  • deadlock;

  • timeout;

  • integridade referencial;

  • constraints;

  • concorrência;

  • unidade de recuperação.

O protótipo pergunta:

Posso mudar este telefone?

O sistema corporativo pergunta:

Posso mudar este telefone, neste instante, sem violar regras, perder a atualização de outro usuário ou deixar metade da transação confirmada?



23. O problema dos dois operadores

Imagine dois usuários consultando o mesmo cliente:

Telefone atual: 11999990000

Operador A muda para:

11911112222

Operador B, que ainda vê a versão antiga, muda para:

11933334444

Se B gravar por último, a alteração de A poderá desaparecer.

Isso é chamado de lost update, ou atualização perdida.

A tabela em memória com um único usuário não mostra esse problema. Em um ambiente corporativo, ele precisa ser tratado por:

  • locks;

  • isolamento;

  • versionamento;

  • timestamp;

  • comparação da imagem anterior;

  • controle otimista de concorrência.

Uma estratégia seria atualizar somente se o registro ainda estiver na versão consultada:

UPDATE CLIENTE
   SET TELEFONE = :NOVO-TELEFONE,
       VERSAO   = VERSAO + 1
 WHERE CODIGO   = :CODIGO
   AND VERSAO   = :VERSAO-LIDA

Se nenhuma linha for atualizada, alguém modificou o registro antes.

Chuck Norris não sofre lost update. Quando ele altera uma linha, os outros usuários recebem um aviso antes mesmo de abrir a tela.



24. Passo a passo para construir o protótipo completo

Para um iniciante, eu seguiria esta ordem:

Passo 1 — Defina o registro

CODIGO
NOME
CPF
TELEFONE

Decida tamanhos e tipos conscientemente.

Passo 2 — Crie a tabela

OCCURS 50 TIMES

Mantenha um contador de registros ativos.

Passo 3 — Crie o menu

Use DISPLAY, ACCEPT e EVALUATE.

Passo 4 — Implemente a inclusão

Receba em área temporária, valide e somente depois grave.

Passo 5 — Centralize a pesquisa

Crie LOCALIZAR-CLIENTE e armazene a posição encontrada.

Passo 6 — Implemente consulta e listagem

Uma consulta por código e uma varredura completa.

Passo 7 — Implemente o UPDATE

Use imagens ANTES e DEPOIS, proteja a chave e peça confirmação.

Passo 8 — Implemente a exclusão

Localize, confirme, desloque os registros e diminua o contador.

Passo 9 — Trate limites e entradas inválidas

Teste tabela cheia, tabela vazia, código duplicado e cliente inexistente.

Passo 10 — Crie casos de teste

Não teste apenas o caminho feliz.



25. Roteiro de testes sob o olhar desconfiado de Chuck Norris

TesteResultado esperado
Incluir primeiro clienteTotal passa de 0 para 1
Incluir código repetidoInclusão recusada
Incluir 51º clienteLimite informado
Consultar cliente existenteDados exibidos
Consultar inexistenteMensagem controlada
Listar tabela vaziaNenhum cliente cadastrado
Alterar nomeMesma posição e mesmo código
Alterar CPF para CPF já usadoOperação recusada
Entrar no Update e não mudar nadaNenhuma alteração
Cancelar UpdateRegistro original preservado
Excluir primeiro clienteRegistros deslocados
Excluir cliente intermediárioTabela permanece compacta
Excluir último clienteÚltima posição inicializada
Cancelar exclusãoTotal e tabela permanecem iguais
Digitar opção inválidaMenu reapresentado
Encerrar e reabrirDados desaparecem na versão em memória

O último teste não é um defeito inesperado. É uma limitação conhecida da arquitetura.

Documentar limitações é uma forma de qualidade.





26. Easter eggs escondidos na WORKING-STORAGE

Easter egg 1 — O CRUD estava incompleto

O primeiro segredo estava no próprio acrônimo: faltava o U.

Easter egg 2 — Listar não cria outra letra

Consulta e listagem são duas formas de leitura. Portanto, ambas pertencem ao R.

Easter egg 3 — OCCURS 50 não significa cinquenta clientes

Significa espaço para cinquenta ocorrências. O contador informa quantas estão logicamente ocupadas.

Easter egg 4 — Excluir não apaga necessariamente os bytes

A exclusão lógica e os resíduos de memória mostram que existência física e existência de negócio são conceitos diferentes.

Easter egg 5 — O MOVE final imita um commit

As áreas ANTES e DEPOIS introduzem, em miniatura, o conceito de preparar, validar, confirmar ou abandonar uma mudança.

Easter egg 6 — O terminal pode não ser 3270

Uma tela verde não transforma automaticamente ACCEPT e DISPLAY em uma aplicação CICS.

Easter egg 7 — COBOL não significa necessariamente mainframe

COBOL pode rodar em outras plataformas. Para afirmar que é uma aplicação z/OS, é preciso demonstrar o ambiente, a compilação e a execução.

Easter egg 8 — O código mais importante pode ser o que não altera nada

A validação que impede uma operação indevida pode ser mais valiosa do que o MOVE que grava os dados.





Epílogo — O dia em que o UPDATE voltou ao menu

Ao final da revisão, o menu apareceu novamente:

1 - INCLUIR CLIENTE
2 - CONSULTAR CLIENTE
3 - LISTAR CLIENTES
4 - ALTERAR CLIENTE
5 - EXCLUIR CLIENTE
0 - SAIR

Chuck Norris examinou a WORKING-STORAGE.

Conferiu o limite de cinquenta posições.

Testou código duplicado.

Tentou atualizar um CPF já utilizado.

Pressionou Enter sem mudar nenhum campo.

Cancelou a alteração.

Excluiu o primeiro registro.

Depois encerrou o programa e confirmou que todos os clientes desapareceram, porque ainda estavam apenas na memória.

Igor respirou aliviado:

— Agora é um CRUD completo?

Chuck Norris respondeu:

— Agora ele possui as quatro operações. Completo é outra conversa.

E essa talvez seja a maior lição do projeto.

Um CRUD em memória pode ser excelente para aprender:

  • estruturação de dados;

  • lógica procedural;

  • modularização;

  • pesquisa;

  • validação;

  • estados;

  • inclusão;

  • consulta;

  • alteração;

  • exclusão.

Mas um sistema corporativo também exige:

  • persistência;

  • controle de concorrência;

  • segurança;

  • auditoria;

  • recuperação;

  • integridade;

  • testes;

  • tratamento de erros;

  • observabilidade;

  • operações transacionais.

O protótipo não precisa fingir que já é tudo isso.

Seu valor está justamente em mostrar uma evolução compreensível:

OCCURS em memória
        ↓
arquivo sequencial
        ↓
VSAM KSDS
        ↓
Db2
        ↓
CICS
        ↓
segurança, auditoria e produção

O jovem padawan que entende essa sequência deixa de ser alguém que apenas conhece comandos COBOL.

Ele começa a compreender como dados nascem, mudam, sobrevivem, desaparecem e precisam ser protegidos dentro de sistemas que não podem improvisar.

E, sob o olhar desconfiado de Chuck Norris, a regra final ficou registrada:

Um UPDATE não é apenas sobrescrever caracteres. É localizar a entidade correta, preservar sua identidade, preparar uma nova versão, validar as regras, impedir conflitos e somente então alterar o estado oficial.

Igor tentou acrescentar essa frase ao programa usando um DISPLAY.

Chuck Norris pediu que ele criasse primeiro o FILE STATUS.



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