☕ 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 cicd. Mostrar todas as mensagens
Mostrar mensagens com a etiqueta cicd. Mostrar todas as mensagens

sexta-feira, 26 de dezembro de 2025

UrbanCode DBB: Controle de Versionamento no Mainframe, do Jeito Certo


UrbanCode DBB: Controle de Versionamento no Mainframe, do Jeito Certo

Se você já trabalhou em mainframe, sabe que cada linha de código é sagrada. Um erro de versionamento e você pode acordar com todo o departamento olhando para você como se tivesse errado o compilador na sexta-feira à tarde. Foi justamente pensando nisso que nasceu o UrbanCode DBB, o guardião do código COBOL, PL/I, Assembler, JCL e tudo mais que roda em z/OS.


História e Origem

O DBB, que significa Dependency Based Build, começou sua vida nos laboratórios da IBM como uma forma de modernizar o build de aplicações mainframe. A ideia era simples: parar de depender de scripts complicados de JCL e REXX espalhados pelo servidor e criar algo que entendesse as dependências reais do seu código.

Em 2016, o UrbanCode comprou a tecnologia e integrou no seu portfólio de DevOps, transformando o DBB numa peça central para mainframe moderno, pronto para integração com pipelines CI/CD, Git, Jenkins e até o mundo do container e cloud.


Para que serve e por que usar

Imagine o seu sistema legado com dezenas de programas COBOL interdependentes. Alterou um copybook ou uma tabela DB2? Então você precisa recompilar tudo que depende disso, mas somente o que realmente depende. Aqui entra o DBB:

  • Detecção de dependências: Ele analisa seu código e entende as relações entre programas, módulos e copybooks.

  • Build incremental inteligente: Só recompila o que precisa, economizando horas de batch.

  • Integração DevOps: Pode ser chamado por Jenkins, GitLab, UrbanCode Deploy, tornando o mainframe parte do fluxo ágil.

Em resumo: DBB é o cupido do build, unindo o que mudou com o que precisa mudar.

Como usar: dicas práticas

  1. Estrutura de projetos: Organize seu código como projetos, módulos e pacotes. DBB adora clareza.

  2. Dependência declarativa: Marque copybooks, DB2 DDL e includes. Quanto mais informação ele tiver, mais eficiente será o build.

  3. Log e rastreabilidade: Sempre revise os logs. DBB é detalhista — ele te conta cada recompilação que fez.

  4. Pipeline CI/CD: Integre DBB ao Jenkins ou UrbanCode Deploy para builds automáticos e consistentes.

Exemplo básico

Imagine que você tem um programa PAYROLL que depende de EMPLOYEE e SALARY. Se você altera apenas SALARY, DBB identifica que apenas PAYROLL precisa de recompilação, poupando tempo e evitando que outros programas sejam recompilados desnecessariamente.

PROJECT PAYROLL
   MODULE EMPLOYEE
   MODULE SALARY
   MODULE PAYROLL
   DEPENDS_ON SALARY, EMPLOYEE
ENDPROJECT

Simples, mas poderoso.

Curiosidade e Easter Egg

Você sabia que o DBB foi inspirado em técnicas de build usadas em ambientes UNIX? A diferença é que ele traduziu essas ideias para o z/OS, entendendo a complexidade do JCL, copybooks e DB2.

E o easter egg? Se você examinar os logs detalhados, verá pequenos comentários de debug deixados pelos engenheiros: mensagens como "Aqui mora o fantasma do COBOL" ou "Não acorde o compilador antes do café"… só quem vive de batch entende.

Comentários finais

O DBB é um salvavidas para equipes que querem DevOps sem abandonar o mainframe. Ele reduz erros, agiliza deploys e ainda preserva aquela aura mística de que o código mainframe “funciona sozinho, mas precisa de respeito”.

Se você ainda não experimentou, vale a pena. Modernizar builds não é apenas um luxo, é sobre manter a sanidade e ganhar tempo para o café da tarde.

quinta-feira, 26 de dezembro de 2024

📮 O CARTEIRO E O POETA — QUANDO UMA POSTMAN COLLECTION APRENDEU A ENTREGAR CARTAS AO MAINFRAME

 

Bellacosa Mainframe apresenta o postman

☕ Um Café no Bellacosa Mainframe

📮 O CARTEIRO E O POETA — QUANDO UMA POSTMAN COLLECTION APRENDEU A ENTREGAR CARTAS AO MAINFRAME

Postman, Collections, HTTP, REST, JSON, variáveis, autenticação, scripts, testes positivos e negativos, contratos, Runner, CI/CD, z/OS Connect, CICS, COBOL, Db2 — e o dia em que um jovem programador descobriu que receber 200 OK não significava que a carta havia chegado à pessoa certa.



Sob a tutela de O Carteiro e o Poeta, porque uma API também vive de mensagens. Algumas precisam chegar rápido. Outras precisam chegar com segurança. Todas precisam chegar ao destinatário correto.



🎬 PRÓLOGO — TODA API TEM UM CARTEIRO

Imagine uma pequena ilha.

Todas as manhãs, o carteiro percorre as mesmas ruas carregando cartas. Ele conhece os caminhos, as casas, os moradores e os horários.

Até que encontra um poeta.

O poeta não quer simplesmente que uma carta seja transportada.

Ele quer que ela seja compreendida.

Essa pequena diferença explica uma parte enorme do que significa testar APIs.

Quando começamos a usar o Postman, normalmente fazemos algo parecido com um carteiro iniciante:

GET /clientes/123

Clicamos em Send.

Recebemos:

200 OK

E comemoramos:

Funcionou!

Calma, jovem padawan do COBOL.

O servidor respondeu. Isso é tudo que sabemos até agora.

Talvez tenhamos pedido o cliente 123 e recebido o cliente 999.

Talvez o JSON esteja incompleto.

Talvez o saldo esteja errado.

Talvez uma pessoa sem autorização tenha conseguido consultar informações que não deveria.

Talvez o backend tenha consultado o Db2 errado.

Talvez o COBOL tenha devolvido um código de negócio indicando falha e alguma camada intermediária tenha convertido tudo em HTTP 200.

O carteiro entregou alguma coisa.

Ainda precisamos descobrir se entregou a carta correta para a pessoa correta.

E é aqui que nossa história realmente começa.



📬 CAPÍTULO 1 — POSTMAN NÃO É APENAS UM BOTÃO SEND

Para quem começa a trabalhar com APIs, Postman parece uma ferramenta para escrever uma URL, selecionar GET ou POST e apertar Send.

Isso seria como dizer que ISPF serve para editar texto.

Tecnicamente não está completamente errado.

Mas estamos ignorando quase todo o universo existente atrás da ferramenta.

Uma requisição HTTP pode possuir:

Método
URL
Headers
Parâmetros
Autenticação
Body
Scripts
Testes
Variáveis

Por exemplo:

POST /orders
Content-Type: application/json
Authorization: Bearer {{token}}

Body:

{
  "customerId": "12345",
  "productId": "A100",
  "quantity": 2
}

O Postman permite construir essa requisição, enviá-la e analisar a resposta.

Mas o salto de maturidade acontece quando paramos de pensar em requests isolados e começamos a pensar em Collections.

Uma Collection não deveria ser apenas uma pasta cheia de requisições.

Ela pode representar um verdadeiro sistema automatizado de testes da API.

E isso muda completamente o jogo.



🗃️ CAPÍTULO 2 — COLLECTION: A BOLSA DO CARTEIRO

Imagine a bolsa do nosso carteiro.

Não faria sentido jogar dentro dela milhares de cartas aleatoriamente.

Ele organiza:

Distrito
 ├── Rua
 │    ├── Número
 │    └── Destinatário

Uma Collection bem construída também precisa possuir estrutura.

Por exemplo:

Orders API
│
├── 01 - Authentication
│
├── 02 - Customers
│   ├── Create Customer
│   ├── Get Customer
│   └── Update Customer
│
├── 03 - Orders
│   ├── Create Order
│   ├── Get Order
│   ├── Update Order
│   └── Cancel Order
│
└── 04 - Negative Tests
    ├── Invalid Token
    ├── Customer Not Found
    ├── Invalid Quantity
    └── Forbidden User

Perceba uma coisa importante.

Estamos começando a transformar a Collection em algo parecido com uma especificação executável.

Ela documenta o sistema.

Ela executa o sistema.

Ela testa o sistema.

Ela pode ser compartilhada.

E posteriormente poderá entrar em um pipeline.

Isso é muito diferente de guardar meia dúzia de URLs.



✉️ CAPÍTULO 3 — PRIMEIRO ENTENDA A CARTA

Antes de criar uma request, precisamos entender o contrato.

Suponha:

POST /orders

Pergunte:

O que devo enviar?

{
  "customerId": "C123",
  "productId": "P987",
  "quantity": 2
}

O que espero receber?

{
  "orderId": "O456",
  "status": "CONFIRMED"
}

Qual status HTTP deveria aparecer?

Talvez:

201 Created

Agora temos uma expectativa.

Entrada:

customerId
productId
quantity

Saída:

orderId
status

Esse conceito deveria soar extremamente familiar para quem programa COBOL.

Pense em:

01 WS-REQUEST.
   05 WS-CUSTOMER-ID PIC X(10).
   05 WS-PRODUCT-ID  PIC X(10).
   05 WS-QUANTITY    PIC 9(03).

01 WS-RESPONSE.
   05 WS-ORDER-ID    PIC X(10).
   05 WS-STATUS      PIC X(10).

Mudou a tecnologia.

O princípio continua parecido:

existe uma estrutura de entrada e existe uma estrutura esperada de saída.

O programador COBOL chama isso de layout.

O desenvolvedor moderno talvez chame de contrato.

O carteiro chama de endereço.

Se qualquer um deles estiver errado, alguém receberá a correspondência errada.



🌐 CAPÍTULO 4 — 200 OK NÃO SIGNIFICA “TUDO CERTO”

Este talvez seja o conceito mais importante de toda a conversa.

Considere:

GET /customers/123

Resposta:

200 OK

Body:

{
  "customerId": "999",
  "name": "Mario"
}

A camada HTTP funcionou perfeitamente.

Mas a aplicação falhou.

Você pediu:

123

e recebeu:

999

Portanto precisamos testar diferentes níveis.

No Postman podemos escrever:

pm.test("HTTP status is 200", function () {
    pm.response.to.have.status(200);
});

Mas podemos continuar:

const customer = pm.response.json();

pm.test("Customer ID is correct", function () {
    pm.expect(customer.customerId).to.eql("123");
});

Agora não estamos apenas perguntando:

O servidor respondeu?

Estamos perguntando:

O servidor respondeu corretamente?

Essa diferença separa um teste superficial de um teste realmente útil.


🧠 CAPÍTULO 5 — O CARTEIRO DESCOBRE AS REGRAS DE NEGÓCIO

Imagine que criamos um pedido.

A resposta é:

{
  "orderId": "4711",
  "status": "REJECTED"
}

E recebemos:

200 OK

O transporte funcionou.

Mas talvez nossa expectativa fosse:

status = CONFIRMED

Portanto:

const order = pm.response.json();

pm.test("Order must be confirmed", function () {
    pm.expect(order.status).to.eql("CONFIRMED");
});

Isso é extremamente importante em sistemas mainframe.

Porque muitas aplicações antigas possuem códigos internos de retorno.

Um programa pode devolver algo conceitualmente semelhante a:

RETURN-CODE = 04
MESSAGE     = CUSTOMER BLOCKED

Enquanto uma camada REST pode responder:

200 OK

Se testarmos somente HTTP, podemos declarar sucesso para uma transação que o negócio considera fracasso.

O teste precisa conhecer o significado da resposta.

O poeta não quer saber apenas se a carta chegou.

Ele quer saber se Beatrice leu o poema certo.


📐 CAPÍTULO 6 — TESTANDO O CONTRATO

Agora podemos subir outro degrau.

Não queremos verificar somente valores.

Também queremos verificar estrutura.

Imagine que nossa API deveria responder:

{
  "orderId": "4711",
  "status": "CONFIRMED",
  "amount": 150.00
}

Mas depois de uma alteração recebemos:

{
  "id": 4711,
  "state": "OK"
}

O serviço respondeu.

Mas o contrato mudou completamente.

Isso pode quebrar consumidores.

Imagine um aplicativo esperando:

response.orderId

e alguém muda para:

response.id

Boom.

Não houve necessariamente ABEND no backend.

Mas houve um ABEND conceitual no consumidor.

Schema validation ajuda a detectar mudanças estruturais desse tipo.

Ela pode verificar coisas como:

campo obrigatório
tipo
formato
estrutura

Mas há uma sutileza.

Schema não prova que o conteúdo está correto.

Isto:

{
  "orderId": "9999",
  "status": "CONFIRMED"
}

pode estar estruturalmente perfeito e ainda pertencer ao cliente errado.

Portanto:

Schema Validation
        +
Business Assertions

são complementares.


🔤 CAPÍTULO 7 — VARIÁVEIS: O WORKING-STORAGE DO POSTMAN

Agora começa uma das partes mais interessantes para quem vem do COBOL.

Em vez de escrever:

https://qa.company.com/api/orders/123

podemos utilizar:

{{baseUrl}}/orders/{{orderId}}

E definir:

baseUrl = https://qa.company.com/api
orderId = 123

Podemos possuir ambientes diferentes:

DEV
QA
STAGING

Mudamos o ambiente.

A Collection continua igual.

Isso é poderosíssimo.

Para um programador COBOL, pense nas variáveis como uma espécie de combinação entre parâmetros, configuração e WORKING-STORAGE.

Mas existe uma armadilha.

Variáveis podem existir em diferentes escopos.

Se houver valores duplicados em locais diferentes, podemos executar um teste utilizando um valor que não imaginávamos.

É o equivalente moderno de perguntar:

Quem alterou essa variável?

E descobrir que existem quatro lugares diferentes onde ela poderia ter sido definida.

Dica de sobrevivência:

sempre investigue o valor resolvido, não apenas o nome escrito na request.


🔐 CAPÍTULO 8 — O CARTEIRO PRECISA MOSTRAR O CRACHÁ

APIs modernas frequentemente utilizam tokens.

Por exemplo:

Authorization: Bearer {{accessToken}}

Em vez de configurar autenticação individualmente em cinquenta requests, podemos defini-la na Collection e permitir herança.

Isso reduz repetição.

Mas surge uma distinção fundamental:

Authentication ≠ Authorization

Authentication pergunta:

Quem é você?

Authorization pergunta:

Você pode fazer isso?

Um usuário pode estar perfeitamente autenticado e ainda não possuir autorização para cancelar um pedido.

Por isso os testes precisam explorar situações como:

token ausente
token inválido
token expirado
usuário autenticado sem permissão

E aqui aparece uma pegadinha maravilhosa.

Você cria um teste chamado:

NO TOKEN

remove o token da request...

...e o teste continua funcionando.

Por quê?

Porque a request herdou a autenticação da Collection.

Seu teste negativo acabou sendo positivo sem você perceber.

É o tipo de bug que faz um QA olhar para a tela durante alguns segundos e começar a reconsiderar suas escolhas profissionais.


⚙️ CAPÍTULO 9 — PRE-REQUEST SCRIPT: PREPARANDO A CARTA

Antes de uma request ser enviada, podemos executar scripts.

Por exemplo, gerar um identificador:

const requestId = pm.variables.replaceIn("{{$guid}}");
pm.collectionVariables.set("requestId", requestId);

Depois enviamos:

X-Request-ID: {{requestId}}

Agora cada transação possui uma identidade.

E aqui nossa história chega ao mainframe.

Imagine:

Postman
   ↓
API Gateway
   ↓
z/OS Connect
   ↓
CICS
   ↓
COBOL
   ↓
Db2

Se o mesmo identificador puder ser correlacionado ao longo desse caminho, investigar um problema se torna muito mais poderoso.

Em vez de procurar:

aquela transação que aconteceu mais ou menos às 14:32...

podemos procurar:

Request-ID = 8f7a...

Isso aproxima teste de observabilidade.

E observabilidade é quando o carteiro não sabe apenas que saiu da agência: ele consegue descobrir por quais ruas a carta passou.


🔗 CAPÍTULO 10 — UMA CARTA LEVA À OUTRA

Agora criamos um pedido:

POST /orders

Resposta:

{
  "orderId": "4711"
}

Podemos capturar esse ID:

const body = pm.response.json();

pm.collectionVariables.set(
    "orderId",
    body.orderId
);

A próxima request utiliza:

GET /orders/{{orderId}}

Depois:

PUT /orders/{{orderId}}

Finalmente:

DELETE /orders/{{orderId}}

Criamos um workflow:

CREATE
   ↓
READ
   ↓
UPDATE
   ↓
DELETE

Isso é muito mais poderoso do que requests isoladas.

Estamos testando uma jornada.


💣 CAPÍTULO 11 — TESTE O QUE DEVERIA DAR ERRADO

Desenvolvedores naturalmente gostam de testar:

entrada correta → resultado correto

Mas sistemas reais vivem no território de:

entrada errada
campo ausente
valor máximo
valor mínimo
token expirado
registro inexistente
duplicidade
timeout
permissão insuficiente

Um excelente princípio é:

altere uma condição de cada vez.

Se você alterar cinco coisas simultaneamente e receber erro, não saberá qual delas provocou o comportamento.

Comece com um baseline válido.

Depois altere somente:

quantity = -1

Depois:

quantity = 0

Depois:

quantity = 1

E chegamos aos testes de fronteira.


📏 CAPÍTULO 12 — COBOL ADORA FRONTEIRAS

Suponha:

05 WS-AGE PIC 9(02).

O campo possui limitações claras.

Em APIs também precisamos pensar em limites.

Se uma regra aceita valores entre 1 e 100:

MIN - 1 = 0
MIN     = 1
MIN + 1 = 2

MAX - 1 = 99
MAX     = 100
MAX + 1 = 101

Não teste apenas:

50

O valor 50 provavelmente funciona.

Os monstros costumam morar nas bordas.

Esse princípio aparece em praticamente todas as gerações de computação.

Cartão perfurado, COBOL, Db2, Java, REST ou JSON: limites continuam sendo lugares maravilhosos para encontrar bugs.


📚 CAPÍTULO 13 — UMA REQUEST, CEM CARTAS

Imagine testar:

quantity

com dezenas de valores.

Não queremos duplicar a mesma request cinquenta vezes.

Podemos usar dados externos.

Por exemplo:

quantity,expectedStatus
1,201
2,201
0,400
-1,400
101,400

No teste:

const expected =
    Number(pm.iterationData.get("expectedStatus"));

pm.test("Expected HTTP status", function () {
    pm.expect(pm.response.code).to.eql(expected);
});

Agora temos data-driven testing.

A lógica do teste permanece.

Os dados mudam.

Programadores COBOL deveriam reconhecer imediatamente a beleza disso.

É quase como um processamento batch:

READ INPUT
PERFORM PROCESS-RECORD
PERFORM VALIDATE
READ NEXT

O Postman Runner passa a executar diferentes iterações sobre a mesma lógica.

O velho batch está sorrindo discretamente no fundo da sala.


🏃 CAPÍTULO 14 — COLLECTION RUNNER: O BATCH DAS APIs

Chega uma hora em que clicar em Send deixa de fazer sentido.

Temos:

20 requests
50 datasets
30 assertions
4 workflows

Queremos executar tudo.

É aí que entra o Runner.

Conceitualmente:

Inicializa
   ↓
Carrega ambiente
   ↓
Executa request
   ↓
Executa testes
   ↓
Armazena variáveis
   ↓
Executa próxima request
   ↓
Gera resultados

Parece familiar?

Claro.

Isso é praticamente a filosofia batch reaparecendo em roupas modernas.

A tecnologia mudou.

A ideia de processamento repetível e automatizado continua conosco.


🧹 CAPÍTULO 15 — O FANTASMA DO ESTADO ANTERIOR

Um dos bugs mais traiçoeiros em testes automatizados é o estado residual.

Imagine que ontem:

orderId = 4711

Hoje o POST falha.

Mas a variável ainda contém:

4711

A próxima request executa:

GET /orders/4711

e funciona.

Resultado?

Parece que o workflow passou.

Mas estamos consultando o pedido de ontem.

Esse é um falso positivo perigosíssimo.

Por isso suítes maduras precisam pensar em:

setup
execução
validação
cleanup

Teste repetível significa:

posso executá-lo novamente sem depender dos fantasmas deixados pela execução anterior.


🔦 CAPÍTULO 16 — DEBUGUE NA ORDEM CERTA

Quando algo falhar, não comece alterando JavaScript aleatoriamente.

Siga uma investigação disciplinada:

Endpoint
   ↓
Environment
   ↓
Variáveis resolvidas
   ↓
Authentication
   ↓
Headers
   ↓
Request body
   ↓
Response
   ↓
Scripts
   ↓
Dados
   ↓
Ordem do workflow

Se funciona individualmente mas falha no Runner, desconfie especialmente de:

ordem
estado
variáveis
dados
dependências

Essa disciplina lembra investigação de incidente no mainframe.

Você não começa culpando o COBOL.

Primeiro reconstrói o caminho.


📖 CAPÍTULO 17 — UMA COLLECTION DEVE SOBREVIVER AO SEU CRIADOR

Chegamos a uma pergunta excelente:

Se eu entregar minha Collection para outro desenvolvedor, ele consegue executá-la?

Se a resposta for:

“Sim, mas primeiro preciso explicar umas quinze coisas...”

a documentação ainda não está boa.

Explique:

objetivo
pré-requisitos
ambiente
autenticação
variáveis
ordem de execução
dados necessários
resultado esperado

Inclua exemplos.

Remova segredos.

Nunca transforme uma Collection compartilhada em cofre de:

password
API key
client secret
token permanente

Uma suíte de testes também é código.

Trate-a como tal.


🚂 CAPÍTULO 18 — A COLLECTION ENTRA NO CI/CD

Aqui acontece a grande transformação.

Antes:

Programador
   ↓
Postman
   ↓
Send

Depois:

Commit
   ↓
Build
   ↓
Deploy QA
   ↓
API Tests
   ↓
Resultado
   ↓
Pipeline continua ou falha

Agora o teste deixa de depender de alguém lembrar de apertar um botão.

Podemos executar smoke tests depois do deploy.

Podemos executar regressão.

Podemos impedir que uma mudança incompatível avance silenciosamente.

Em um ambiente mainframe moderno, podemos imaginar:

Git
 ↓
COBOL + COPYBOOK
 ↓
DBB / Build
 ↓
Deploy
 ↓
z/OS Connect
 ↓
Postman API Tests
 ↓
CICS
 ↓
COBOL
 ↓
Db2

O COBOL não deixou de ser COBOL.

O mainframe não deixou de ser mainframe.

Nós simplesmente construímos uma estrada moderna até ele.


🧬 CAPÍTULO 19 — O MAPA MENTAL DO PROGRAMADOR COBOL

Se você está começando em APIs, guarde esta tradução mental:

POSTMAN                    COBOL / MAINFRAME

Iteration Data       →     Arquivo de entrada
Variables            →     WORKING-STORAGE/configuração
Pre-request Script   →     Inicialização
HTTP Request         →     Chamada/transação
JSON Body            →     Estrutura de dados
Response             →     Estrutura retornada
pm.test              →     Validação
Collection           →     Conjunto organizado de processos
Runner               →     Batch automatizado
Environment          →     DEV / QA / PROD
Workflow             →     Sequência transacional
CI/CD                →     Esteira automatizada
Correlation ID       →     Identidade rastreável da transação

Não são equivalências tecnológicas perfeitas.

São pontes mentais.

E pontes são extremamente úteis quando estamos aprendendo um mundo novo.


🕵️ CAPÍTULO 20 — O NÍVEL QUE QUASE NINGUÉM ENSINA

Existe ainda um passo além.

Imagine que um teste falhou:

POST /payment

Resposta:

500 Internal Server Error

Uma suíte básica informa:

FAILED

Uma engenharia madura pergunta:

Por quê?

Imagine conseguir seguir:

Postman
   │
   │ correlation-id = POETA-0317
   ↓
API Gateway
   ↓
z/OS Connect
   ↓
CICS
   ↓
TRANSACTION ABCD
   ↓
COBOL PAYMENT01
   ↓
Db2
   ↓
SQLCODE -911

Agora não temos apenas automação.

Temos rastreabilidade.

O teste encontrou o sintoma.

A observabilidade mostrou o caminho.

Os logs forneceram evidência.

O mainframe revelou a causa.

🥚 EASTER EGG

Se algum dia encontrar nos exemplos do Bellacosa Mainframe uma transação executada exatamente às:

03:17

não tente corrigir o relógio.

O mainframe sabe perfeitamente que horas são.

Algumas transações simplesmente preferem trabalhar no turno da madrugada.


🎓 EPÍLOGO — O POETA FINALMENTE ENTENDEU O CARTEIRO

No começo de nossa história, tínhamos:

URL
 ↓
Send
 ↓
200 OK

Parecia suficiente.

Depois descobrimos um universo inteiro:

API CONTRACT
      ↓
COLLECTION
      ↓
ENVIRONMENT
      ↓
VARIABLES
      ↓
AUTHENTICATION
      ↓
PRE-REQUEST
      ↓
REQUEST
      ↓
RESPONSE
      ↓
ASSERTIONS
      ↓
SCHEMA
      ↓
BUSINESS RULES
      ↓
NEGATIVE TESTS
      ↓
BOUNDARIES
      ↓
WORKFLOWS
      ↓
DATA-DRIVEN TESTS
      ↓
RUNNER
      ↓
DEBUG
      ↓
DOCUMENTATION
      ↓
CI/CD
      ↓
OBSERVABILITY

Essa é a verdadeira evolução.

Você começa testando uma API.

Depois constrói uma suíte.

Depois transforma essa suíte em regressão.

Depois conecta a regressão ao pipeline.

Finalmente conecta os testes à observabilidade e consegue seguir uma transação desde o mundo distribuído até o programa COBOL que executou a regra de negócio.

E então acontece algo curioso.

A tecnologia mais moderna da arquitetura encontra uma das mais antigas.

JSON encontra COPYBOOK.

REST encontra CICS.

OAuth encontra RACF.

CI/CD encontra COBOL.

Postman encontra z/OS.

E nenhum deles precisa destruir o outro.

Porque modernizar mainframe não significa necessariamente arrancar o coração da aplicação e reescrevê-lo.

Às vezes significa simplesmente construir melhores caminhos para chegar até ele.

É justamente aí que O Carteiro e o Poeta se torna uma metáfora perfeita.

O carteiro domina o transporte.

O poeta domina o significado.

Uma boa API precisa dos dois.

Não basta entregar bytes.

Precisamos entregar os bytes certos, ao serviço certo, com a identidade certa, na sequência certa, respeitando o contrato certo e produzindo o resultado de negócio esperado.

Da próxima vez que o Postman mostrar:

200 OK

não feche o teste.

Olhe para aquele verde bonito e pergunte:

“Muito bem, carteiro. Você entregou a carta. Agora me prove que entregou a carta certa.”

☕ Porque no Bellacosa Mainframe, até uma API precisa apresentar evidências antes de sair da War Room.

sexta-feira, 3 de fevereiro de 2023

🧀 WALLACE & GROMIT E A MÁQUINA QUE FABRICAVA AMBIENTES DE MAINFRAME

 

Bellacosa Mainframe e o ambiente de testes em mainframe

☕ Um Café no Bellacosa Mainframe

🧀 WALLACE & GROMIT E A MÁQUINA QUE FABRICAVA AMBIENTES DE MAINFRAME

COBOL, Db2, IMS, CICS, test data, ambientes efêmeros, service virtualization, CI/CD, DevOps, shift-left, RACF — e o dia em que Wallace descobriu que automatizar o build não adiantava muito quando Gromit precisava esperar três dias pelo ambiente de testes.

Sob a tutela de Wallace & Gromit — porque, no mainframe, construir uma máquina gigantesca para economizar cinco minutos pode parecer absurdo... até descobrirmos que estamos perdendo três dias esperando um DBA.


 



🎬 PRÓLOGO — UMA MANHÃ TRANQUILA EM WEST WALLABY STREET

Wallace acordou com uma ideia brilhante.

Isso normalmente era perigoso.

Ele levantou da cama, apertou alguns botões e anunciou:

— Gromit! Precisamos modernizar o mainframe!

Gromit abaixou o jornal lentamente.

Sobre a mesa havia um programa COBOL.

Nada particularmente assustador.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. CRD001.

       PROCEDURE DIVISION.

           EXEC SQL
              SELECT LIMITE_CREDITO,
                     STATUS_CLIENTE
                INTO :WS-LIMITE,
                     :WS-STATUS
                FROM CLIENTE
               WHERE CLIENTE_ID = :WS-ID
           END-EXEC.

Wallace explicou:

— Só precisamos alterar uma regra!

Gromit olhou novamente para o programa.

Parecia simples.

Alterar.

Compilar.

Testar.

Entregar.

Wallace então abriu outro papel.

Para testar aquela pequena alteração seriam necessários:

  • uma região CICS;

  • um subsistema Db2;

  • tabelas atualizadas;

  • dados de clientes;

  • packages;

  • plans;

  • permissões RACF;

  • filas MQ;

  • datasets;

  • programas dependentes;

  • eventualmente IMS;

  • talvez uma API externa;

  • e um ambiente que não estivesse sendo usado por outro projeto.

Gromit fechou os olhos.

A alteração levaria talvez duas horas.

Conseguir tudo necessário para testá-la poderia levar dois dias.

E aqui começa nossa história.

Porque um dos grandes problemas do desenvolvimento moderno no mainframe não está necessariamente no COBOL.

Está no tempo entre:

EU TERMINEI O PROGRAMA

e:

EU CONSIGO TESTAR O PROGRAMA

Pegue seu café.

Wallace já está construindo uma máquina.

Isso nunca termina de maneira simples.



🧀 CAPÍTULO 1 — O COBOL NÃO É NECESSARIAMENTE O GARGALO

Existe uma ideia curiosa no mercado:

Sistemas mainframe são lentos para mudar porque COBOL é antigo.

Isso é uma simplificação perigosa.

Um programador experiente pode fazer rapidamente uma alteração COBOL relativamente pequena.

O verdadeiro fluxo pode ser:

REQUISITO
   ↓
COBOL
   ↓
COMPILE
   ↓
LINK
   ↓
DEPLOY
   ↓
CICS
   ↓
Db2
   ↓
DADOS
   ↓
INTEGRAÇÕES
   ↓
TESTE

Agora imagine que cada seta possa envolver outra equipe.

O programador termina.

Precisa do DBA.

O DBA precisa preparar alguma coisa.

Depois precisa do administrador CICS.

Depois segurança.

Depois alguém precisa restaurar dados.

Depois descobrem que SIT está ocupado.

A aplicação levou duas horas para mudar.

O processo levou quatro dias.

Wallace olharia para isso e imediatamente construiria uma máquina com 47 engrenagens, três chaleiras, duas correias transportadoras e provavelmente um dispensador automático de queijo.

Gromit faria algo melhor:

mediria onde está o tempo perdido.



⏱️ CAPÍTULO 2 — O TEMPO QUE NINGUÉM COLOCA NO DASHBOARD

Suponha que uma mudança tenha este lead time:

Programação ................  4 h
Build ......................  1 h
Teste ......................  3 h

Esperando ambiente ......... 18 h
Esperando dados ............ 10 h
Esperando deploy ........... 12 h
Esperando aprovação ........  8 h

Temos:

TRABALHO EFETIVO ...........  8 h
ESPERA ..................... 48 h

A empresa poderia comprar uma ferramenta que faça o programador produzir código 25% mais rapidamente.

Fantástico.

Talvez economize uma hora.

Ou poderia reduzir pela metade as filas.

Economizaria 24 horas.

É por isso que uma métrica interessante para DevOps é:

Developer Waiting Time

Quanto tempo um desenvolvedor passa esperando alguma coisa necessária para continuar?

Isso pode revelar gargalos invisíveis.

É quase como aplicar conceitos de filas e workload management ao próprio processo de desenvolvimento.

Wallace quer melhorar a máquina.

Gromit primeiro observa onde a máquina está parada.



🏭 CAPÍTULO 3 — DEV, SIT, UAT E A ÚNICA REGIÃO CICS DA VILA

Imagine uma organização com:

DEV
 ↓
SIT
 ↓
UAT
 ↓
PRE-PROD
 ↓
PROD

Parece organizado.

Até descobrirmos que dezenas de desenvolvedores compartilham os mesmos ambientes.

Na segunda-feira:

SIT reservado para Projeto A.

Terça:

indisponível para manutenção.

Quarta:

Projeto B executando regressão.

Quinta:

dados inconsistentes.

Sexta:

release freeze.

Nosso programador COBOL pensa:

Posso testar na próxima semana?

Aqui surge um princípio fundamental:

Ambiente de teste também é recurso computacional.

E recurso computacional pode ser provisionado, configurado, versionado e automatizado.

Essa mudança de pensamento é enorme.



🗄️ CAPÍTULO 4 — Db2: TER O BANCO NÃO SIGNIFICA TER O TESTE

Wallace consegue finalmente um ambiente Db2.

Ele comemora.

Gromit aponta para a tabela CLIENTE.

Há três clientes.

Todos ativos.

Nosso programa precisa testar:

CLIENTE NORMAL
CLIENTE BLOQUEADO
CLIENTE INEXISTENTE
CLIENTE VIP
CONTA ENCERRADA
LIMITE EXCEDIDO
SALDO NEGATIVO
CARTÃO EXPIRADO
CARTÃO ROUBADO
TRANSAÇÃO DUPLICADA

Temos ambiente.

Não temos dados úteis.

Essa diferença é fundamental.

Um banco de desenvolvimento com milhões de registros inúteis pode ser pior para QA do que alguns milhares cuidadosamente preparados.

E simplesmente copiar produção cria outro conjunto de problemas:

LGPD
PCI DSS
dados pessoais
dados financeiros
segredos
volume
permissões
mascaramento
retenção
auditoria

Portanto surge uma disciplina importantíssima:

Test Data Management


🧩 CAPÍTULO 5 — NÃO COPIE APENAS A TABELA CUSTOMER

Suponha:

CUSTOMER
   │
   ├── ACCOUNT
   │      ├── TRANSACTION
   │      └── PAYMENT
   │
   └── CARD
          └── AUTHORIZATION

Você seleciona 100 clientes.

Excelente.

Mas se copiar somente CUSTOMER, sua aplicação pode procurar contas que não existem.

Se copiar ACCOUNT, mas esquecer TRANSACTION, outro teste quebra.

Se copiar CARD, talvez precise preservar relações com autorizações.

Portanto um bom subconjunto de dados precisa manter consistência referencial e semântica.

Não queremos apenas dados.

Queremos uma pequena representação coerente do mundo.


🌳 CAPÍTULO 6 — IMS: AGORA GROMIT DESCOBRIU UMA ÁRVORE

Db2 normalmente nos faz pensar em tabelas.

IMS DB introduz outro modelo mental.

Imagine:

CUSTOMER
│
├── ACCOUNT
│   ├── TRANSACTION
│   └── PAYMENT
│
└── ADDRESS

Aqui podemos estar lidando com estruturas hierárquicas.

O programador COBOL pode encontrar operações DL/I como:

GU
GN
GNP

De maneira simplificada:

GU — Get Unique

Procure algo específico.

GN — Get Next

Continue navegando.

GNP — Get Next within Parent

Continue dentro de determinado contexto hierárquico.

Mas IMS não termina no banco.

Podemos encontrar:

IMS DB
IMS TM
DL/I
DBD
PSB
PCB
SSA
IMS Connect

Para um iniciante, isso parece uma sopa de siglas.

Wallace provavelmente tentaria resolver construindo uma máquina de sopa.

Gromit abriria o manual.

A lição é outra:

Quando virtualizamos ou reproduzimos um ambiente, precisamos compreender suas dependências.

Copiar alguns segmentos pode não reproduzir corretamente a situação necessária ao teste.


🏪 CAPÍTULO 7 — CICS: NENHUM PROGRAMA É UMA ILHA

Nosso programa executa:

EXEC CICS LINK
     PROGRAM('PGM002')
     COMMAREA(WS-COMMAREA)
END-EXEC.

Parece apenas uma chamada.

Mas PGM002 pode acessar Db2.

Depois MQ.

Depois outro programa.

Depois uma API.

Temos:

PGM001
   │
   ▼
PGM002
   │
   ├── Db2
   │
   ├── MQ
   │
   └── PGM003
          │
          ▼
        API

Para testar PGM001, precisamos realmente de tudo isso?

Às vezes sim.

Mas nem sempre.

E aí Wallace encontra uma nova caixa de ferramentas.


🎭 CAPÍTULO 8 — MOCKS, STUBS E SERVICE VIRTUALIZATION

Imagine que PGM001 precise chamar um serviço antifraude.

Em produção:

COBOL
  ↓
CICS
  ↓
MQ
  ↓
ANTIFRAUDE

Mas nosso objetivo atual é testar somente uma regra COBOL.

Podemos substituir temporariamente uma dependência por um comportamento controlado.

Por exemplo:

COBOL
  ↓
SERVIÇO VIRTUAL
  ↓
RESPOSTA CONTROLADA

O serviço virtual pode responder:

{
  "riskScore": 87,
  "decision": "REVIEW"
}

Agora conseguimos testar nosso programa sem depender do sistema antifraude real.

Melhor ainda.

Podemos ordenar:

Agora devolva timeout.

Depois:

Agora devolva erro.

Depois:

Agora envie resposta inválida.

Assim podemos criar:

SUCCESS
TIMEOUT
DENIED
INVALID
DUPLICATE
UNAVAILABLE

Isso é extraordinariamente útil.


💣 CAPÍTULO 9 — GROMIT DESCOBRE QUE QUEBRAR O SISTEMA TAMBÉM É TESTAR

Testar não significa verificar apenas:

ENTRADA CORRETA → RESULTADO CORRETO

Precisamos descobrir:

O QUE ACONTECE QUANDO ALGO DÁ ERRADO?

Imagine:

TRANSACTION
     │
     ▼
   CICS
     │
     ▼
   COBOL
     │
     ├── Db2 → SQLCODE -911
     │
     ├── MQ  → problema na fila
     │
     └── API → HTTP 503

Como o programa reage?

Faz rollback?

Tenta novamente?

Duplica uma transação?

Perde informação?

Produz mensagem compreensível?

Grava evidência suficiente?

Isso nos leva aos testes negativos.

Eles são particularmente valiosos porque muitos incidentes graves não acontecem durante o happy path.

Acontecem nas exceções.


🥚 EASTER EGG — 03:17

Wallace finalmente termina sua máquina.

Relógio:

03:17.

Gromit olha preocupado.

A API retorna timeout.

O MQ começa a acumular mensagens.

Db2 apresenta contenção.

CICS espera.

Wallace pergunta:

— Por que ninguém testou isso?

Porque todos testaram:

HTTP 200
SQLCODE 0
MQ OK
CICS OK

Ninguém perguntou:

E se três coisas falharem juntas?

O incidente das 03:17 nasceu exatamente no lugar onde terminava o happy path.


⚡ CAPÍTULO 10 — E SE O DESENVOLVEDOR PUDESSE PEDIR UM MAINFRAME?

Aqui chegamos a uma mudança conceitual enorme.

Modelo tradicional:

DEVELOPER
    ↓
TICKET
    ↓
SYSPROG
    ↓
DBA
    ↓
SECURITY
    ↓
CICS ADMIN
    ↓
WAIT
    ↓
ENVIRONMENT

Agora imagine:

DEVELOPER
    ↓
SELF-SERVICE
    ↓
TEMPLATE APROVADO
    ↓
PROVISION
    ↓
AMBIENTE DEV/TEST

Não estamos falando de entregar produção para o desenvolvedor.

Estamos falando de criar ambientes isolados e governados para desenvolvimento e testes.

O conceito pode incluir tecnologias de virtualização e ofertas destinadas a proporcionar ambientes z/OS de desenvolvimento e teste de maneira muito mais rápida.

A pergunta deixa de ser:

Qual LPAR está livre?

E passa a ser:

Qual configuração de ambiente eu preciso?

Essa mudança é gigantesca.


🧀 CAPÍTULO 11 — WALLACE INVENTA O MAINFRAME DESCARTÁVEL

Não descarte o IBM Z!

Calma.

Estamos falando do ambiente de desenvolvimento.

Imagine:

CREATE
  ↓
TEST
  ↓
COLLECT EVIDENCE
  ↓
DESTROY

Ou:

TEMPLATE
   ↓
ENVIRONMENT A
ENVIRONMENT B
ENVIRONMENT C

Cada squad pode trabalhar com isolamento muito maior.

Isso nos aproxima do conceito de ambientes efêmeros.

O ambiente nasce para cumprir determinada finalidade.

Executamos os testes.

Coletamos logs e evidências.

Depois ele pode ser removido.

Amanhã outro ambiente é criado novamente a partir de uma configuração conhecida.


🧬 CAPÍTULO 12 — INFRASTRUCTURE AS CODE ENCONTRA O COBOL

Wallace adora infraestrutura.

Especialmente se possuir alavancas.

DevOps prefere arquivos declarativos, APIs e automação.

Conceitualmente:

environment:
  zos: enabled
  cics: enabled
  db2: enabled
  ims: enabled
  mq: enabled

Não estou dizendo que essa configuração fictícia cria magicamente um ambiente real.

Ela ilustra a ideia.

A infraestrutura deixa de existir apenas como conhecimento informal:

Pergunte ao José porque ele sabe configurar.

E passa a ser descrita de maneira reproduzível.

Isso gera:

padronização
repetibilidade
auditabilidade
automação
velocidade

🚀 CAPÍTULO 13 — RAPID PROTOTYPING

Agora alguém propõe:

Vamos expor esta transação CICS através de REST.

Antes:

REUNIÃO
 ↓
TICKET
 ↓
AMBIENTE
 ↓
CONFIGURAÇÃO
 ↓
TESTE

Com um laboratório disponível:

CICS
 ↓
COBOL
 ↓
Db2
 ↓
API
 ↓
JSON
 ↓
POSTMAN

Podemos experimentar.

Não funcionou?

Reconfiguramos.

Quebrou?

Restauramos.

A ideia é importante porque experimentação precisa ser barata.

Quando cada tentativa exige uma semana de burocracia, as pessoas naturalmente experimentam menos.


🔬 CAPÍTULO 14 — SHIFT LEFT NÃO É EMPURRAR UMA CAIXINHA NO POWERPOINT

Você provavelmente já viu:

DEV → TEST → QA → UAT → PROD

E alguém desenhou uma seta enorme:

← SHIFT LEFT

Pronto.

Transformação digital concluída.

Não.

Shift left significa descobrir problemas mais cedo.

Idealmente:

DEV
 ↓
UNIT TEST
 ↓
INTEGRATION TEST
 ↓
SYSTEM TEST
 ↓
UAT
 ↓
PROD

Quanto mais cedo encontramos:

erro de lógica
SQL incorreto
dependência quebrada
contrato incompatível
timeout
problema de dados

menor tende a ser o custo de correção.

Encontrar um erro cinco minutos depois de escrevê-lo é muito diferente de encontrá-lo durante uma janela de implantação.

Ou às 03:17.


🏭 CAPÍTULO 15 — GROMIT CONSTRÓI UM PIPELINE

Agora tudo começa a se encaixar.

git push
   │
   ▼
BUILD
   │
   ▼
STATIC ANALYSIS
   │
   ▼
UNIT TEST
   │
   ▼
PROVISION ENVIRONMENT
   │
   ▼
DEPLOY
   │
   ▼
TEST DATA
   │
   ▼
INTEGRATION TEST
   │
   ▼
REGRESSION
   │
   ▼
EVIDENCE
   │
   ▼
PROMOTION

Perceba uma diferença importantíssima.

O ambiente entrou no pipeline.

Antes o pipeline dizia:

Aqui está o executável.

Agora ele pode dizer:

Aqui está o software, o ambiente onde foi validado, os testes executados e suas evidências.

Isso é muito mais poderoso.


🗃️ CAPÍTULO 16 — MAS E O Db2?

Aqui existe uma armadilha clássica.

Aplicação:

APP V1

Banco:

SCHEMA V1

Nova aplicação:

APP V2

Mas ela depende de:

SCHEMA V2

Portanto DevOps não pode cuidar apenas do .CBL.

Precisamos pensar em:

DDL
SQL
BIND
PACKAGE
PLAN
SCHEMA
TEST DATA
MIGRATION
ROLLBACK

Banco de dados também possui ciclo de vida.

Isso é Database DevOps.

E atenção:

automação não significa:

Todo mundo pode executar ALTER em produção.

É justamente o contrário.

Uma boa automação transforma regras em guardrails.


🔐 CAPÍTULO 17 — WALLACE QUASE REMOVE O RACF

Wallace vê todos esses processos automatizados.

— Excelente! Agora todo mundo pode fazer tudo!

Gromit olha horrorizado.

Não.

Self-service não significa ausência de controle.

Continuamos precisando de:

RACF
SAF
least privilege
segregation of duties
audit trail
approvals
data protection
logging
evidence

A diferença é:

Antes

controle = pessoas executando tarefas repetitivas

Depois

controle = políticas + automação + evidência

Esse é um ponto essencial.

DevOps não elimina governança.

DevOps pode transformar governança em código e processos repetíveis.


🧠 CAPÍTULO 18 — MODERNIZAR NÃO SIGNIFICA JOGAR O COBOL FORA

Talvez esta seja a maior lição da aventura.

Durante anos ouvimos modernização descrita assim:

COBOL
 ↓
LEGACY
 ↓
REWRITE
 ↓
CLOUD

Mas existe outra possibilidade:

COBOL
CICS
Db2
IMS
MQ
 ↓
MODERN DEVELOPMENT EXPERIENCE

Podemos manter aplicações extremamente valiosas e modernizar tudo ao redor:

Git
CI/CD
APIs
automated testing
test virtualization
observability
DevSecOps
Infrastructure as Code
automated provisioning
modern IDEs

Isso é modernização sem obrigatoriamente reescrever tudo.


🔭 CAPÍTULO 19 — O MAINFRAME NÃO É MAIS APENAS O DESTINO

Esta é uma mudança profunda.

No modelo antigo:

PIPELINE
   ↓
MAINFRAME

O mainframe era o lugar onde o resultado finalmente chegava.

No modelo moderno:

             PIPELINE
                │
     ┌──────────┼──────────┐
     ▼          ▼          ▼
   BUILD       TEST     ENVIRONMENT
     │          │          │
     └──────────┼──────────┘
                ▼
              z/OS

O próprio ambiente mainframe participa do ciclo.

Provisionamento.

Build.

Teste.

Deploy.

Validação.

Evidência.

Tudo pode integrar uma cadeia de automação.


📊 CAPÍTULO 20 — O DASHBOARD QUE WALLACE ESQUECEU

Estamos acostumados a observar:

CPU
MSU
I/O
latência
throughput
availability
response time

Tudo correto.

Mas DevOps precisa olhar também:

lead time
deployment frequency
change failure
recovery time
test execution time
environment provisioning time
developer waiting time

Imagine descobrir:

Lead time ............... 120 horas

Programando ............. 12
Testando ................ 10

Esperando ambiente ...... 38
Esperando dados ......... 20
Esperando deploy ........ 25
Esperando aprovação ..... 15

Temos:

TRABALHO = 22 horas
ESPERA   = 98 horas

Wallace estava tentando construir uma máquina para fazer COBOL 30% mais rápido.

Gromit apontou para as 98 horas.

Aí Wallace finalmente entendeu.


🛠️ CAPÍTULO 21 — PASSO A PASSO PARA COMEÇAR

Se você está começando em COBOL, não tente construir toda essa arquitetura amanhã.

Comece pequeno.

PASSO 1 — Mapeie uma aplicação

Descubra:

COBOL
 ↓
CICS?
 ↓
Db2?
 ↓
IMS?
 ↓
MQ?
 ↓
API?

PASSO 2 — Mapeie dependências

Pergunte:

Para testar este programa, do que realmente preciso?

PASSO 3 — Separe teste unitário de integração

Nem todo teste precisa do universo inteiro.

PASSO 4 — Identifique dados necessários

Crie casos:

NORMAL
BOUNDARY
INVALID
ERROR
TIMEOUT
DUPLICATE

PASSO 5 — Automatize o build

Compile sempre da mesma maneira.

PASSO 6 — Automatize testes repetitivos

Se alguém executa exatamente os mesmos passos diariamente, existe um ótimo candidato à automação.

PASSO 7 — Crie evidências

Guarde:

build
versão
logs
resultado
dados
timestamp

PASSO 8 — Meça espera

Talvez o maior gargalo não esteja onde todos imaginavam.

PASSO 9 — Virtualize dependências caras

Nem todo sistema externo precisa estar presente em todo teste.

PASSO 10 — Automatize ambientes gradualmente

Comece pelo que produz maior espera.


💡 CAPÍTULO 22 — CURIOSIDADES PARA O PADAWAN COBOL

Primeira curiosidade:

COBOL ser uma linguagem antiga não significa que todo processo ao redor dele precise continuar antigo.

Segunda:

Um programa de 200 linhas pode depender de uma arquitetura com dezenas de componentes.

Terceira:

Mais dados de teste não significa necessariamente melhores testes.

Quarta:

Conseguir provocar um erro propositalmente é uma habilidade extremamente valiosa de QA.

Quinta:

Automação não serve apenas para fazer alguma coisa mais rapidamente.

Ela também serve para fazer alguma coisa da mesma maneira todas as vezes.

Sexta:

Ambiente reproduzível é documentação executável.

Se conseguimos reconstruí-lo automaticamente, sabemos muito mais sobre ele do que quando sua configuração vive apenas na cabeça de algumas pessoas.


🧀 EPÍLOGO — WALLACE FINALMENTE APERTA O BOTÃO

Depois de dias trabalhando, Wallace apresenta sua nova invenção.

Uma máquina gigantesca ocupa toda a garagem.

Gromit observa.

Wallace aperta o botão.

Engrenagens começam a girar.

Git
 ↓
Build
 ↓
COBOL
 ↓
Test
 ↓
Environment
 ↓
CICS
 ↓
Db2
 ↓
IMS
 ↓
MQ
 ↓
Regression
 ↓
Evidence

Uma pequena luz verde acende.

Na tela:

BUILD SUCCESSFUL

UNIT TESTS:       PASS
INTEGRATION:      PASS
NEGATIVE TESTS:   PASS
REGRESSION:       PASS

ENVIRONMENT DESTROYED

Wallace sorri.

— Pronto, Gromit! Automatizamos o mainframe!

Gromit aponta para outra tela:

AVERAGE DEVELOPER WAITING TIME

BEFORE: 31 HOURS
AFTER:   47 MINUTES

Wallace finalmente percebe que aquela era a informação realmente importante.

Eles não tornaram o COBOL moderno.

O COBOL já estava fazendo aquilo para que havia sido criado.

Não substituíram Db2.

Não destruíram IMS.

Não aposentaram CICS.

Não migraram tudo para alguma tecnologia da moda apenas para poder colocar a palavra "modernização" num PowerPoint.

Eles fizeram algo talvez mais inteligente.

Modernizaram o caminho entre a ideia do programador e a evidência de que aquela ideia funciona.

Essa é uma das grandes fronteiras do DevOps no mainframe.

O problema não é necessariamente:

"Como fazemos COBOL parecer uma aplicação cloud?"

Talvez a pergunta correta seja:

"Como permitimos que uma aplicação COBOL, CICS, IMS ou Db2 participe de uma experiência moderna de desenvolvimento sem destruir as qualidades que fizeram esse ecossistema sobreviver por décadas?"

E a resposta passa por:

AUTOMAÇÃO
+
SELF-SERVICE
+
TEST DATA
+
SERVICE VIRTUALIZATION
+
SHIFT LEFT
+
CI/CD
+
AMBIENTES REPRODUZÍVEIS
+
SEGURANÇA
+
OBSERVABILIDADE
+
EVIDÊNCIA

Wallace guarda as ferramentas.

Gromit prepara o chá.

O programador COBOL faz um commit.

O pipeline começa a trabalhar.

Nenhum chamado precisa ser aberto apenas para descobrir se uma pequena alteração funciona.

E em algum lugar dentro do datacenter, silenciosamente, o relógio muda para:

03:16

Gromit olha para ele.

Espera.

03:17

Nada acontece.

Nenhum pager toca.

Nenhuma fila explode.

Nenhum operador corre.

Nenhum programador é acordado.

Gromit toma mais um gole de chá.

Talvez aquele tenha sido o melhor teste de todos.


☕ MORAL DO CAFÉ

Modernizar mainframe não significa necessariamente substituir aquilo que funciona.

Às vezes significa eliminar tudo aquilo que obriga pessoas altamente qualificadas a ficarem esperando.

Porque existe uma diferença enorme entre:

MAINFRAME LEGACY

e:

PROCESSO LEGACY

Não confunda os dois.

O IBM Z pode processar bilhões de transações.

CICS pode responder em frações de segundo.

Db2 pode atender workloads gigantescos.

IMS pode sustentar aplicações críticas durante décadas.

E mesmo assim...

o programador pode ficar três dias esperando um ambiente de teste.

Nesse caso, meu jovem padawan COBOL, talvez a coisa mais lenta do sistema não esteja rodando no mainframe.

Talvez esteja rodando no processo.

E é justamente aí que Wallace & Gromit começariam a construir a próxima máquina.

Welcome to the Mainframe. ☕🧀

segunda-feira, 19 de outubro de 2015

⚙️ z/OS 2.2 — O despertar do Mainframe DevOps 🧩☁️



 






⚙️ z/OS 2.2 — O despertar do Mainframe DevOps 🧩☁️

Por Bellacosa Mainframe — onde o passado conversa com o futuro em EBCDIC e RESTful 😎💻


O z/OS 2.2, lançado oficialmente em setembro de 2015, foi mais que uma simples atualização: foi um marco de mentalidade.
Depois do z/OS 2.1 abrir as portas para a era híbrida e cognitiva, o 2.2 consolidou o conceito do Mainframe moderno, automatizado e pronto para DevOps, com uma pegada mais “cloud-native”, mas ainda com o DNA sólido do System z.

Prepare seu café ☕, porque hoje vamos mergulhar nas entranhas técnicas dessa revolução — o sistema que transformou o jeito de pensar, operar e programar no mundo z.


🧬 1. Contexto histórico — o z/OS entra na era da automação inteligente

O z/OS 2.2 nasceu junto ao IBM z13, uma máquina lendária com até 141 processadores, 10 TB de memória e clock de 5 GHz.
O z13 não era apenas rápido — ele foi desenhado para o mundo do analytics, mobilidade e integração contínua, e o z/OS 2.2 veio para acompanhá-lo.

🔹 Data de lançamento: setembro de 2015
🔹 Última entrega de service: 2017, antes da chegada do 2.3
🔹 Compatível com: zEnterprise EC12, BC12 e z13

O foco? Simplificação da administração, escalabilidade e automação das operações.
O mainframe, enfim, começava a falar “DevOpsês”.


💾 2. O cérebro expandido — memória, CSA e o poder 64-bit

A IBM refinou o modelo de endereçamento 64-bit iniciado no 2.1.
Com o z/OS 2.2, praticamente todo o ambiente de sistema passou a ser endereçável em 64 bits, incluindo:

  • LPA (Link Pack Area) e CSA (Common Service Area) — agora totalmente relocáveis e expansíveis.

  • SQA (System Queue Area) — reorganizada para uso mais eficiente.

  • Memory Objects de até 2 TB por address space.

  • Paging mais inteligente, com balanceamento dinâmico entre SSD e DASD.

💡 Bellacosa Curiosidade: Foi a primeira vez que a IBM implementou algoritmos de prefetch baseados em machine learning interno para otimizar cache e paging — sem precisar de software externo.


⚙️ 3. PR/SM e créditos de CPU — o cérebro oculto do equilíbrio

O PR/SM (Processor Resource/System Manager) ganhou um novo conjunto de truques com o z/OS 2.2, otimizando a interação entre LPARs e workloads concorrentes.

Avanços notáveis:

  • HiperDispatch aprimorado, com melhor localização de cache e “affinity awareness”.

  • WLM (Workload Manager) mais sensível a prioridades de negócios.

  • Dynamic LPAR weight adjustment: o sistema redistribui automaticamente créditos de CPU entre partições conforme o workload.

  • Soft Capping “aware” — agora detecta picos temporários e aplica limites de forma inteligente, evitando throttling brusco.

🎩 Easter Egg técnico: Se você observar o SMF 70-1 do z/OS 2.2, vai notar métricas novas de “CPU delay by dispatch group”. Essa foi uma das primeiras sementes do que viria a ser o Container Performance Management no z/OS 2.4+.


🧰 4. Aplicativos internos e softwares — o z/OS vai para a nuvem

O z/OS 2.2 trouxe uma das maiores ondas de modernização da história do sistema:

🔹 z/OSMF (Management Facility) 2.2

O grande astro da versão.
O z/OSMF deixou de ser “um web painel bonito” e virou uma plataforma de orquestração e automação, com:

  • Workflows automáticos para instalação, migração e tuning;

  • REST APIs nativas para integração com ferramentas externas (Jenkins, Ansible, UrbanCode, etc.);

  • Wizard de Parmlib e profile assistido — o sistema se “autoafina”.

💬 Bellacosa Insight: Foi o nascimento do conceito “Mainframe as Code” dentro da IBM.


🔹 JES2 (V2R2)

Mais rápido, mais limpo e finalmente unicode-aware.

  • Melhor compressão de spool.

  • Novo formato de checkpoint em 64 bits.

  • Subsystem Interface (SSI) modernizada para integração com automações externas.

🔹 RACF

Revisado para suportar mais de 1 milhão de perfis ativos sem degradação.
Novos logs SAF, e suporte inicial a password phrases com 100 caracteres.

🔹 UNIX System Services

Expansão para POSIX 2008, suporte nativo a Python e Node.js (início da integração com z/OS Open Tools).
Shells mais leves, com fork otimizado.

🔹 DFSMS e DFSMShsm

Reorganização total do storage management — agora com:

  • Data Class-aware Tiering, movendo datasets frios para fita automaticamente.

  • Catalog Search Rebuild mais rápido (aquela lerdeza do IDCAMS LISTCAT começou a sumir 😅).


🧩 5. Instruções de máquina e z13 — performance turbinada

O z/OS 2.2 foi otimizado para o novo z13 chip, que trouxe inovações absurdas em instruções e performance:

  • SIMD (Single Instruction, Multiple Data): acelera cálculos matemáticos e criptográficos.

  • Vector Facility: base do que hoje o z16 usa para IA e analytics.

  • Crypto Express5S com hardware AES-GCM e SHA-3 nativo.

  • Transactional Memory 2.0, reduzindo o overhead de locks no DB2.

📈 Resultado: workloads Java, DB2 e CICS ficaram 20% a 30% mais rápidos só com recompilação ou tuning leve.


☁️ 6. Nuvem, APIs e o z/OS Connect (preview edition)

Sim, o z/OS 2.2 foi o “berço” do z/OS Connect Enterprise Edition.
Pela primeira vez, o mainframe falava JSON nativo, publicando e consumindo REST APIs com segurança RACF.

  • CICS TS 5.3 passou a ser o host natural para APIs REST.

  • MQ 8.0 foi integrado como canal de comunicação padrão.

  • E os workloads IMS/DB2 começaram a se comportar como microservices antes da moda.

💬 Curiosidade Bellacosa: algumas demos internas da IBM em 2015 chamavam o z/OS Connect de "Mainframe Tinder", porque ele fazia “match” entre o legado e o mobile. 😂


🔐 7. Segurança, criptografia e auditoria

A segurança subiu de patamar:

  • ICSF (Integrated Cryptographic Services Facility) expandido com novos algoritmos ECC e RSA 4096.

  • Audit Trail centralizado via SMF 80/81, pronto para frameworks como SIEM e QRadar.

  • AT-TLS reforçado com certificados SHA-256.

E claro — zAware (z/OS Analytics for z) ganhou integração nativa: o sistema começava a “entender seu próprio comportamento”.


🧙‍♂️ 8. Curiosidades, bastidores e “fofoquices” IBMianas

  • 🧠 Internamente, o z/OS 2.2 era chamado de “Blue Lightning” — pela cor e velocidade do z13.

  • ☕ O time do z/OSMF 2.2 tinha devs que antes trabalharam no Lotus Notes (sim, os mesmos!).

  • 🧩 Foi a primeira versão que recebeu testes de integração contínua com Jenkins rodando no próprio z/OS.

  • 💬 Rumores dizem que a IBM testou o z/OS 2.2 no “Blue Cloud Lab”, um datacenter experimental com PR/SM distribuído entre continentes.


🚀 9. Conclusão — o Mainframe acorda para o DevOps

O z/OS 2.2 não é só uma atualização: é um ponto de virada cultural e técnico.
Ele uniu o tradicional mundo batch e transacional à filosofia DevOps, APIs e automação, consolidando o que hoje conhecemos como o ecossistema “Hybrid Mainframe”.

O gigante não apenas sobreviveu — ele se reinventou com estilo.
E nós, mainframers, ganhamos um novo brinquedo para brincar de futuro. 😎


Bellacosa Mainframe
☕ Onde bits têm alma e memória tem história.
💬 E você, padawan — lembra a primeira vez que viu o z/OSMF com REST APIs?
Deixe nos comentários: foi amor, susto ou “onde fica o ISPF disso aí?” 😂

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