| Bellacosa Mainframe e o platoon zos entnda vuca bani fragil antifragil e cisnes negros |
☕ Um Café no Bellacosa Mainframe
PLATOON Z/OS — A Patrulha que Entrou Frágil no Batch e Saiu Antifrágil
Como resiliência, antifragilidade, VUCA, BANI e Cisnes Negros explicam a sobrevivência de sistemas que processam bilhões enquanto o mundo dorme
Às 02h17 da madrugada, o datacenter não parecia uma sala de computadores.
Parecia uma selva.
As luzes dos painéis piscavam como vaga-lumes eletrônicos. O ar-condicionado soprava com a insistência de um helicóptero distante. Nos monitores do NOC, milhares de jobs atravessavam o JES2 como pelotões marchando em direção a objetivos que nenhum deles compreendia completamente.
Cada JOB carregava sua missão.
Cada STEP tinha uma responsabilidade.
Cada dataset era uma caixa de munição que não podia desaparecer.
E cada return code poderia decidir quem continuaria avançando e quem ficaria abandonado no spool.
Naquela noite, um jovem programador COBOL chamado Charlie Bell recebeu sua primeira missão crítica em produção.
Seu supervisor apontou para a tela e disse:
— O fechamento bancário está atrasado.
Charlie olhou para o relógio.
02:18.
Depois olhou para o SDSF.
JOBNAME STATUS RC
PAYBATCH ABEND S0C7
O silêncio que se seguiu foi mais assustador do que qualquer alarme.
Havia uma coisa que Charlie ainda não sabia, mas aprenderia antes do amanhecer:
No mainframe, sobreviver a uma falha não é suficiente.
É preciso voltar melhor do que se entrou.
1. O primeiro inimigo: a fragilidade invisível
Charlie abriu o job log.
O programa havia processado 18 milhões de registros corretamente. No registro seguinte, encontrou um campo numérico contendo caracteres inválidos.
O código executou:
ADD WS-VALOR-ENTRADA TO WS-TOTAL.
Só que WS-VALOR-ENTRADA, definida como numérica, havia recebido:
00012A50
O resultado foi o inevitável:
S0C7 - DATA EXCEPTION
O programa morrera por causa de uma única letra.
Dezoito milhões de registros atravessaram o campo de batalha sem problemas. Bastou um registro contaminado para derrubar toda a unidade.
Aquilo era fragilidade.
Um sistema frágil pode funcionar por anos. Ele parece estável, eficiente e confiável. Mas sua estabilidade depende de uma condição perigosa:
Nada inesperado pode acontecer.
O programa de Charlie supunha que todos os registros seriam válidos.
Não havia:
validação antes do cálculo;
registro de rejeitados;
mecanismo de checkpoint;
possibilidade de continuar após um erro;
identificação rápida do registro causador;
estatística de qualidade da entrada.
Era como uma ponte de cristal sobre a qual passavam milhares de veículos todos os dias.
O fato de ainda não ter quebrado não significava que fosse forte.
Significava apenas que o golpe certo ainda não havia chegado.
Fragilidade no mundo COBOL
Para um programador iniciante, a fragilidade aparece em lugares aparentemente inocentes:
MOVE CAMPO-ALFANUMERICO TO CAMPO-NUMERICO.
READ ARQUIVO-CLIENTES.
PERFORM PROCESSAR-REGISTRO
UNTIL WS-FIM-ARQUIVO = 'S'.
Os comandos não estão errados por si mesmos. O perigo está nas premissas escondidas.
O campo sempre será numérico?
O arquivo sempre existirá?
O READ sempre retornará 00?
A chave sempre será encontrada?
O volume sempre caberá no espaço alocado?
O programa sempre terminará dentro da janela?
A fragilidade é frequentemente uma coleção de frases começando com:
“Isso nunca acontece.”
No mainframe, “nunca” é apenas um incidente que ainda não recebeu número de chamado.
2. Frágil, robusto, resiliente e antifrágil
O comandante da madrugada, um veterano conhecido como Sargento Abend, aproximou-se da estação de Charlie.
Ele havia sobrevivido a migrações, conversões de moeda, bugs de ano bissexto, viradas de versão do Db2 e a três projetos anunciados como “o fim definitivo do mainframe”.
Apontou para o S0C7 e perguntou:
— O que você pretende fazer?
— Corrigir o dado e reiniciar o job.
— Isso é recuperação. Mas o que impedirá o próximo dado inválido?
Charlie ficou calado.
O Sargento Abend pegou um marcador e desenhou quatro palavras em um quadro:
FRÁGIL
ROBUSTO
RESILIENTE
ANTIFRÁGIL
Frágil: quebra com o choque
Um programa frágil funciona apenas enquanto o ambiente respeita suas expectativas.
Exemplo:
COMPUTE WS-MEDIA =
WS-TOTAL / WS-QUANTIDADE.
Se WS-QUANTIDADE for zero, o programa poderá sofrer uma exceção.
O código pressupôs que sempre existiria pelo menos um item.
A entrada inesperada revelou a fragilidade.
Robusto: suporta o choque
Um sistema robusto possui força suficiente para permanecer praticamente inalterado.
Exemplo:
IF WS-QUANTIDADE NOT = ZERO
COMPUTE WS-MEDIA =
WS-TOTAL / WS-QUANTIDADE
ELSE
MOVE ZERO TO WS-MEDIA
END-IF.
Agora o programa não quebra com a divisão por zero.
Ele suporta a condição adversa.
Mas apenas suportar não significa aprender.
Resiliente: sofre, recupera-se e retorna
Um sistema resiliente pode falhar parcialmente, mas possui meios de retornar ao serviço.
No batch, isso pode envolver:
checkpoint;
restart;
arquivos de controle;
commits intermediários;
GDGs;
cópias de segurança;
steps reiniciáveis;
datasets temporários preservados;
lógica para evitar duplicidade.
Um job resiliente não precisa reprocessar 18 milhões de registros porque falhou no registro 18.000.001.
Ele sabe onde estava.
Ele consegue retomar.
Antifrágil: melhora depois do choque
O antifrágil vai além.
Depois do S0C7, a equipe não apenas corrige o registro.
Ela transforma o incidente em uma melhoria permanente:
cria validação de dados;
isola registros inválidos;
gera relatório de rejeitados;
adiciona métricas;
implementa checkpoint;
revisa outros programas com o mesmo padrão;
cria teste automatizado;
documenta a causa;
atualiza o runbook;
monitora a qualidade da origem.
O próximo dado inválido não encontra o mesmo sistema.
Ele encontra um sistema que aprendeu.
3. A batalha entre voltar e evoluir
Resiliência e antifragilidade são parentes, mas não são gêmeas.
A resiliência diz:
“Fui atingido, mas consegui voltar.”
A antifragilidade diz:
“Fui atingido, descobri onde era vulnerável e transformei a cicatriz em blindagem.”
Imagine um CICS que sofre indisponibilidade porque uma região AOR atingiu seu limite de tarefas.
Uma resposta resiliente poderia ser:
reiniciar a região;
redirecionar transações;
restaurar o serviço;
limpar filas;
normalizar o processamento.
Excelente. O ambiente voltou.
Mas uma resposta antifrágil investigaria:
por que o MXT foi atingido;
quais transações ficaram suspensas;
se houve contenção de recursos;
se o tempo de resposta cresceu antes da falha;
se alertas poderiam ter sido disparados;
se o CPSM poderia distribuir melhor a carga;
se determinada transação deveria possuir limite próprio;
se os dados SMF já indicavam a aproximação do problema.
A recuperação devolve o sistema ao estado anterior.
O aprendizado muda o estado futuro.
No campo de batalha digital, uma tropa que apenas substitui soldados sem mudar sua estratégia continuará caindo no mesmo lugar.
4. O Cisne Negro entrou no CPD
Às 03h02, enquanto Charlie analisava o dump, o telefone da operação tocou.
Um sistema externo enviara um arquivo três vezes maior do que o habitual. Ninguém havia sido avisado. A campanha promocional que gerara o volume fora criada por uma área de negócios sem comunicação com a equipe técnica.
O arquivo maior provocou:
aumento do tempo de leitura;
crescimento de arquivos temporários;
pressão sobre sort work;
atraso nos jobs dependentes;
acúmulo de mensagens;
ultrapassagem da janela batch.
Para a equipe de operações, aquele aumento parecia um Cisne Negro.
Um evento inesperado, de alto impacto, fora do radar daquelas pessoas.
Mas havia uma sutileza.
Para a área de marketing, o crescimento não era imprevisível. A campanha havia sido planejada.
Isso ensina algo importante:
Um Cisne Negro depende também da perspectiva do observador.
O evento pode ser inesperado para o CPD e perfeitamente conhecido por outra área.
Muitos supostos eventos imprevisíveis são, na realidade, falhas de comunicação, governança ou observabilidade.
Depois do problema, todos dizem:
— Era evidente que o volume aumentaria.
Essa é a racionalização posterior.
Depois que o cisne aparece, parece fácil explicar por que ele sempre esteve ali.
O erro de tentar prever tudo
Não existe ferramenta capaz de prever cada:
crise;
falha;
ataque;
alteração regulatória;
comportamento de cliente;
ruptura de fornecedor;
crescimento inesperado;
defeito escondido.
Portanto, a estratégia madura não consiste apenas em tentar adivinhar o próximo evento.
Consiste em construir um ambiente capaz de:
absorver impactos;
limitar danos;
manter serviços essenciais;
recuperar dados;
alterar prioridades;
aprender rapidamente;
explorar oportunidades surgidas durante a crise.
No mainframe, isso significa projetar para o inesperado, e não apenas para o cenário ideal.
5. VUCA: a selva onde o mainframe opera
O pelotão de Charlie atravessava um ambiente VUCA.
VUCA significa:
V – Volatility – Volatilidade
U – Uncertainty – Incerteza
C – Complexity – Complexidade
A – Ambiguity – Ambiguidade
Volatilidade: o volume muda sem pedir licença
Hoje o sistema processa um milhão de transações.
Amanhã, quinze milhões.
Um PIX coletivo, uma promoção, uma mudança de tarifa ou uma crise pode alterar o comportamento do processamento em minutos.
No mainframe, a volatilidade afeta:
CPU;
MSU;
memória;
buffers;
filas;
conexões;
datasets;
sort work;
janela batch;
consumo de serviço externo.
Como reagir
O programador iniciante deve aprender a não construir programas limitados apenas ao volume atual.
Algumas perguntas úteis:
O contador suporta o crescimento?
O campo PIC é grande o suficiente?
O total pode ultrapassar o limite?
O arquivo poderá ter milhões de registros?
O processamento pode ser dividido?
Existe gargalo em operações repetitivas?
O programa grava DISPLAY para cada registro?
Há commits demais ou de menos?
Considere:
01 WS-CONTADOR PIC 9(05).
Esse contador suporta até 99.999.
Talvez funcione hoje.
Mas, se o arquivo crescer para 100.000 registros, o contador poderá sofrer truncamento ou comportamento inadequado, dependendo do uso.
Uma definição mais prudente poderia ser:
01 WS-CONTADOR PIC 9(09) COMP-5 VALUE ZERO.
Não se trata de tornar tudo gigantesco. Trata-se de dimensionar com consciência.
Incerteza: não sabemos exatamente o que virá
O requisito ainda pode mudar.
A origem do dado pode alterar o layout.
Uma API pode ficar indisponível.
O negócio pode criar uma nova categoria.
O programa iniciante costuma tentar eliminar toda incerteza antes de começar.
O profissional experiente aceita que parte dela continuará existindo.
Por isso, ele cria:
validações;
parâmetros;
tabelas de configuração;
mensagens claras;
códigos de retorno;
interfaces versionadas;
tratamento de exceções;
pontos de observação.
Um programa cheio de valores fixos é uma armadilha.
IF WS-LIMITE > 5000
Por que 5000?
Quem definiu?
Quando mudará?
Seria melhor manter o valor em uma tabela, arquivo de parâmetros ou mecanismo de configuração apropriado.
A incerteza não desaparece. Mas o custo de adaptação pode ser reduzido.
Complexidade: tudo está ligado a tudo
Charlie pensava que estava investigando apenas um programa COBOL.
Logo descobriu que o job dependia de:
arquivo vindo de Linux;
transferência por Connect:Direct;
catálogo de datasets;
SMS;
DFSORT;
programa COBOL;
tabela Db2;
fila MQ;
transação CICS;
API consumida por mobile banking;
relatório enviado para outro sistema.
O S0C7 era apenas o primeiro cadáver encontrado na selva.
Sistemas mainframe raramente existem sozinhos.
A complexidade nasce das interações.
Um programa pode estar correto isoladamente e ainda provocar um incidente quando combinado com:
volume;
concorrência;
locks;
ordem de execução;
formato de dados;
timezone;
encoding;
dependências externas.
Dica de sobrevivência
Mapeie o fluxo:
Origem
↓
Transferência
↓
Validação
↓
Programa COBOL
↓
Db2 / VSAM
↓
MQ
↓
CICS
↓
API
↓
Usuário
Quando você enxerga apenas seu código, cada falha parece misteriosa.
Quando enxerga o sistema inteiro, as pistas começam a falar.
Ambiguidade: o requisito possui duas interpretações
O analista escreveu:
“Clientes com saldo superior a R$ 10.000 recebem tratamento especial.”
Charlie perguntou:
— Saldo atual, saldo médio ou saldo disponível?
Ninguém soube responder.
A ambiguidade surge quando a mesma frase permite múltiplas interpretações.
No COBOL, ambiguidade de negócio é mais perigosa do que ambiguidade sintática.
O compilador rejeita um comando malformado.
Mas aceita perfeitamente uma regra de negócio incorreta.
IF SALDO-CLIENTE > 10000
MOVE 'S' TO CLIENTE-ESPECIAL
END-IF.
O código compila.
O problema é que talvez ninguém saiba o que SALDO-CLIENTE realmente representa.
Como reduzir a ambiguidade
pergunte;
escreva exemplos;
defina casos-limite;
registre premissas;
confirme resultados esperados;
crie testes com valores próximos à fronteira.
Exemplo:
R$ 9.999,99 → Não especial
R$ 10.000,00 → Não especial
R$ 10.000,01 → Especial
Ou seria >= 10000?
Uma única condição pode alterar milhares de clientes.
6. BANI: quando a selva também entra na mente
Se VUCA descreve a natureza instável do ambiente, BANI ajuda a compreender como sistemas e pessoas reagem.
B – Brittle – Frágil
A – Anxious – Ansioso
N – Non-linear – Não linear
I – Incomprehensible – Incompreensível
Brittle: sólido por fora, quebradiço por dentro
O sistema de Charlie parecia confiável.
Executava havia 12 anos.
Mas dependia de:
um único especialista;
um layout não documentado;
espaço de disco calculado em 2018;
um programa sem testes automatizados;
uma PROC alterada manualmente;
um fornecedor externo sem acordo de volume.
Era um castelo pintado sobre vidro.
A fragilidade pode esconder-se atrás de anos de sucesso.
Quanto mais tempo um sistema funciona sem incidentes, maior pode ser a tentação de acreditar que ele é invulnerável.
Esse é o momento mais perigoso.
Anxious: todos recebem alarmes, ninguém sabe agir
Às 03h20, os grupos de mensagens explodiram.
URGENTE
CRÍTICO
PRIORIDADE MÁXIMA
PRECISAMOS DE POSIÇÃO
ALGUMA NOVIDADE?
A cada dois minutos alguém perguntava quando o problema seria resolvido.
A equipe precisava investigar, mas era interrompida por solicitações de atualização.
Isso é ansiedade operacional.
Um ambiente com alarmes demais produz cegueira.
Se tudo é crítico, nada é realmente priorizado.
A solução não é exigir que os profissionais “sejam mais fortes”.
É construir:
papéis claros;
canal único de comando;
periodicidade de atualização;
classificação de severidade;
runbooks;
observabilidade útil;
comunicação objetiva.
Em incidentes graves, uma pessoa deve investigar enquanto outra comunica.
Colocar o mesmo técnico para diagnosticar, corrigir, responder mensagens, participar de reunião e preencher planilha é transformar um problema técnico em colapso humano.
Non-linear: uma letra derrubou milhões de registros
O S0C7 nasceu de um caractere.
Uma única letra produziu impacto sobre milhões de transações.
Essa é a não linearidade:
Causa pequena
≠
Efeito pequeno
Outros exemplos:
um DDNAME incorreto impede um fechamento;
uma chave duplicada interrompe carga VSAM;
um lock esquecido bloqueia milhares de usuários;
um commit mal dimensionado degrada todo o Db2;
um DISPLAY dentro de loop lota o spool;
um campo aumentado quebra dezenas de programas;
uma condição
>em vez de>=altera resultados financeiros.
Em sistemas não lineares, pequenas mudanças exigem respeito.
Nunca diga:
“É só uma linha.”
Uma linha pode ser a porta de entrada de um exército inteiro.
Incomprehensible: o sistema funciona, mas ninguém sabe por quê
O programa possuía 27 mil linhas.
Algumas rotinas eram chamadas por GO TO.
Havia COPYBOOKs dentro de COPYBOOKs.
Campos chamados:
WS-AUX1
WS-AUX2
WS-FLAG-X
WS-CONTROLE
WS-AREA
Ninguém sabia exatamente por que determinado trecho existia.
Mas todos tinham medo de removê-lo.
Esse é o território do incompreensível.
Não significa que o sistema seja mágico.
Significa que seu conhecimento foi perdido, fragmentado ou escondido.
Como lutar contra isso
nomes significativos;
documentação próxima ao código;
testes;
mapas de chamadas;
análise de impacto;
comentários úteis;
redução de duplicidade;
revisão periódica;
transferência de conhecimento.
Evite comentários como:
* MOVE O VALOR PARA WS-VALOR
MOVE VALOR-ENTRADA TO WS-VALOR.
O comentário apenas repete o código.
Prefira explicar a razão:
* Preserva o valor original porque a rotina de cálculo
* converte o campo para centavos e altera seu conteúdo.
MOVE VALOR-ENTRADA TO WS-VALOR-ORIGINAL.
O código mostra o que acontece.
O comentário deve explicar por quê.
7. Transformando o programa em um sobrevivente
O Sargento Abend pediu a Charlie que corrigisse o programa, mas proibiu uma solução limitada ao registro defeituoso.
A missão era torná-lo melhor.
Passo 1 — Verificar o FILE STATUS
Todo arquivo deveria possuir um campo de status.
SELECT ARQ-ENTRADA
ASSIGN TO DDENTRA
ORGANIZATION IS SEQUENTIAL
FILE STATUS IS WS-FS-ENTRADA.
01 WS-FS-ENTRADA PIC XX VALUE SPACES.
Na abertura:
OPEN INPUT ARQ-ENTRADA
IF WS-FS-ENTRADA NOT = '00'
DISPLAY 'ERRO OPEN DDENTRA. FILE STATUS: '
WS-FS-ENTRADA
MOVE 12 TO RETURN-CODE
GOBACK
END-IF.
Nunca presuma que o arquivo abriu.
Pergunte ao sistema.
O FILE STATUS é a testemunha silenciosa de cada operação.
Passo 2 — Controlar corretamente o fim do arquivo
PERFORM LER-ENTRADA
PERFORM UNTIL WS-FIM-ARQUIVO = 'S'
PERFORM PROCESSAR-REGISTRO
PERFORM LER-ENTRADA
END-PERFORM.
LER-ENTRADA.
READ ARQ-ENTRADA
AT END
MOVE 'S' TO WS-FIM-ARQUIVO
NOT AT END
ADD 1 TO WS-LIDOS
END-READ
IF WS-FS-ENTRADA NOT = '00'
AND WS-FS-ENTRADA NOT = '10'
DISPLAY 'ERRO READ. FILE STATUS: '
WS-FS-ENTRADA
MOVE 12 TO RETURN-CODE
MOVE 'S' TO WS-FIM-ARQUIVO
END-IF.
O status 10 normalmente indica fim lógico de arquivo em processamento sequencial.
O programa não deve tratar EOF como desastre.
O fim do arquivo não é um inimigo. É o ponto de extração da patrulha.
Passo 3 — Validar antes de calcular
IF CAMPO-VALOR NUMERIC
MOVE CAMPO-VALOR TO WS-VALOR
ADD WS-VALOR TO WS-TOTAL
ADD 1 TO WS-PROCESSADOS
ELSE
ADD 1 TO WS-REJEITADOS
PERFORM GRAVAR-REJEITADO
END-IF.
A validação impede que um registro inválido derrube todo o pelotão.
Mas cuidado: NUMERIC precisa ser usado de acordo com a representação real do campo. Dados em formatos compactados, binários ou contendo sinal requerem entendimento do layout e do compilador.
Um bom programador não usa uma condição apenas porque ela parece correta.
Ele verifica como o dado está armazenado.
Passo 4 — Separar rejeição de falha estrutural
Nem todo erro de dado precisa encerrar o batch.
Podemos classificar:
Erro de registro
CPF inválido;
valor não numérico;
data impossível;
código desconhecido.
O programa pode rejeitar o registro e continuar, conforme a regra de negócio.
Erro estrutural
arquivo ausente;
LRECL incompatível;
falha de escrita;
tabela indisponível;
corrupção de dataset;
erro de autorização.
Esses casos podem exigir encerramento controlado.
O segredo é não tratar todos os problemas da mesma maneira.
Passo 5 — Criar resumo operacional
Ao terminar:
DISPLAY '--------------------------------'
DISPLAY 'RESUMO DO PROCESSAMENTO'
DISPLAY 'REGISTROS LIDOS : ' WS-LIDOS
DISPLAY 'REGISTROS PROCESSADOS : ' WS-PROCESSADOS
DISPLAY 'REGISTROS REJEITADOS : ' WS-REJEITADOS
DISPLAY '--------------------------------'
Isso melhora a observabilidade.
Entretanto, não faça DISPLAY de cada registro em produção sem necessidade. Milhões de mensagens podem inflar o spool, prejudicar performance e criar outro incidente.
A observabilidade deve iluminar.
Não incendiar a floresta.
8. Checkpoint e restart: ninguém deve atravessar a selva duas vezes
Reprocessar milhões de registros pode:
ultrapassar a janela;
duplicar atualizações;
consumir CPU;
gerar inconsistência;
atrasar sistemas dependentes.
Um mecanismo de checkpoint registra o progresso.
Pode armazenar:
número do último registro;
última chave;
posição lógica;
quantidade processada;
identificador do ciclo;
timestamp;
estado do processamento.
Exemplo conceitual:
JOB: PAYBATCH
CICLO: 20260729
ULTIMA-CHAVE: 000184725991
PROCESSADOS: 18000000
STATUS: EM-PROCESSAMENTO
Na retomada, o programa consulta o checkpoint e continua do ponto adequado.
Mas checkpoint exige cuidado.
O ponto salvo deve estar sincronizado com as atualizações realizadas.
Se o programa grava o checkpoint antes do commit, pode pular dados.
Se grava depois, pode reprocessar alguns registros.
Em Db2, a unidade de commit deve ser coerente com o registro de retomada.
Em VSAM e arquivos, talvez seja necessário usar arquivos de controle, marcações ou desenho específico de restart.
Resiliência não nasce de uma palavra.
Nasce de consistência entre:
Dados
Checkpoint
Commit
Saída
Estado
9. O perigo do herói único
Às 04h06, Charlie perguntou:
— Quem conhece a rotina de fechamento?
Responderam:
— O Nogueira.
— Onde ele está?
— Em férias, sem acesso ao celular.
A organização descobriu um ponto único de falha humano.
Sistemas robustos podem ser operados por equipes frágeis.
Isso ocorre quando:
só uma pessoa conhece a aplicação;
senhas dependem de um administrador;
o restart existe apenas na memória de alguém;
decisões não são documentadas;
não há substituição;
não existe treinamento cruzado.
A antifragilidade exige distribuir conhecimento.
Não significa que todos devem conhecer tudo.
Significa que nenhuma função crítica deveria depender exclusivamente da presença de uma pessoa.
O verdadeiro legado não é ser indispensável.
É construir algo que continue funcionando quando você não estiver na sala.
10. Pequenas falhas controladas evitam grandes derrotas
O pelotão decidiu criar exercícios periódicos.
Não esperaria a próxima madrugada crítica para descobrir se a recuperação funcionava.
Foram planejados testes de:
ausência de arquivo;
registro inválido;
dataset cheio;
duplicidade de chave;
timeout;
indisponibilidade de tabela;
falha após commit;
falha antes do checkpoint;
aumento de volume;
restart intermediário.
Essa prática se aproxima da engenharia do caos, desde que executada com limites e segurança.
O objetivo não é quebrar produção por diversão.
É criar perturbações controladas em ambientes adequados para descobrir fragilidades antes que o inimigo real as encontre.
Regra do estressor útil
Um estressor só fortalece quando:
o impacto é limitado;
existe observação;
ocorre aprendizado;
há tempo para recuperação;
ações corretivas são implementadas.
Falhar sem aprender não é antifragilidade.
É apenas desorganização.
11. Redundância: o que o corte de custos não enxerga
Um gerente pode olhar para dois caminhos de rede e perguntar:
— Por que pagamos por dois se usamos apenas um?
Pode olhar para dois especialistas e dizer:
— Por que duas pessoas conhecem o mesmo processo?
Pode olhar para capacidade ociosa e concluir:
— Estamos desperdiçando recursos.
Até o dia em que o caminho principal cai, o especialista adoece ou o volume dobra.
Redundância parece desperdício durante a normalidade.
Durante a crise, torna-se sobrevivência.
No mainframe, exemplos incluem:
múltiplas LPARs;
Parallel Sysplex;
caminhos redundantes;
replicação;
GDPS;
clusters MQ;
CICSplex;
cópias de segurança;
armazenamento espelhado;
profissionais treinados em mais de uma função.
Contudo, redundância precisa ser testada.
Um backup que nunca foi restaurado é apenas uma esperança armazenada.
Um site alternativo que nunca assumiu carga é apenas uma apresentação de PowerPoint.
Uma pessoa indicada como substituta, mas sem acesso nem treinamento, não é redundância.
É decoração organizacional.
12. O mainframe já é antifrágil?
Aqui existe uma curiosidade importante.
O IBM Z é reconhecido por recursos de disponibilidade, recuperação, particionamento, integridade e continuidade.
Mas isso não significa que qualquer aplicação executada nele seja automaticamente antifrágil.
Uma aplicação COBOL ruim continua ruim em um hardware excelente.
O mainframe pode oferecer:
isolamento;
logs;
segurança;
recuperação;
alta disponibilidade;
gerenciamento de workload;
consistência transacional.
Mas a aplicação ainda precisa utilizar esses recursos corretamente.
Um programa que ignora FILE STATUS, não verifica SQLCODE, não trata RESP do CICS e não possui restart pode transformar uma plataforma robusta em uma operação frágil.
A tecnologia oferece a fortaleza.
O código decide se a porta ficará aberta.
13. Easter egg: o soldado chamado RETURN-CODE
No fim de cada missão batch existe um pequeno mensageiro.
Ele se chama:
RETURN-CODE
Muitos iniciantes o tratam como detalhe.
Mas ele comunica ao JCL se a missão terminou com sucesso.
MOVE 0 TO RETURN-CODE.
MOVE 4 TO RETURN-CODE.
MOVE 8 TO RETURN-CODE.
MOVE 12 TO RETURN-CODE.
A interpretação exata depende dos padrões da organização, mas uma convenção comum é:
00 – Sucesso
04 – Alerta ou ocorrência não fatal
08 – Erro funcional
12 – Erro grave
16 – Falha crítica
O JCL pode decidir o próximo passo:
// IF (STEP01.RC = 0) THEN
//STEP02 EXEC PGM=PROXIMO
// ELSE
//ERRO EXEC PGM=TRATAERR
// ENDIF
Esse é o easter egg: o humilde RETURN-CODE é o rádio pelo qual o programa COBOL informa ao comandante do batch se a unidade pode avançar.
Sem essa comunicação, o JCL pode continuar executando steps sobre dados incompletos.
14. A diferença entre sobreviver e aprender
Às 05h31, o programa corrigido começou a rodar.
O registro inválido foi separado.
O processamento continuou.
O resumo operacional mostrou:
REGISTROS LIDOS : 24.813.407
REGISTROS PROCESSADOS : 24.813.406
REGISTROS REJEITADOS : 1
RETURN-CODE : 4
O job terminou.
Mas a missão ainda não.
Na manhã seguinte, a equipe realizou uma análise do incidente.
Não perguntou apenas:
— Quem colocou a letra no campo?
Perguntou:
Por que o dado inválido atravessou as validações anteriores?
Por que um registro derrubou o arquivo inteiro?
Por que não havia checkpoint?
Por que o aumento de volume não foi comunicado?
Por que os alertas não anteciparam o atraso?
Por que apenas uma pessoa conhecia o restart?
Que outros programas possuem o mesmo risco?
Essa mudança de perguntas separa uma cultura de culpa de uma cultura de aprendizado.
Encontrar um culpado pode encerrar uma reunião.
Encontrar a fragilidade pode evitar cem novos incidentes.
15. Manual de campo para o programador COBOL iniciante
Antes de considerar um programa pronto para atravessar a selva de produção, verifique:
Arquivos
todos possuem FILE STATUS;
OPEN, READ, WRITE, REWRITE e CLOSE são verificados;
EOF é tratado;
registros inválidos não provocam comportamento indefinido;
arquivos de saída possuem controle de criação;
layouts e LRECL estão documentados.
Dados
campos numéricos são validados;
tamanhos suportam crescimento razoável;
sinais e casas decimais estão corretos;
datas possuem validação;
valores-limite são testados;
conversões não provocam truncamento.
Processamento
loops possuem condição clara de término;
contadores não estouram;
divisões verificam zero;
erros são classificados;
mensagens permitem diagnosticar o problema;
dados sensíveis não aparecem no spool.
Recuperação
o job pode ser reiniciado;
o restart não duplica atualizações;
checkpoints são coerentes;
arquivos intermediários possuem política definida;
steps são idempotentes quando possível.
Idempotência significa que repetir uma operação produz o mesmo resultado final, sem duplicar efeitos indevidos.
Banco de dados
SQLCODE é verificado;
commits são dimensionados;
rollback é compreendido;
cursores são fechados;
deadlocks e timeouts possuem tratamento;
mensagens incluem contexto suficiente.
CICS
RESP ou condições são tratadas;
COMMAREA possui tamanho validado;
LINK e XCTL são usados conscientemente;
recursos são liberados;
ENQ possui DEQ correspondente;
transações longas são evitadas;
unidades de trabalho são bem definidas.
Operação
o programa define RETURN-CODE;
existe documentação de execução;
o runbook de falha é testado;
outra pessoa consegue operar;
métricas permitem observar tendência;
volume esperado e limite conhecido estão registrados.
16. A lição final do pelotão
O sol começava a aparecer atrás das paredes do datacenter quando Charlie saiu da sala.
Ele havia entrado naquela madrugada pensando que programar COBOL significava escrever comandos corretos.
Saiu entendendo que o verdadeiro trabalho era construir sistemas capazes de viver em um mundo que não respeita nossas expectativas.
Um programa não é antifrágil porque nunca falha.
Ele se aproxima da antifragilidade quando:
falhas pequenas revelam fraquezas;
o impacto é contido;
o serviço consegue voltar;
o incidente produz conhecimento;
o conhecimento altera código e processo;
a próxima perturbação encontra uma defesa melhor.
VUCA ensina que o ambiente é volátil, incerto, complexo e ambíguo.
BANI lembra que sistemas podem ser frágeis, pessoas podem estar ansiosas, efeitos podem ser não lineares e acontecimentos podem tornar-se incompreensíveis.
O Cisne Negro avisa que alguns eventos só parecerão óbvios depois que já tiverem acontecido.
A resiliência ensina a retornar.
A antifragilidade exige algo maior:
voltar diferente.
Charlie olhou pela última vez para o monitor.
O PAYBATCH estava com status OUTPUT.
Return code 4.
Um registro rejeitado.
Milhões processados.
Nenhuma duplicidade.
Nenhuma perda.
No spool, a última mensagem do programa dizia:
PROCESSAMENTO CONCLUÍDO COM ALERTA.
VERIFICAR ARQUIVO DE REJEITADOS.
O Sargento Abend apareceu atrás dele com uma xícara de café.
— Terminou?
Charlie respondeu:
— O job terminou. O aprendizado está apenas começando.
O veterano sorriu.
Porque essa era a verdade que todo profissional de mainframe descobre, cedo ou tarde:
O sistema frágil teme a madrugada.
O sistema robusto suporta a madrugada.
O sistema resiliente sobrevive à madrugada.
Mas o sistema antifrágil usa cada madrugada
para estar mais preparado quando a próxima chegar.
E, enquanto o resto da cidade acordava sem saber que estivera a poucos minutos de um fechamento atrasado, o pelotão z/OS recolhia seus dumps, atualizava seus runbooks e preparava a próxima versão.
Na guerra silenciosa do processamento corporativo, não havia medalhas.
Havia apenas o extrato correto pela manhã.
E, às vezes, isso precisava ser suficiente.
Sem comentários:
Enviar um comentário