☕ 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

quarta-feira, 18 de setembro de 2024

AIOps : Quando um Programador Embarca no Seaview e Descobre que o Verdadeiro Monstro do Oceano Não é um Polvo Gigante.

Bellacosa Mainframe apresenta o aiops

☕ Um Café no Bellacosa Mainframe

AIOps sem Mistérios para Programadores COBOL

Quando um Programador Embarca no Seaview e Descobre que o Verdadeiro Monstro do Oceano Não é um Polvo Gigante... É uma Anomalia de Performance Escondida Entre Milhões de Métricas

"Profundidade: 8.000 metros."

"Pressão externa: centenas de atmosferas."

"Silêncio absoluto."

No fundo do oceano não existe espaço para improvisação.

Não existe Ctrl+C.

Não existe reboot.

Não existe "vamos tentar novamente amanhã".

Uma pequena falha...

...e toda a missão termina.

Curiosamente, é exatamente assim que funciona um IBM Z.

Enquanto milhões de pessoas compram, transferem dinheiro, usam cartões, fazem PIX, reservam passagens e movimentam bolsas de valores, o mainframe continua trabalhando silenciosamente nas profundezas da infraestrutura mundial.

É justamente aí que nasce o universo do AIOps, do Performance Management e do Capacity Planning.

Prepare seu uniforme da Marinha Nelson Institute, embarque no USS Seaview, comandado pelo Almirante Harriman Nelson e pelo Capitão Lee Crane, porque hoje faremos uma viagem ao fundo do mar... das métricas do IBM Z.


Capítulo 1 — O Oceano Invisível do Mainframe

Todo iniciante imagina que um computador executa apenas programas.

Na realidade, um IBM Z executa milhares de atividades simultaneamente.

Enquanto seu programa COBOL faz um simples:

READ CLIENTES

o sistema inteiro está trabalhando.

Nos bastidores existem:

  • Dispatcher

  • PR/SM

  • WLM

  • zIIP

  • RMF

  • SMF

  • CICS

  • Db2

  • MQ

  • JES2

  • VSAM

  • RACF

  • DFSMS

  • Coupling Facility

  • IOS

  • Channel Subsystem

Todos gerando estatísticas.

Imagine centenas de sensores espalhados pelo casco do Seaview.

Cada sensor mede:

  • pressão

  • temperatura

  • velocidade

  • combustível

  • profundidade

  • oxigênio

  • consumo elétrico

Agora multiplique isso por dezenas de milhares.

É isso que o IBM Z mede continuamente.


Easter Egg nº 1

Na série Viagem ao Fundo do Mar, o Seaview parecia navegar calmamente.

Mas na sala de máquinas havia dezenas de oficiais monitorando centenas de instrumentos.

No IBM Z acontece exatamente o mesmo.

Você vê apenas uma tela 3270.

Por trás dela existe um oceano inteiro de telemetria.


Capítulo 2 — O erro que muita gente está cometendo

Com a chegada dos LLMs surgiu uma ideia perigosa.

"Agora basta perguntar para uma IA."

Será?

Imagine entrar no Seaview e perguntar:

— IA, estamos seguros?

Resposta:

— Sim.

Fim.

Mas...

E se existir uma microfissura no casco?

E se um sonar estiver apresentando ruído?

E se uma bomba hidráulica estiver começando a vibrar?

A IA respondeu.

Mas não analisou.

Essa é exatamente a diferença entre um chatbot e uma plataforma especializada como o IBM Z IntelliMagic Vision.


Informação não é conhecimento

Uma IA pode responder:

"A CPU está em 82%."

Ótimo.

Mas isso é bom?

Ruim?

Esperado?

Anormal?

Ela não sabe.

Porque falta contexto.

O especialista pergunta:

  • qual CPC?

  • qual LPAR?

  • qual horário?

  • qual workload?

  • qual Service Class?

  • qual política WLM?

  • houve IPL?

  • mudou o firmware?

  • houve novo package Db2?

  • apareceu nova aplicação Java?

  • aumentou MQ?

  • mudou o peso PR/SM?

É outro nível de investigação.


Capítulo 3 — O verdadeiro tesouro do oceano chama-se SMF

Poucos iniciantes conhecem o SMF.

Mas ele talvez seja o recurso mais valioso do z/OS.

SMF significa:

System Management Facility

Pense nele como o diário de bordo do Seaview.

Tudo é registrado.

Tudo.

Quem usou CPU.

Quem fez I/O.

Quem abriu datasets.

Quem executou CICS.

Quem acessou Db2.

Quem consumiu zIIP.

Quem gerou paging.

Quem alterou configuração.

Décadas de história ficam registradas.

Sem SMF...

não existe análise histórica.


Curiosidade

Muitas empresas possuem anos de dados SMF armazenados.

Algumas conseguem comparar o comportamento atual com períodos de cinco ou dez anos atrás.

É como comparar uma expedição submarina atual com os registros originais do Almirante Nelson.


Capítulo 4 — Uma imagem vale mais que mil RMFs

O artigo comenta algo extremamente importante.

Uma figura vale mais que mil palavras.

Observe mentalmente a topologia apresentada.

Diversos:

CPC

LPARs

Sysplex

Tudo conectado.

Em segundos o especialista entende:

Quem pertence a quem.

Quem compartilha recursos.

Quem faz parte do mesmo Sysplex.

Quem utiliza determinado processador.

Nenhum texto consegue transmitir isso tão rapidamente.


Easter Egg nº 2

No Seaview existia uma enorme mesa de navegação.

Ninguém decorava o oceano.

Eles olhavam o mapa.

O IntelliMagic faz exatamente isso.

Ele desenha o mapa do seu mainframe.


Capítulo 5 — O poder do Change Detection

Imagine esta situação.

Segunda-feira:

Tudo perfeito.

Terça-feira:

Usuários reclamando.

O que mudou?

Essa pergunta pode consumir dias de investigação.

Mas o IntelliMagic compara automaticamente períodos diferentes.

Ele verifica:

  • CPU

  • zIIP

  • Dispatch Time

  • Busy

  • Eligible Work

  • Utilização

  • Tendências

  • Desvios

Não apenas mostra valores.

Mostra mudanças.

E mais importante...

Mostra mudanças relevantes.


O segredo do desvio padrão

Imagine um sonar.

O ruído normal fica entre:

10 e 15 decibéis.

Hoje apareceu:

Nada mudou.

Agora imagine:

Tem algo enorme vindo na direção do submarino.

Foi isso que o desvio padrão detectou.

Mudanças realmente fora do comportamento esperado.

Não basta aumentar.

Precisa aumentar de forma estatisticamente significativa.


Capítulo 6 — Health Rating

Talvez a funcionalidade mais fascinante.

Imagine o painel do Seaview.

Luzes verdes.

Luzes amarelas.

Luzes vermelhas.

Você não precisa ler milhares de sensores.

Basta olhar o painel.

No IntelliMagic ocorre exatamente isso.

Cada sistema recebe indicadores como:

  • Dispatch Time

  • MVS Busy

  • LPAR Busy

  • zIIP

  • IOSQ

  • Pending

  • Connect

  • Interrupt

  • Page-ins

Em poucos segundos o especialista sabe onde investigar primeiro.


Dica Bellacosa

Nunca olhe apenas um indicador.

Performance é correlação.

CPU alta pode ser consequência.

Não a causa.


Capítulo 7 — Tendência vale mais que fotografia

Uma fotografia mostra um instante.

Um gráfico mostra uma história.

É por isso que Capacity Planning utiliza séries históricas.

Não interessa apenas saber:

Hoje = 70%.

Interessa descobrir:

Janeiro:

65%

Fevereiro:

67%

Março:

69%

Abril:

72%

Maio:

75%

Junho:

78%

Agora existe uma tendência.

Sem histórico...

não existe previsão.


Capítulo 8 — Capacity Planning

Aqui muitos iniciantes cometem outro erro.

Pensam:

Capacity Planning = CPU.

Não.

CPU é apenas uma peça.

O especialista observa:

CPU

Memória

I/O

Storage

Channels

Paging

Network

zIIP

MSU

Software

CICS

Db2

MQ

IMS

Batch

Online

WLM

Tudo ao mesmo tempo.

Porque gargalos raramente aparecem isolados.


Curiosidade

Em muitos ambientes o problema nunca foi CPU.

Foi um único volume DASD saturado.

Ou uma fila MQ crescendo.

Ou uma política WLM mal definida.

Ou uma consulta SQL sem índice.


Capítulo 9 — O verdadeiro papel do especialista

O artigo fala algo maravilhoso.

O maior problema não é coletar dados.

É interpretá-los.

Hoje qualquer ferramenta coleta milhões de métricas.

Mas poucas conseguem responder:

O que realmente importa?

Imagine o Seaview.

Existem dez mil instrumentos.

Mas apenas um oficial experiente percebe que pequenas vibrações significam falha futura.

É exatamente isso que faz um especialista em performance.


Capítulo 10 — Explainability

Uma IA responde.

O especialista explica.

Existe enorme diferença.

Imagine um diretor perguntando:

"Por que precisamos comprar outro CPC?"

Você responde:

"Porque a IA sugeriu."

A reunião termina.

Agora imagine responder:

  • crescimento médio de 18% ao ano;

  • tendência confirmada em 36 meses;

  • workloads Batch crescendo;

  • consumo zIIP estabilizado;

  • pico de MSU chegando ao limite contratual;

  • risco para SLA da aplicação bancária;

  • previsão estatística de saturação em oito meses.

Agora existe evidência.


Easter Egg nº 3

No Seaview, o Almirante Nelson nunca dizia apenas:

"Vamos mergulhar."

Ele mostrava:

  • cartas náuticas;

  • sonar;

  • profundidade;

  • corrente marítima;

  • combustível;

  • pressão.

Isso é explainability.


Capítulo 11 — IA não substitui Analytics

Esse talvez seja o maior ensinamento do artigo.

A IA facilita perguntas.

O IntelliMagic produz respostas confiáveis.

Pense assim.

ChatGPT é como um excelente oficial de comunicações.

Ele conversa.

Resume.

Explica.

O IntelliMagic é o centro de controle do submarino.

Recebe milhares de sinais.

Correlaciona.

Detecta anomalias.

Calcula riscos.

Prevê problemas.

Ambos trabalham juntos.

Jamais um substitui o outro.


Passo a passo de uma investigação de performance

Imagine que um gerente liga dizendo:

"O sistema ficou lento."

Como um especialista procede?

Passo 1 — Confirmar o sintoma

Foi CPU?

I/O?

Rede?

Storage?

Aplicação?


Passo 2 — Comparar com a baseline

Como era ontem?

Semana passada?

Mesmo horário?


Passo 3 — Procurar mudanças

Novo deploy?

Novo package?

Nova política WLM?

Novo firmware?

Novo microcódigo?


Passo 4 — Correlacionar métricas

CPU alta.

Mas também houve:

  • aumento de I/O;

  • queda no cache;

  • crescimento do MQ;

  • aumento de locks Db2.

Agora aparece a verdadeira causa.


Passo 5 — Avaliar impacto

Quem sofreu?

Clientes?

PIX?

Internet Banking?

Cartão?

Folha?

Ou apenas um batch interno?


Passo 6 — Recomendar ações

Redistribuir workload.

Aumentar zIIP.

Reconfigurar WLM.

Otimizar SQL.

Criar índices.

Mover datasets.

Alterar prioridades.


O futuro

A próxima geração de ferramentas será híbrida.

Imagine conversar com a plataforma:

"Quais sistemas apresentaram crescimento anormal?"

A IA responde.

Mas por trás dela existe um motor especializado analisando:

  • milhares de métricas;

  • estatísticas;

  • tendências;

  • Health Insights;

  • correlações;

  • previsões.

É exatamente essa união que o artigo chama de:

AI + Analytics.


Curiosidades Bellacosa

✅ Um único IBM Z pode produzir milhões de registros SMF por dia.

✅ O WLM ajusta prioridades automaticamente centenas de vezes por segundo para manter os objetivos de serviço.

✅ O zIIP pode descarregar grande parte do processamento elegível de Db2, XML, Java, criptografia e workloads analíticos, reduzindo custos de software em muitos cenários.

✅ Um problema aparentemente "de CPU" pode, na verdade, ser consequência de filas de I/O, contenção em locks Db2, espera por MQ ou políticas WLM inadequadas.

✅ Ferramentas como o IBM Z IntelliMagic Vision incorporam décadas de conhecimento de especialistas em performance, automatizando análises que antes exigiam anos de experiência.


Conclusão — A Verdadeira Viagem ao Fundo do Mar

Ao final da missão, o USS Seaview emerge lentamente das profundezas. A tripulação sobreviveu não porque tinha o sonar mais bonito ou o rádio mais moderno, mas porque soube interpretar corretamente cada sinal vindo do oceano.

No IBM Z acontece exatamente o mesmo.

Os gráficos, mapas de Sysplex, indicadores de saúde, detecção automática de mudanças e análises históricas são os "sonares" do mundo corporativo. Eles transformam bilhões de amostras de desempenho em conhecimento acionável.

A IA generativa representa o novo oficial de comunicações: traduz perguntas complexas para linguagem natural, resume informações e acelera o acesso ao conhecimento. Já plataformas como o IBM Z IntelliMagic Vision são o cérebro analítico do navio, capazes de correlacionar milhares de métricas, detectar riscos antes que se tornem incidentes e justificar cada conclusão com evidências.

Para o programador COBOL iniciante, a maior lição é simples: escrever um bom programa não significa apenas fazer a lógica funcionar. Significa entender como esse programa consome CPU, acessa VSAM e Db2, utiliza CICS, aproveita zIIP, respeita as metas do WLM e influencia todo o ecossistema do mainframe.

No universo Bellacosa Mainframe, o código é apenas a ponta do iceberg.

A verdadeira aventura começa quando você aprende a enxergar o oceano invisível que existe sob cada EXEC CICS, cada SELECT no Db2, cada mensagem no MQ e cada READ em um dataset. É nesse oceano que vivem os maiores desafios da engenharia de performance — e também onde se encontram os maiores tesouros de conhecimento para quem deseja se tornar um verdadeiro Mestre Jedi do Mainframe.

quinta-feira, 12 de setembro de 2024

Kojak Entra no CPD — O Dia em que um SQLCODE -911 Virou Suspeito e o Db2 Foi Chamado para Depor

 

Bellacosa Mainframe apresenta cobol e db2

☕ Um Café no Bellacosa Mainframe

Kojak Entra no CPD — O Dia em que um SQLCODE -911 Virou Suspeito e o Db2 Foi Chamado para Depor

Ou: como COBOL, SQL, DBRM, BIND, PACKAGE, access path, COMMIT, ROLLBACK, locking, CICS e um programador iniciante descobriram que, no mainframe, até um SELECT tem antecedentes

Nova York, 1973.

Um policial careca, impecavelmente vestido, andando pelas ruas com um pirulito na boca começa a resolver crimes enquanto solta ironias e uma pergunta que se tornaria inseparável do personagem:

“Who loves ya, baby?”

Era o tenente Theo Kojak.

A série Kojak, criada por Abby Mann e protagonizada por Telly Savalas, estreou na CBS em 24 de outubro de 1973 e permaneceu originalmente no ar até 1978. (Paramount Press Express)

Curiosamente, Kojak surgiu antes da série: Telly Savalas interpretou o personagem no telefilme The Marcus-Nelson Murders, de 1973, que funcionou como origem do programa. (Los Angeles Times)

E existe algo profundamente mainframe em Kojak.

Ele não olha apenas para o cadáver.

Olha para quem entrou, quem saiu, quem tinha autorização, quem estava segurando o recurso, quem alterou o registro e por que aquela história aparentemente perfeita não combina com as evidências.

Troque a delegacia por um CPD.

Troque o assassinato por uma transação travada.

Troque as testemunhas por logs.

E dê ao tenente um terminal 3270.

Temos nosso novo investigador Db2.



Prólogo — 03:17, alguma coisa morreu em produção

O telefone toca.

O programador COBOL iniciante atende.

— Produção está parada.

Cinco palavras capazes de transformar café em combustível nuclear.

Ele abre o fonte.

EXEC SQL
    SELECT SALDO
      INTO :WS-SALDO
      FROM CONTA
     WHERE NUMERO = :WS-CONTA
END-EXEC.

Olha novamente.

Nada parece errado.

Compilou.

Ontem funcionava.

O programador conclui:

— Deve ser o banco.

A porta do CPD abre.

Um homem careca entra lentamente, coloca um pirulito na boca e observa o terminal.

— O banco, baby?

Silêncio.

— Vamos começar novamente. Quem executou o SQL?

E aí descobrimos nosso primeiro problema.



1. COBOL não executa SQL sozinho

Quando vemos:

EXEC SQL
    SELECT ...
END-EXEC

é fácil imaginar que SELECT seja uma instrução COBOL.

Não é.

COBOL e SQL são linguagens diferentes trabalhando juntas.

Podemos imaginar três responsabilidades:

COBOL
   │
   ├── lógica da aplicação
   ├── cálculos
   ├── decisões
   └── fluxo
          │
          ▼
         SQL
          │
          └── declara quais dados queremos
                    │
                    ▼
                   Db2
                    │
                    └── determina como obtê-los

O COBOL pode dizer:

“Preciso consultar o saldo desta conta.”

O SQL expressa:

SELECT SALDO
FROM CONTA
WHERE NUMERO = :WS-CONTA

E o Db2 precisa resolver como encontrar aquele registro eficientemente.

Kojak tira o pirulito da boca.

— Então temos três testemunhas. COBOL diz uma coisa, SQL pede outra e Db2 faz o trabalho pesado.

Exatamente.



2. O primeiro interrogatório: as Host Variables

Observe:

WHERE NUMERO = :WS-CONTA

Por que existe aquele :?

Porque WS-CONTA pertence ao programa hospedeiro.

É uma host variable.

Temos uma fronteira:

       COBOL                     SQL

    WS-CONTA ───────────────► :WS-CONTA

    WS-SALDO ◄─────────────── :WS-SALDO

No comando:

EXEC SQL
    SELECT SALDO
      INTO :WS-SALDO
      FROM CONTA
     WHERE NUMERO = :WS-CONTA
END-EXEC

WS-CONTA fornece informação.

WS-SALDO recebe informação.

Parece simples.

Até aparecerem:

  • tipos incompatíveis;

  • valores NULL;

  • indicator variables;

  • truncamentos;

  • conversões;

  • nenhuma linha;

  • múltiplas linhas.

Kojak aponta para WS-CONTA.

— Interrogue esse sujeito primeiro. Todo mundo culpa o Db2 antes de perguntar o que mandou para ele.

Primeira regra da investigação:

entrada errada produz investigação errada.


3. O crime aconteceu antes da execução

Nosso iniciante acredita que o fonte vai diretamente para o compilador COBOL.

Kojak balança a cabeça.

— Baby... tem alguém faltando nessa história.

Quando existe SQL embutido, o SQL precisa ser processado.

No fluxo tradicional, podemos representar:

COBOL + SQL
     │
     ▼
PRECOMPILE
     │
     ├────────────► DBRM
     │
     ▼
COBOL modificado
     │
     ▼
COBOL COMPILER
     │
     ▼
OBJECT
     │
     ▼
LINK-EDIT
     │
     ▼
LOAD MODULE

O processamento SQL e o processamento COBOL são coisas distintas.

E acabamos de encontrar nosso primeiro suspeito misterioso.

DBRM.


4. DBRM — o dossiê policial do SQL

DBRM significa Database Request Module.

Não é o executável COBOL.

Não é a tabela.

Não é o banco.

Não é o programa completo.

Uma maneira didática de imaginá-lo é como o dossiê contendo informações sobre as requisições SQL extraídas do programa para uso posterior pelo Db2.

A documentação IBM descreve o DBRM dentro justamente desse processo de preparação das instruções SQL para o bind. (Wikipedia)

Imagine:

PROGRAMA ABC123

SQL 001
SELECT SALDO...

SQL 002
UPDATE CONTA...

SQL 003
INSERT MOVIMENTO...

O Db2 precisará conhecer essas requisições.

O DBRM entra nessa história.

Kojak pega a pasta.

— Agora temos antecedentes.


5. BIND — agora leve o suspeito para a delegacia

Aqui aparece uma palavra que todo programador COBOL/Db2 precisa conhecer:

BIND.

Simplificando bastante, durante o bind o Db2 trabalha com as informações SQL preparadas anteriormente e produz aquilo que será necessário para executar o SQL estático.

Temos:

DBRM
  │
  ▼
BIND PACKAGE
  │
  ▼
PACKAGE

Agora nossa investigação começa a ficar interessante.

Porque significa que existem dois universos relacionados:

             APLICAÇÃO

        ┌───────────────┐
        │               │
        ▼               ▼
      COBOL            SQL
        │               │
        ▼               ▼
 LOAD MODULE          DBRM
                        │
                        ▼
                      BIND
                        │
                        ▼
                     PACKAGE

É perfeitamente possível que alguém diga:

“Mas o COBOL compilou!”

Ótimo.

Isso prova apenas uma parte da história.

Kojak sorri.

— Compilou? Muito bonito. Agora me mostre o package.


6. PACKAGE — o personagem que o iniciante quase nunca conhece

O package contém informações necessárias para a execução das instruções SQL estáticas associadas à aplicação.

E aqui ocorre uma mudança mental importante.

O programa executável e o SQL preparado possuem processos relacionados, mas distintos.

Portanto:

SOURCE
  │
  ├──────── COBOL ────────► LOAD MODULE
  │
  └──────── SQL ─► DBRM ─► BIND ─► PACKAGE

Na execução, esses mundos precisam conversar corretamente.

É por isso que um problema de Db2 pode existir mesmo quando o compilador COBOL não reclamou.

O compilador não é Sherlock Holmes.

Muito menos Kojak.


7. “Mas quem decidiu usar aquele índice?”

Chegamos ao grande interrogatório.

Considere:

SELECT NOME,
       LIMITE,
       SALDO
FROM CLIENTE
WHERE CPF = :WS-CPF

O programador declarou o que deseja.

Não escreveu:

vá para cilindro X
abra página Y
ande 37 posições
leia registro Z

Essa é uma das grandes diferenças entre programação procedural e acesso relacional.

O Db2 possui um optimizer.

Conceitualmente:

             SQL
              │
              ▼
          OPTIMIZER
              │
       ┌──────┼──────┐
       │      │      │
       ▼      ▼      ▼
   índices estatísticas cardinalidade
       │      │      │
       └──────┼──────┘
              ▼
         ACCESS PATH
              │
              ▼
          EXECUÇÃO

O optimizer avalia alternativas e custos.

Pode considerar índices.

Pode considerar outras estratégias.

O resultado dessa decisão é fundamental para performance.

Kojak olha para o programador:

— Você escreveu o SELECT. Mas não decidiu necessariamente como ele encontraria o sujeito.

Perfeito.


8. RUNSTATS — quando a testemunha está dizendo a verdade de 2019

Agora temos uma situação deliciosa.

O programa não mudou.

O SQL não mudou.

A tabela não mudou estruturalmente.

Mas o desempenho ficou horrível.

Como?

Imagine que o Db2 esteja tomando decisões baseado em informações estatísticas inadequadas ou desatualizadas.

É como Kojak perguntar:

— Quantas pessoas vivem neste prédio?

E alguém responder:

— Doze.

— Quando você contou?

— Em 1997.

Temos um problema.

As estatísticas ajudam o optimizer a compreender características dos dados.

Daí a importância de operações como RUNSTATS.

Isso nos ensina uma lição extraordinária:

Performance SQL não está inteiramente dentro do fonte SQL.

Ela depende do ecossistema.


9. Índice não é pó mágico

O iniciante aprende:

Índice deixa SELECT rápido.

Depois cria índice para tudo.

Parabéns.

Acabamos de transformar uma boa ideia em um novo incidente.

Índices possuem custo.

Precisam ser mantidos.

INSERT, UPDATE e DELETE podem ter trabalho adicional quando índices associados precisam ser atualizados.

Portanto:

MAIS ÍNDICES

      não significa automaticamente

MAIS PERFORMANCE

A pergunta é:

qual índice atende quais padrões reais de acesso?

Kojak provavelmente perguntaria:

— Esse índice estava onde na noite do crime?


10. O SQLCODE chega para depor

Executamos:

EXEC SQL
    SELECT SALDO
      INTO :WS-SALDO
      FROM CONTA
     WHERE NUMERO = :WS-CONTA
END-EXEC

E agora?

Precisamos saber o resultado.

Entra o SQLCODE.

Didaticamente:

SQLCODE = 0
     │
     └── sucesso

SQLCODE positivo
     │
     └── condição/warning

SQLCODE negativo
     │
     └── erro

Um programador iniciante pode fazer:

IF SQLCODE NOT = ZERO
    DISPLAY 'ERRO DB2'
END-IF.

Kojak quase engole o pirulito.

Porque os códigos precisam ser interpretados, não simplesmente classificados como “deu certo/deu errado”.

O famoso +100, por exemplo, normalmente indica ausência de linha correspondente ou fim do conjunto de resultados conforme a operação.

Isso pode ser perfeitamente normal.

Pesquisar cliente inexistente não significa necessariamente que o banco “quebrou”.


11. Até que aparece o cadáver: SQLCODE -911

Agora temos drama.

O programa retorna:

SQLCODE = -911

E alguém grita:

— Db2 caiu!

Não necessariamente.

Temos uma pista ligada a situações envolvendo rollback provocado por deadlock ou timeout, conforme o contexto e reason code.

Kojak sorri.

Finalmente um crime digno dele.

Imagine:

TRANSAÇÃO A

LOCK RECURSO 1
      │
      ▼
PRECISA RECURSO 2


TRANSAÇÃO B

LOCK RECURSO 2
      │
      ▼
PRECISA RECURSO 1

Temos:

A espera B

B espera A

Os dois poderiam esperar até a aposentadoria do programador.

O sistema precisa resolver a situação.

Bem-vindo ao mundo de locking, timeout e deadlock.


12. ACID — a divisão de crimes financeiros

Imagine uma transferência:

CONTA A = 1000
CONTA B =  500

TRANSFERÊNCIA = 100

Queremos terminar:

A = 900
B = 600

Não queremos:

A = 900
B = 500

porque o sistema caiu no meio.

É aqui que as propriedades ACID entram em cena:

Atomicity — a unidade lógica precisa ser tratada de maneira indivisível quanto ao resultado transacional.

Consistency — regras de consistência devem permanecer válidas.

Isolation — transações concorrentes precisam coexistir sob regras controladas.

Durability — depois da confirmação, os resultados precisam possuir as garantias de persistência esperadas.

Esse não é detalhe acadêmico.

É o motivo pelo qual você consegue dormir depois de transferir dinheiro pelo banco.


13. COMMIT — pode liberar os suspeitos

Considere:

UPDATE CONTA A
       │
       ▼
UPDATE CONTA B
       │
       ▼
INSERT MOVIMENTO
       │
       ▼
     COMMIT

O COMMIT delimita a confirmação apropriada daquela unidade de trabalho.

Mas imagine:

UPDATE A       OK
UPDATE B       OK
INSERT         ERRO

Dependendo da lógica e do contexto transacional, podemos precisar desfazer alterações.

Entra:

ROLLBACK

Portanto:

        UNIT OF WORK

UPDATE
   │
UPDATE
   │
INSERT
   │
   ├──── tudo correto ───► COMMIT
   │
   └──── problema ───────► ROLLBACK

Essa dupla é parte central da engenharia transacional.


14. COMMIT também é performance

Agora vem uma sutileza importante.

Alguns iniciantes imaginam COMMIT apenas como:

salvar alterações.

Mas unidades de trabalho também estão relacionadas à utilização e liberação de determinados recursos e locks.

Imagine um batch processando:

10 registros
100 registros
10.000 registros
10.000.000 registros

sem pensar adequadamente na estratégia de commit.

Ele pode manter recursos por períodos indesejáveis, afetar concorrência e complicar recuperação.

Logo, frequência de commit não deveria ser escolhida com:

COMMIT a cada 1000

simplesmente porque alguém encontrou esse número num programa de 1987.

A estratégia depende da aplicação.


15. Então chega o CICS à delegacia

Até agora poderíamos estar pensando em batch.

Mas coloque a aplicação em ambiente transacional:

CLIENTE
   │
   ▼
CICS
   │
   ▼
PROGRAMA COBOL
   │
   ▼
SQL
   │
   ▼
DB2

Agora milhares de usuários podem executar transações.

Temos simultaneamente:

CICS transaction 001 ──┐
CICS transaction 002 ──┤
CICS transaction 003 ──┼──► Db2
CICS transaction 004 ──┤
CICS transaction 005 ──┘

Nesse momento, locking deixa de ser um capítulo de apostila.

Vira sobrevivência.


16. COBOL + Db2 Connect? Cuidado com essa simplificação

O infográfico original apresenta conceitualmente uma camada intermediária chamada Db2 Connect.

Aqui Kojak levantaria uma sobrancelha.

Db2 Connect não deve ser ensinado como passagem obrigatória de todo programa COBOL local no z/OS para Db2.

Dependendo do ambiente, temos diferentes mecanismos de attachment e execução.

Batch, CICS, IMS, TSO e aplicações distribuídas podem envolver arquiteturas diferentes.

Portanto:

COBOL → DB2 Connect → Db2

não é uma representação universal.

Esse é exatamente o tipo de simplificação que funciona num infográfico 101, mas precisa ser desmontada quando o aluno chega ao nível 201.


17. “COBOL cuida da regra; Db2 cuida dos dados”

Boa explicação.

Mas incompleta.

No mundo real, Db2 também possui recursos relacionados a:

  • constraints;

  • integridade referencial;

  • views;

  • triggers;

  • stored procedures;

  • functions.

Então podemos pensar:

COBOL
 │
 ├── fluxo
 ├── cálculo
 ├── regras da aplicação
 └── orquestração

DB2
 │
 ├── persistência
 ├── integridade
 ├── concorrência
 ├── recuperação
 ├── otimização
 └── acesso relacional

As responsabilidades precisam ser projetadas.

Não simplesmente presumidas.


18. Static SQL e Dynamic SQL entram na sala

Nosso exemplo:

EXEC SQL
    SELECT SALDO
    ...
END-EXEC

é um exemplo clássico de SQL embutido estático.

Conceitualmente:

STATIC SQL

conhecido durante
preparação/deployment
       │
       ▼
processamento
       │
       ▼
DBRM
       │
       ▼
BIND
       │
       ▼
PACKAGE

Mas existe SQL dinâmico.

Podemos ter situações nas quais a instrução é preparada durante a execução usando mecanismos como PREPARE e EXECUTE.

Isso oferece flexibilidade, mas muda aspectos da preparação e execução.

Novamente:

não existe “um é sempre melhor”.

Existe:

qual mecanismo atende melhor ao problema?


19. O crime perfeito: SELECT *

Kojak encontra:

SELECT *
FROM CLIENTE

Olha para o programador.

Olha novamente para a tela.

— Você precisa de todas essas colunas?

— Não.

— Então por que pediu?

Silêncio.

Essa pergunta vale ouro.

Evite transportar dados desnecessários.

Se precisa de:

NOME
SALDO

não peça quarenta colunas simplesmente porque:

SELECT *

é mais rápido de digitar.

Cinco segundos economizados na programação podem gerar trabalho desnecessário repetido milhões de vezes em produção.


20. Outro suspeito: SELECT dentro de LOOP

Agora Kojak encontra:

PERFORM 100000 TIMES

       SELECT ...

END-PERFORM

Acende a luz da sala de interrogatório.

Dependendo do problema, isso pode representar enorme quantidade de chamadas e processamento que talvez pudesse ser resolvida por uma estratégia SQL muito melhor.

O erro conceitual é tratar banco relacional como arquivo sequencial:

LEIA
LEIA
LEIA
LEIA
LEIA

SQL trabalha naturalmente com conjuntos.

Essa mudança de pensamento é enorme para quem vem de COBOL procedural.


21. Não coloque toda a investigação num único SQL monstruoso

Mas existe o extremo oposto.

Alguém aprende que SQL trabalha com conjuntos e produz:

SELECT
 JOIN
  JOIN
   JOIN
    CASE
     CASE
      SUBQUERY
       UNION
        CTE
         FUNCTION
          JOIN
           ...

O SQL parece o mapa genealógico de Game of Thrones.

SQL complexo não é automaticamente ruim.

Às vezes uma operação sofisticada no banco é exatamente a solução correta.

Mas complexidade precisa possuir justificativa.

Legibilidade importa.

Manutenção importa.

Performance importa.

Testabilidade importa.


22. EXPLAIN — reconstruindo a cena do crime

Se queremos investigar desempenho, precisamos saber mais sobre o access path.

É aí que conceitos relacionados ao EXPLAIN tornam-se fundamentais.

O objetivo é investigar como o Db2 pretende ou decidiu acessar os dados, conforme o cenário analisado.

Você começa a procurar pistas:

INDEX?
TABLESPACE SCAN?
JOIN METHOD?
JOIN ORDER?
ESTIMATIVAS?
SORT?

Kojak coloca fotografias na parede.

Agora temos uma investigação de verdade.

O programador deixa de dizer:

“Esse SELECT está lento.”

E começa a perguntar:

“Qual access path está sendo utilizado e por quê?”

Essa diferença separa palpite de diagnóstico.


23. O verdadeiro CPD aparece

Finalmente afastamos a câmera.

O programador pensava que estava trabalhando com:

COBOL + DB2

Mas agora enxerga:

                    z/OS
                      │
       ┌──────────────┼──────────────┐
       │              │              │
      JES2           CICS           Db2
       │              │              │
      JCL            COBOL          SQL
       │              │              │
    datasets           ├──────────────┤
                       │              │
                       MQ          PACKAGE
                       │              │
                      API         OPTIMIZER
                                      │
                                  ACCESS PATH
                                      │
                              ┌───────┴───────┐
                              │               │
                           INDEXES          TABLES

E ainda não terminamos.

Ao redor estão:

RACF
SMF
WLM
TCP/IP
LOGS
RECOVERY
BACKUP
MONITORAMENTO
PARALLEL SYSPLEX

Agora entendemos por que profissionais podem trabalhar décadas com mainframe e continuar aprendendo.


24. Kojak finalmente resolve o caso

Voltamos às 03:17.

O programa estava correto.

O SQL também.

O Db2 estava disponível.

O problema estava relacionado à concorrência.

Outra unidade de trabalho estava mantendo recursos necessários.

A transação esperou.

O limite foi atingido.

O SQL recebeu erro.

O programa não possuía tratamento suficientemente inteligente.

A mensagem apresentada ao operador foi:

ERRO NO BANCO

Ou seja:

o único inocente da investigação talvez fosse justamente “o banco”.

Kojak olha para o programador.

— Então você acusou Db2 sem verificar SQLCODE, reason code, locks, unidade de trabalho e logs?

— Sim.

Kojak coloca o pirulito na boca.

— Who loves ya, baby?


🍭 Easter egg — por que Kojak usa pirulito?

Esse detalhe é perfeito para nossa história.

O pirulito não nasceu simplesmente como um adereço aleatório inventado pelo departamento de marketing. Telly Savalas contou posteriormente que a ideia surgiu numa situação em que uma personagem queria que Kojak parasse de fumar e lhe entregava um pirulito; o detalhe pegou e tornou-se uma das marcas visuais do personagem. (Los Angeles Times)

Na própria série, o pirulito apareceu durante a primeira temporada e acabou associado à tentativa de reduzir o cigarro. (Wikipedia)

Ou seja:

pequena decisão
      │
      ▼
efeito inesperado
      │
      ▼
torna-se característica permanente

Qualquer semelhança com sistemas legados é absolutamente maravilhosa.

Um programador em 1984 cria:

05 WS-FLAG PIC X.

para resolver temporariamente um problema.

Quarenta anos depois:

“Não mexa no WS-FLAG. Ninguém sabe exatamente por quê, mas o fechamento mensal depende dele.”

😂


25. A lição que Kojak deixaria ao programador COBOL

O grande erro de quem começa no mainframe é imaginar que aprender COBOL significa aprender sintaxe:

MOVE
COMPUTE
IF
EVALUATE
PERFORM

Isso é apenas a porta de entrada.

Depois vem:

COBOL
  +
JCL
  +
Db2
  +
CICS
  +
VSAM
  +
MQ
  +
RACF
  +
JES2
  +
WLM
  +
SMF
  +
z/OS

E finalmente você percebe:

o sistema corporativo não é um programa. É um ecossistema de componentes cooperando.

O SELECT SALDO que parece possuir cinco linhas pode envolver host variables, processamento SQL, DBRM, package, optimizer, estatísticas, índices, buffer management, locking, logging, segurança, recuperação e infraestrutura antes de devolver alguns bytes para WS-SALDO.

Essa é uma das coisas mais bonitas do mainframe.

Na superfície:

EXEC SQL
   SELECT SALDO
   INTO :WS-SALDO
...
END-EXEC.

Debaixo:

               50 ANOS
                  DE
             ENGENHARIA
                  │
                  ▼
             WS-SALDO

O programador olha para a variável.

Depois olha para Kojak.

Finalmente compreendeu.

Não basta perguntar:

“O programa compilou?”

É preciso investigar:

Qual SQL executou? Qual SQLCODE retornou? Qual package? Qual access path? As estatísticas estão adequadas? Existe índice apropriado? Houve locking? Timeout? Deadlock? Onde começa e termina a unidade de trabalho? Houve COMMIT? O que os logs mostram?

Porque produção não aceita álibi.

Produção aceita evidência.

Kojak se levanta, pega o sobretudo e caminha para a porta do CPD.

O programador pergunta:

— Tenente, e se amanhã aparecer outro -911?

Kojak sorri.

— Agora você sabe interrogar os suspeitos, baby.

E sai.

Na mesa fica apenas um pirulito, um dump, três relatórios de performance e um post-it:

****************************************
* NÃO CULPE O DB2 ANTES DO EXPLAIN.    *
****************************************

Fim do JOB.

IEF404I KOJAK - ENDED
IEF142I KOJAK STEP01 - COND CODE 0000

E, pela primeira vez naquela madrugada, ninguém precisou dar ROLLBACK no café. ☕🍭

quarta-feira, 11 de setembro de 2024

🐴💩 Dois Cavalos e uma Filosofia Brasileira O cocô do cavalo do bandido e o cavalo do desfile de 7 de Setembro

 

Bellacosa Mainframe frase escatologicas sobre cavalos e cocos

☕ Um café no Bellacosa Mainframe

🐴💩 Dois Cavalos e uma Filosofia Brasileira

O cocô do cavalo do bandido e o cavalo do desfile de 7 de Setembro

Uma pequena cápsula do tempo linguística para algum arqueólogo digital de 2126

Caro leitor do futuro,

Se por algum acidente arqueológico você encontrou este texto daqui a cinquenta, cem ou duzentos anos, talvez esteja tentando compreender por que brasileiros do século XXI falavam tanto de cavalos que aparentemente possuíam funções filosóficas.

Não tente traduzir literalmente.

Vai piorar.

Existem expressões que pertencem tão profundamente à cultura de um povo que traduzi-las palavra por palavra produz uma frase perfeitamente compreensível e absolutamente incompreensível.

O Brasil possui pelo menos duas preciosidades desse gênero:

“Estou me sentindo o cocô do cavalo do bandido.”

e

“Vou fazer igual ao cavalo do desfile de 7 de Setembro.”

Curiosamente, ambas utilizam cavalos.

Mais curiosamente ainda, ambas envolvem merda.

E, apesar disso, representam posições filosóficas praticamente opostas diante da existência.



🐴 1. Primeiro conheça o bandido

Imagine um velho filme de faroeste.

Existe o mocinho.

Existe a mocinha.

Existe o xerife.

Existe o bandido.

Existem os capangas.

E existem os cavalos.

O cavalo do mocinho ainda possui alguma dignidade cinematográfica. Pode receber close, salvar o protagonista, galopar heroicamente contra o pôr do sol e, nos filmes mais generosos, até possuir nome.

Mas existe também o cavalo do bandido.

Esse pobre animal já está bastante abaixo na cadeia alimentar do roteiro.

Ninguém comprou ingresso para vê-lo.

Ninguém pergunta o que aconteceu com ele depois que o bandido levou um tiro.

Provavelmente nem aparece nos créditos.

Agora imagine algo ainda menos importante.

💩 O cocô do cavalo do bandido.

Pronto.

Chegamos ao brasileiro.



💩 2. “Estou me sentindo o cocô do cavalo do bandido”

Essa extraordinária construção significa aproximadamente:

“Minha importância nesta situação atingiu níveis subterrâneos.”

Mas isso ainda é uma tradução ruim.

Porque alguém poderia simplesmente dizer:

“Estou sendo desprezado.”

Não tem graça.

Ou:

“Sinto que ninguém valoriza minha participação.”

Parece reunião de Recursos Humanos.

Ou ainda:

“Estou me sentindo insignificante.”

Parece sessão de terapia.

O brasileiro resolveu o problema adicionando um bandido, um cavalo e suas necessidades fisiológicas.

“Estou me sentindo o cocô do cavalo do bandido.”

Instantaneamente o interlocutor entende.

Você não está apenas mal.

Você não está apenas esquecido.

Você não está simplesmente no fim da fila.

Existe toda uma hierarquia acima de você.

Mocinho.

Bandido.

Cavalo.

E finalmente...

você.



🪰 3. Naturalmente, o brasileiro achou que isso ainda não era suficiente

Uma expressão popular brasileira raramente permanece intacta quando existe possibilidade de piorá-la.

Em algum momento apareceu:

“A mosca do cocô do cavalo do bandido.”

Fantástico.

Criamos mais um nível hierárquico.

Posteriormente poderiam surgir versões envolvendo a pata da mosca, a sujeira da pata da mosca, a bactéria presente na sujeira da pata da mosca...

Não existe limite teórico.

É uma espécie de recursividade escatológica brasileira.

BANDIDO
   ↓
CAVALO
   ↓
COCÔ
   ↓
MOSCA
   ↓
PATA DA MOSCA
   ↓
SUJEIRA DA PATA
   ↓
VOCÊ

COBOL não faria isso.

LISP provavelmente faria.



🇧🇷🐴 4. Então aparece o segundo cavalo

Agora mudamos completamente de estado de espírito.

Imagine o desfile brasileiro de 7 de Setembro, comemoração da Independência.

Autoridades.

Uniformes impecáveis.

Bandeiras.

Banda militar.

Marcha.

Cerimônia.

Público.

Câmeras.

Tudo organizado segundo um protocolo cuidadosamente preparado por seres humanos.

Então passa um cavalo.

O cavalo não conhece o protocolo.

O cavalo não estudou História do Brasil.

O cavalo desconhece solenidades republicanas.

O cavalo simplesmente...

caga.

No meio da parada.

E continua andando.

Majestosamente.



😎 5. “Vou fazer igual ao cavalo do desfile de 7 de Setembro”

Aqui encontramos uma filosofia completamente diferente.

O sujeito não está derrotado.

Também não está revoltado.

Muito menos desesperado.

Ele atingiu um estágio superior de indiferença.

A tradução aproximada seria:

“Vou permanecer absolutamente tranquilo, cumprir meu caminho, fazer aquilo que considero necessário e deixar que os demais lidem com as consequências.”

Novamente, tradução horrível.

A original é infinitamente melhor:

“Vou fazer igual ao cavalo do desfile de 7 de Setembro.”

O interlocutor brasileiro imediatamente completa mentalmente:

andar calmamente...

olhar para o público...

cagar na parada...

e continuar andando.

😂



🧘 6. O segredo está na serenidade

Existe uma diferença importantíssima entre:

“mandar tudo à merda”

e

ser o cavalo do desfile.

Quem manda tudo à merda ainda está emocionalmente envolvido.

Está bravo.

Grita.

Bate a porta.

Talvez escreva um e-mail de 1.700 palavras copiando quinze gerentes.

O cavalo não.

O cavalo não discute com o comandante da parada.

Não abre chamado.

Não pede escalation.

Não cria PowerPoint.

Não coloca ninguém em cópia.

Ele simplesmente realiza sua contribuição pessoal ao evento...

e segue caminhando.

Essa serenidade é essencial.



🐴 7. Os dois cavalos representam extremos da existência

E aqui chegamos à beleza dessas duas expressões.

No primeiro caso:

Você é o cocô do cavalo.

No segundo:

Você é o cavalo.

Parece uma diferença pequena.

É gigantesca.

O cocô do cavalo do bandido representa alguém submetido às circunstâncias.

O cavalo do desfile de 7 de Setembro representa alguém que decidiu que as circunstâncias não merecem mais sua preocupação.

Um diz:

“Ninguém liga para mim.”

O outro responde:

“Eu não ligo para ninguém.”

E assim aproximadamente dois séculos de filosofia ocidental podem ser resumidos utilizando apenas dois cavalos.



🌎 8. Agora tente traduzir isso para inglês

Boa sorte.

“I feel like the poop of the bandit's horse.”

Um americano provavelmente perguntará se você precisa de assistência médica.

“I'm going to behave like the horse at the September 7th Independence Day parade.”

Agora você precisará explicar:

— September 7th is Brazilian Independence Day...

— Okay...

— There are military parades...

— Right...

— Sometimes there are horses...

— Sure...

— And the horse shits...

— What?

Acabou.

A piada morreu durante a imigração.


🧠 9. Porque a verdadeira expressão não está nas palavras

Esse talvez seja o ponto linguisticamente mais interessante.

Essas frases funcionam porque o ouvinte participa da construção da piada.

Quando alguém diz:

“Estou igual ao cocô do cavalo do bandido.”

não precisa acrescentar:

“Isso significa que estou me sentindo desprestigiado.”

Todo mundo entendeu.

Quando alguém anuncia:

“Agora vou fazer igual ao cavalo do 7 de Setembro.”

não precisa explicar o restante.

O interlocutor já está sorrindo.

Porque sua cabeça produziu o filme inteiro.

E frequentemente a gargalhada acontece justamente antes da explicação que nunca será necessária.


📦 10. São arquivos ZIP culturais

Talvez essa seja uma boa definição.

Essas expressões são arquivos ZIP da cultura popular.

Poucas palavras armazenam:

memória coletiva, imagens, ironia, hierarquia social, resignação, cinismo, autodepreciação e humor.

O falante envia:

“Cavalo do bandido.”

O cérebro do receptor executa:

DESCOMPACTAR.EXE

E recebe todo o restante.

É por isso que traduções literais fracassam.

Você consegue traduzir as palavras.

Não consegue transportar automaticamente o arquivo cultural que permite descompactá-las.


🍺 11. Manual prático para o brasileiro contemporâneo

Segunda-feira.

O chefe esqueceu seu nome.

Seu projeto perdeu orçamento.

Seu computador atualizou sozinho.

O café acabou.

Você declara:

“Hoje estou o cocô do cavalo do bandido.”

Quarta-feira.

Depois de oito reuniões, quatro apresentações e alguém perguntar pela terceira vez aquilo que estava escrito no primeiro slide, alguma coisa muda dentro de você.

Finalmente chega sexta-feira.

17h43.

Alguém manda:

“Rapidinho, você consegue olhar uma coisinha antes de sair?”

Nesse momento ocorre a metamorfose.

Você deixa de ser o cocô.

Você se torna o cavalo.

Endireita a coluna.

Olha serenamente para o horizonte.

E pensa:

“Agora vou de cavalo do desfile de 7 de Setembro.”


🏺 12. Nota para o arqueólogo digital do futuro

Se você encontrou este texto no ano de 2126 tentando descobrir o significado dessas expressões, registre isto cuidadosamente:

sim, brasileiros realmente falavam essas coisas.

Não sabemos exatamente quem pronunciou cada uma delas pela primeira vez.

Provavelmente circularam durante muito tempo pela oralidade, ganhando versões, exageros e novos detalhes conforme passavam de uma pessoa para outra.

E justamente por isso vale deixar mais uma ocorrência escrita.

Porque expressões populares possuem uma característica curiosa:

todo mundo conhece,

ninguém sabe quem inventou,

ninguém lembra onde ouviu pela primeira vez,

mas todo mundo sabe exatamente quando usar.


☕ Conclusão — A sabedoria dos dois cavalos

Talvez algum filósofo do futuro encontre uma teoria sofisticada para explicar tudo isso.

Nós podemos economizar o trabalho.

Existem momentos na vida em que você inevitavelmente será:

💩 o cocô do cavalo do bandido.

Aceite.

Sobreviva.

Dê risada.

Mas existem outros momentos em que a melhor estratégia possível será transformar-se no:

🐴 cavalo do desfile de 7 de Setembro.

Mantenha a postura.

Caminhe calmamente.

Sorria para o público.

Faça aquilo que precisa fazer.

E siga adiante sem olhar para trás.

Porque talvez uma pequena parte da filosofia brasileira possa ser resumida assim:

Quando o mundo fizer você se sentir o cocô do cavalo do bandido, sobreviva tempo suficiente para um dia poder ser o cavalo do desfile.

O resto...

bem...

fica para quem vem marchando atrás. 🐴💩🇧🇷



terça-feira, 10 de setembro de 2024

Viagem ao Centro do Clojure: COBOL, Rich Hickey e a Linguagem que Decidiu que Mudar Estado Era um Péssimo Hábito

 

Bellacosa Mainframe e uma viagem ao centro do clojure

☕ Um Café no Bellacosa Mainframe

Viagem ao Centro do Clojure: COBOL, Rich Hickey e a Linguagem que Decidiu que Mudar Estado Era um Péssimo Hábito

🌋 Lisp, JVM, imutabilidade, REPL, funções, memória, performance, concorrência, Datomic, Nubank e a expedição de um COBOLzeiro ao interior de uma linguagem de 2007 que parecia ter sido escrita por Júlio Verne depois de descobrir a programação funcional


Há tecnologias que entram na sala fazendo barulho.

Chegam com conferências, camisetas, logos coloridos e evangelistas dizendo:

“Isto vai mudar tudo.”

E há tecnologias que entram silenciosamente, sentam no fundo da sala, olham para cinquenta anos de programação imperativa e perguntam:

“Vocês têm certeza de que ficar alterando estado o tempo inteiro foi uma boa ideia?”

Clojure pertence ao segundo grupo.

Para um programador COBOL iniciante, especialmente alguém acostumado a imaginar programas como uma sequência de:

MOVE
ADD
SUBTRACT
COMPUTE
IF
PERFORM

Clojure parece inicialmente uma criatura saída das profundezas de um romance de Júlio Verne.

Você olha para:

(+ 1 2)

e pergunta:

— Por que o operador está do lado errado?

Depois encontra:

(defn debitar [saldo valor]
  (- saldo valor))

e pensa:

— Cadê minha WORKING-STORAGE?

Cinco minutos depois alguém escreve:

(->> transacoes
     (filter suspeita?)
     (map analisar)
     (group-by :cliente))

e o COBOLzeiro começa a procurar a saída de emergência.

Mas talvez devêssemos fazer exatamente o contrário.

Em vez de fugir, vamos acender as lanternas.

Hoje descemos ao centro do Clojure.


Capítulo I — O mapa da expedição

Nossa viagem começa em 2007.

Naquele ano, Java já dominava boa parte do mundo corporativo.

.NET crescia.

C++ permanecia forte.

PHP estava por toda a Web.

Ruby ganhava atenção.

Python ainda não tinha conquistado o planeta inteiro.

E a JVM parecia um continente relativamente bem cartografado.

Então Rich Hickey aparece com uma pergunta perigosa:

E se pudéssemos usar a JVM sem carregar todo o modelo mental orientado a objetos tradicional?

A resposta foi Clojure.

O desenvolvimento havia começado alguns anos antes, por volta de 2005, e em 2007 a linguagem tornou-se pública.

Ela nasceu como um dialeto de Lisp projetado especificamente para rodar sobre a JVM.

Isso é muito importante.

Rich Hickey não tentou construir:

LINGUAGEM NOVA
+
VM NOVA
+
ECOSSISTEMA NOVO
+
BIBLIOTECAS NOVAS
+
BOA SORTE

Ele fez algo muito mais pragmático:

CLOJURE
   |
   v
JVM
   |
   v
JAVA ECOSYSTEM

Isso significava acesso a:

bibliotecas Java
drivers JDBC
threads JVM
garbage collector
networking
cryptography
AWS SDK
Kafka
HTTP
filesystem

Ou seja, Clojure podia ser estranha por cima sem precisar reinventar o planeta por baixo.


Capítulo II — Quem é Rich Hickey?

Rich Hickey é o criador de Clojure e uma das figuras mais influentes da programação funcional moderna.

Ele também está intimamente ligado ao Datomic.

Isso importa porque existe uma linha intelectual direta:

RICH HICKEY
     |
     +---- CLOJURE
     |       |
     |       +-- valores
     |       +-- imutabilidade
     |       +-- funções
     |       +-- estado controlado
     |
     +---- DATOMIC
             |
             +-- fatos imutáveis
             +-- tempo
             +-- histórico
             +-- database values

Se Clojure é a filosofia aplicada ao programa, Datomic é parte dessa filosofia aplicada aos dados.

Por isso entender Clojure ajuda brutalmente a entender por que Datomic parece tão diferente de Db2, Oracle ou PostgreSQL.


Capítulo III — Qual “geração” de linguagem é Clojure?

Se usarmos aquela classificação antiga:

1GL → máquina
2GL → assembler
3GL → alto nível
4GL → declarativas/especializadas

Clojure cabe genericamente como linguagem de alto nível.

Mas isso diz pouco.

Uma descrição melhor seria:

LISP
+
FUNCIONAL
+
DINÂMICA
+
COMPILADA PARA JVM
+
PROPÓSITO GERAL
+
MULTIPARADIGMA

Ela não é puramente funcional no sentido extremo.

Você pode ter estado.

Você pode ter efeitos colaterais.

Você pode conversar com Java.

Mas a linguagem favorece fortemente valores imutáveis e transformação de dados através de funções.


Capítulo IV — A primeira grande heresia: valores não deveriam mudar

Em COBOL fazemos naturalmente:

MOVE 1000 TO WS-SALDO.
SUBTRACT 200 FROM WS-SALDO.

Antes:

WS-SALDO = 1000

Depois:

WS-SALDO = 800

Nosso modelo mental é:

MESMA COISA
   |
   v
MUDOU

Clojure prefere separar:

VALOR A = 1000

FUNÇÃO
   |
   v

VALOR B = 800

1000 continua sendo 1000.

800 é outro valor.

A diferença parece banal.

Não é.

Quando você possui:

threads
concorrência
cache
eventos
estado compartilhado
sistemas distribuídos

objetos mutáveis podem virar pequenas minas terrestres.


Capítulo V — Estruturas persistentes imutáveis

Agora encontramos uma das maiores forças da linguagem.

Clojure oferece estruturas como:

[1 2 3]

vector.

'(1 2 3)

lista.

#{1 2 3}

set.

E:

{:nome "Arthur"
 :saldo 1000M}

map.

Agora:

(def cliente
  {:nome "Arthur"
   :saldo 1000M})

Depois:

(def cliente2
  (assoc cliente :saldo 800M))

Temos:

cliente  = saldo 1000
cliente2 = saldo 800

O primeiro não mudou.

Isso não significa copiar ingenuamente cada byte inteiro.

Clojure utiliza persistent data structures, compartilhando internamente partes estruturais.

É uma técnica inteligente para tornar imutabilidade prática.


Capítulo VI — O império dos parênteses

Chega a hora daquilo que todos comentam.

(+ 2 3)

Em vez de:

2 + 3

Isso é prefix notation.

Outro:

(* (+ 2 3) 4)

Resultado:

20

Parece alienígena.

Mas tem uma vantagem.

A sintaxe tende a seguir:

(função argumento argumento argumento)

Exemplo:

(str "Bellacosa" " Mainframe")

Tudo começa a seguir uma estrutura relativamente uniforme.

E aqui surge o primeiro Easter egg:

Lisp não possui parênteses demais.

Nós é que crescemos acostumados a escondê-los atrás de quinze tipos diferentes de sintaxe.

O Clojure apenas deixou todos à vista.

😄


Capítulo VII — def, defn, let e companhia

Comecemos simples.

Definir um valor:

(def saldo 1000M)

Definir função:

(defn somar [a b]
  (+ a b))

Executar:

(somar 10 20)

Resultado:

30

Variáveis locais:

(let [saldo 1000M
      compra 200M]
  (- saldo compra))

Resultado:

800M

E sim, existe if.

(if (> saldo 0)
  "POSITIVO"
  "NEGATIVO")

O COBOLzeiro respira aliviado.

A humanidade ainda não conseguiu eliminar:

IF

Capítulo VIII — Funções de primeira classe

Em COBOL tradicional, subrotinas e PERFORM possuem papel central.

Em Clojure, funções são tratadas como valores.

Você pode passá-las para outras funções.

Exemplo:

(map inc [1 2 3])

Resultado:

(2 3 4)

inc é uma função passada para map.

Outro:

(filter even? [1 2 3 4 5 6])

Resultado:

(2 4 6)

Aos poucos você para de escrever:

FOR cada item
  IF condição
     faça algo

e começa a pensar:

pegue coleção
filtre
transforme
reduza

Capítulo IX — map, filter e reduce: a Santíssima Trindade funcional

Suponha transações:

(def transacoes
  [100 200 50 900 300])

Quero apenas valores acima de 200:

(filter #(> % 200) transacoes)

Resultado:

(900 300)

Quero dobrar:

(map #(* % 2) transacoes)

Quero somar:

(reduce + transacoes)

Isso é programação orientada a transformação de dados.

Para um COBOLzeiro, pense em algo como:

INPUT FILE
   |
   v
FILTER
   |
   v
TRANSFORM
   |
   v
AGGREGATE

É quase um SORT/ICETOOL filosófico.

😄


Capítulo X — Threading macros: o encanamento elegante

Uma das características mais simpáticas é -> e ->>.

Sem:

(println
  (clojure.string/upper-case
    "bellacosa"))

Com:

(-> "bellacosa"
    clojure.string/upper-case
    println)

Leia:

"bellacosa"
   |
   v
uppercase
   |
   v
println

Para coleções:

(->> [1 2 3 4 5 6]
     (filter even?)
     (map #(* % 10)))

Resultado:

(20 40 60)

Isso deixa pipelines de dados extremamente legíveis.


Capítulo XI — REPL: programando dentro da máquina viva

REPL significa:

Read
Eval
Print
Loop

Você abre o ambiente e escreve:

(+ 2 2)

Ele responde:

4

Depois:

(def cliente
  {:nome "Arthur"
   :saldo 1000})

Depois:

(:saldo cliente)

E recebe:

1000

Você constrói, testa e inspeciona o programa sem aquele ciclo pesado de compilar tudo e recomeçar.

Para quem viveu:

EDIT
COMPILE
LINK
RUN
ABEND

o REPL parece máquina do tempo.

E isso muda profundamente o workflow.

Em Clojure, o REPL não é apenas calculadora interativa.

É ferramenta de desenvolvimento.


Capítulo XII — Estado existe, mas precisa mostrar documento

Clojure não proíbe estado mutável.

Ele apenas não quer que mudanças fiquem espalhadas e invisíveis.

Exemplo com atom:

(def saldo
  (atom 1000))

Consultar:

@saldo

Resultado:

1000

Alterar:

(swap! saldo - 200)

Agora:

@saldo

retorna:

800

A diferença é que o ponto onde existe identidade mutável está explícito.

A linguagem possui também:

Vars
Refs
Agents
Atoms

cada qual com propósitos diferentes.


Capítulo XIII — STM: transações sem banco de dados

Clojure também possui Software Transactional Memory.

Refs podem ser atualizadas coordenadamente dentro de transações de memória.

Isso parece quase familiar:

BEGIN
ALTERA A
ALTERA B
COMMIT

Mas sobre referências de memória.

A ideia é evitar manualmente boa parte do pesadelo de locks.

Não significa que STM seja solução universal.

Mas demonstra a obsessão de Hickey:

estado mutável precisa ser controlado, não espalhado.


Capítulo XIV — Concorrência: onde Clojure mostra por que nasceu

Imagine:

THREAD 1 → altera objeto
THREAD 2 → lê objeto
THREAD 3 → altera objeto

Se todo mundo compartilha estado mutável, temos:

race condition
locks
deadlocks
synchronization

Agora:

VALOR IMUTÁVEL

pode ser compartilhado livremente porque ninguém consegue alterá-lo.

Isso não elimina concorrência.

Mas reduz radicalmente certas classes de problema.

Esse é um dos grandes argumentos em favor da linguagem.


Capítulo XV — Java está logo abaixo do convés

Uma das vantagens fundamentais de Clojure é Java interop.

Você pode chamar diretamente:

(System/currentTimeMillis)

Ou:

(.toUpperCase "cobol")

Resultado:

"COBOL"

Ou criar:

(java.util.Date.)

Isso significa que Clojure não depende de esperar alguém escrever uma biblioteca “clojuriana” para tudo.

Pode aproveitar:

JDBC
Kafka
AWS SDK
Java crypto
HTTP clients
XML parsers
drivers

Essa foi uma decisão arquitetural brilhante.


Capítulo XVI — Performance: rápido ou lento?

Agora a pergunta inevitável.

Clojure não é simplesmente interpretada.

Ela compila para bytecode JVM.

Depois:

JVM
  |
  v
JIT
  |
  v
MACHINE CODE

Isso lhe permite boa performance para enorme quantidade de workloads empresariais.

Mas existem custos.

dynamic dispatch
boxing
reflection
persistent data structures
lazy sequences
object allocation
GC

Então não existe:

CLOJURE = LENTO

nem:

CLOJURE = TÃO RÁPIDO QUANTO C OTIMIZADO

O correto é:

depende do workload e da qualidade do código.


Capítulo XVII — Boxing, primitives e type hints

JVM possui tipos primitivos eficientes.

Mas linguagens dinâmicas podem acabar empacotando valores em objetos.

Isso custa memória e CPU.

Você pode ajudar o compilador em alguns casos:

(defn tamanho [^String texto]
  (.length texto))

O:

^String

é type hint.

Isso reduz necessidade de reflection em determinados pontos.

Mas não faça isso em todo lugar por superstição.

A velha regra continua:

MEÇA
ANTES
DE
OTIMIZAR

Capítulo XVIII — Memória e persistent structures

Clojure frequentemente consome mais memória que código Java cuidadosamente otimizado usando arrays primitivos.

Exemplo:

Java int[]

pode ser extremamente compacto.

Uma collection Clojure genérica traz metadados, nós e objetos.

Mas as persistent structures também compartilham estrutura, evitando cópias inteiras.

Quando performance de construção é crítica, Clojure possui:

transients

que permitem uma fase de mutabilidade controlada para performance.

É quase:

“Você pode mexer, mas devolva tudo arrumado.”


Capítulo XIX — Garbage Collection: o monstro subterrâneo

Estamos na JVM.

Então existe GC.

A vantagem:

malloc/free manual

não é problema normal do programador.

A desvantagem:

muita alocação
      |
      v
GC
      |
      v
pausas / CPU

Em sistemas de baixa latência, você precisa observar:

heap
GC pause
allocation rate
latency p99
latency p999
working set

O COBOLzeiro olha e diz:

“Sabia que havia alguma coisa para monitorar.”

Sempre há.


Capítulo XX — Onde Clojure é particularmente forte?

Ela se encaixa muito bem em:

backends
serviços concorrentes
event processing
data pipelines
fintech
fraude
regra de negócio
APIs
Kafka
sistemas distribuídos
Datomic

Especialmente quando dados fluem por várias transformações.

O modelo:

DADOS
  |
FUNÇÃO
  |
DADOS
  |
FUNÇÃO

pode resultar em código pequeno e expressivo.


Capítulo XXI — Fraquezas reais

Agora vamos parar de romance.

Curva de aprendizado

O problema não são apenas parênteses.

É mudar a cabeça.

Um desenvolvedor OO pergunta:

qual classe?

O clojurista pergunta:

quais dados?
qual transformação?

Ecossistema menor

Java, Python e JavaScript possuem comunidades muito maiores.

Empregabilidade mais estreita

Há empresas sérias usando Clojure, mas o número de vagas é menor.

Ferramentas

O ecossistema é bom, porém menos vasto.

Mensagens de erro

Podem ser duras para iniciantes.

JVM startup

Para scripts minúsculos pode ser pesado.

Memória

Pode haver overhead.


Capítulo XXII — Ferramentas da expedição

Hoje você normalmente encontrará:

Clojure CLI
deps.edn
REPL
nREPL
Clojure LSP
Calva
CIDER
Cursive
Leiningen

Para começar, eu escolheria algo simples:

Java
+
Clojure CLI
+
VS Code
+
Calva

ou IntelliJ + Cursive.

Não comece com quinze plugins.

Aprenda a linguagem.


Capítulo XXIII — Máquina necessária

Para aprender Clojure você não precisa de infraestrutura monstruosa.

Uma máquina perfeitamente normal:

4 cores
8 GB RAM
SSD
Java moderno

funciona bem.

16 GB deixam desenvolvimento mais confortável.

Produção obviamente depende do workload.

O tamanho correto não é:

MÁQUINA PADRÃO CLOJURE

É:

MÁQUINA ADEQUADA AO SERVIÇO

CPU.

RAM.

Throughput.

GC.

Latência.

Tudo de novo.


Capítulo XXIV — Licença e código-fonte

Clojure é open source.

Historicamente está sob a Eclipse Public License 1.0.

O projeto possui código público no GitHub.

Mas existe uma característica importante:

o desenvolvimento do core é relativamente conservador e controlado.

Isso não é necessariamente defeito.

Linguagem de programação é infraestrutura.

Quebrar compatibilidade todo semestre seria divertido apenas para consultorias.


Capítulo XXV — O conservadorismo inesperado

Aqui existe uma ironia deliciosa.

Clojure é:

Lisp
funcional
imutável
JVM

e parece radical.

Mas a evolução da linguagem é relativamente conservadora.

Rich Hickey valorizou muito:

stability
simplicity
backward compatibility

Para um COBOLzeiro isso deveria soar curiosamente familiar.

Tecnologia moderna com mentalidade:

“Não vamos quebrar produção só porque terça-feira chegou.”

Há algo admirável nisso.


Capítulo XXVI — Empregabilidade

Clojure é nicho.

Isso precisa ser dito claramente.

Não existe volume de vagas comparável a:

Java
Python
JavaScript
C#

Mas existe mercado profissional.

Fintechs.

Empresas de software.

Dados.

Saúde.

Sistemas distribuídos.

O curioso é a dinâmica:

POUCAS VAGAS
+
POUCOS PROFISSIONAIS

Isso pode gerar bons nichos.

Mas também significa maior dependência de especialização.


Capítulo XXVII — Nubank e o elefante roxo

Você não consegue falar de Clojure moderno sem falar do Nubank.

A empresa adotou Clojure cedo.

Adotou Datomic.

Escalou ambos brutalmente.

E em 2020 adquiriu a Cognitect.

Isso criou uma situação extraordinária.

CLOJURE
   |
COGNITECT
   |
NUBANK USA
   |
NUBANK CRESCE
   |
NUBANK COMPRA COGNITECT

O cliente tornou-se também sustentador central do ecossistema.

Isso dá enorme prova operacional.

Mas também concentra parte do ecossistema em torno de um usuário gigantesco.


Capítulo XXVIII — Penetração acadêmica

Clojure não é uma linguagem universitária dominante.

Universidades usam muito mais:

Python
Java
C
C++
Scheme
Racket
Haskell

dependendo do curso.

Clojure aparece em contextos como:

functional programming
concurrency
Lisp
language design
persistent structures

Seu crescimento é muito mais profissional/comunitário que acadêmico.


Capítulo XXIX — Como aprender sem afundar o Nautilus

Minha rota recomendada:

Etapa 1

Aprenda:

def
defn
let
if
vectors
maps
sets
keywords

Etapa 2

Depois:

map
filter
reduce
sort
group-by

Etapa 3

Entenda:

immutability
assoc
update
conj

Etapa 4

Aprenda:

->
->>

Etapa 5

Use REPL diariamente.

Etapa 6

Depois:

atom
refs
agents
STM

Etapa 7

Java interop.

Etapa 8

Somente então:

HTTP
Kafka
database
Datomic

Capítulo XXX — Mini sistema bancário

Vamos construir algo simples.

Cliente:

(def cliente
  {:id 123
   :nome "Arthur Dent"
   :saldo 1000M})

Função débito:

(defn debitar [cliente valor]
  (update cliente :saldo - valor))

Executar:

(def cliente2
  (debitar cliente 200M))

Agora:

(:saldo cliente)

continua:

1000

Enquanto:

(:saldo cliente2)

é:

800

Este pequeno exemplo explica Clojure melhor que cinquenta slides.


Capítulo XXXI — Autorização financeira

Agora:

(defn autorizar [cliente valor]
  (if (>= (:saldo cliente) valor)
    {:status :aprovada
     :cliente (debitar cliente valor)}
    {:status :negada
     :cliente cliente}))

Teste:

(autorizar cliente 200M)

Você recebe:

{:status :aprovada
 :cliente {:id 123
           :nome "Arthur Dent"
           :saldo 800M}}

Observe o estilo.

Dados simples.

Funções simples.

Pouca cerimônia.

Nada de vinte classes para representar uma transferência de R$ 200.


Capítulo XXXII — Clojure versus Java

Simplificando brutalmente:

Java costuma incentivar:

OBJECT
  |
METHOD
  |
STATE

Clojure:

DATA
  |
FUNCTION
  |
NEW DATA

Não significa que Java seja incapaz de programação funcional.

Nem que Clojure não tenha estado.

É questão de gravidade cultural.

A linguagem puxa seu pensamento numa direção.


Capítulo XXXIII — Clojure versus COBOL

Agora vem uma comparação deliciosamente inesperada.

COBOL:

01 CLIENTE.
   05 CLIENTE-ID PIC 9(09).
   05 CLIENTE-NOME PIC X(30).
   05 CLIENTE-SALDO PIC S9(9)V99.

Clojure:

{:id 123
 :nome "Arthur"
 :saldo 1000M}

Ambos possuem uma característica interessante:

dados estão na cara.

Clojure não exige que você esconda tudo dentro de dezenas de classes.

Nesse sentido, um COBOLzeiro pode achar Clojure menos alienígena depois de superar a aparência Lisp.


Capítulo XXXIV — E onde entra Datomic?

Agora finalmente tudo se encaixa.

Clojure diz:

VALORES IMUTÁVEIS

Datomic diz:

FATOS IMUTÁVEIS

Clojure:

VALOR T1
   |
FUNÇÃO
   |
VALOR T2

Datomic:

DATABASE T1
   |
TRANSACTION
   |
DATABASE T2

Clojure separa identidade de valor.

Datomic faz algo semelhante com banco e tempo.

Por isso:

CLOJURE
+
DATOMIC

é uma combinação intelectualmente coerente.


Capítulo XXXV — Easter egg: o nome Clojure

“Clojure” é uma brincadeira fonética com:

closure

um conceito importante da programação funcional.

Mas com:

J

fazendo referência à JVM/Java.

Uma pequena assinatura escondida no nome.


Capítulo XXXVI — Outro Easter egg: Simple Made Easy

Uma das palestras mais famosas de Rich Hickey é:

Simple Made Easy

A distinção central é maravilhosa:

SIMPLE
!=
EASY

Algo pode ser fácil de usar hoje e ainda assim criar enorme complexidade amanhã.

Isso deveria estar colado na parede de todo projeto corporativo.

Outro conceito famoso:

Hammock Driven Development

A ideia:

pense antes de sair digitando furiosamente.

Em alguns ambientes isso seria considerado atividade subversiva.

😄


Capítulo XXXVII — O que o COBOLzeiro deve levar consigo?

Não tente aprender Clojure como:

“Java com sintaxe estranha.”

Vai sofrer.

Também não tente:

“COBOL com parênteses.”

Pior ainda.

Pense:

DADOS
+
FUNÇÕES
+
VALORES
+
TRANSFORMAÇÕES
+
ESTADO EXPLÍCITO

Essa é a porta.


Epílogo — A jornada de volta à superfície

Depois de dias no interior da Terra, nosso explorador COBOL finalmente retorna.

No bolso:

Clojure

Na mochila:

REPL
immutability
persistent structures
functions
JVM
atoms
Datalog
Datomic

O colega pergunta:

— Então COBOL morreu?

Ele responde:

— Não.

— Java morreu?

— Também não.

— Clojure é o futuro?

— Para algumas coisas.

— Então o que você aprendeu?

O velho viajante olha para o horizonte.

— Que cada linguagem carrega uma teoria sobre como devemos pensar.

COBOL diz:

descreva claramente os dados e procedimentos do negócio.

Java tradicional diz:

modele entidades e comportamento através de objetos.

Clojure diz:

trate dados como valores, transforme-os com funções e seja extremamente cuidadoso quando precisar mudar estado.

Nenhuma frase substitui engenharia.

Mas cada uma muda as perguntas que fazemos.

E talvez essa seja a coisa mais fascinante em Clojure.

Ela não tenta simplesmente entregar:

mais uma linguagem

Ela tenta convencer o programador de que parte da complexidade de software foi criada por nós mesmos.

Porque passamos décadas dizendo:

X = 10
X = 20
X = 30

sem perguntar:

O que exatamente é X?

É o valor?

É a identidade?

É seu estado num determinado instante?

E o que aconteceu com os estados anteriores?

Clojure transformou essas perguntas em linguagem.

Datomic transformou parte delas em banco de dados.

Nubank transformou ambas em infraestrutura financeira real.

E nosso COBOLzeiro, depois de atravessar VSAM, IMS, Adabas, Db2 e quase cinquenta anos de evolução tecnológica, descobre algo curioso.

Ele não precisa abandonar o passado para compreender o futuro.

Muito pelo contrário.

Quem conhece bem:

estado
transação
dados
concorrência
integridade
performance
memória
recovery

já possui metade do mapa.

Só precisa aprender a ler as novas coordenadas.

O professor fecha o diário de bordo.

Na última página:

(println
  "Não entre em pânico.
   São apenas parênteses.")

E abaixo, escrito à mão por algum COBOLzeiro anônimo:

* TODO:
* DESCOBRIR ONDE DIABOS FICA A PROCEDURE DIVISION.

Fim da viagem.

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