☕ 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

sexta-feira, 7 de julho de 2023

Kojak Entra no CPD — O Caso do Db2 que Tinha um IMS Escondido no Porão

 


☕ Um Café no Bellacosa Mainframe

Kojak Entra no CPD — O Caso do Db2 que Tinha um IMS Escondido no Porão

Ou: como uma chave composta de 47 bytes entregou a árvore genealógica do sistema, por que uma tabela pode agir como arquivo e o que QSAM, VSAM, DL/I e Edgar Codd estavam fazendo na mesma cena do crime



Prólogo — Quem ama você, banco de dados?

Era uma tarde comum no CPD, o que significa que nada estava realmente comum.

O processamento batch havia terminado com RC=00, os operadores respiravam aliviados e um programador COBOL iniciante recebera uma manutenção considerada pequena: incluir uma nova forma de consultar lançamentos de conta. O pedido parecia inocente. Bastava localizar os lançamentos por documento, sem informar empresa, filial, cliente e contrato.

Ele abriu a tabela no Db2 e encontrou a primeira pista: uma chave composta tão longa que parecia a ficha criminal de metade de Nova York.

CD-EMPRESA
CD-FILIAL
NR-CLIENTE
NR-CONTRATO
TP-PRODUTO
NR-PARCELA
NR-SEQUENCIA

Para alcançar o lançamento, todos os programas percorriam a mesma rota. Primeiro encontravam o cliente. Depois a conta. Depois o contrato. Finalmente chegavam ao movimento. Havia SQL por toda parte, mas o cheiro era de DL/I.

Foi quando a porta do CPD se abriu. Entrou o detetive Kojak, sobretudo impecável, olhar desconfiado e pirulito no lugar onde outros investigadores carregariam um cachimbo.

Ele observou o diagrama de tabelas e fez a pergunta que ninguém queria ouvir:

“Se isto é relacional, por que todo mundo precisa entrar pela mesma porta?”

Silêncio.

O Db2 era moderno. O COBOL compilava. O catálogo estava disponível. Mas alguma coisa antiga vivia no porão. Não era exatamente um defeito de software. Era uma maneira de pensar.

O caso estava aberto.



1. A primeira testemunha: hierarquia não é crime

Kojak começou eliminando uma suspeita comum: a hierarquia.

Hierarquias existem naturalmente no mundo real:

  • uma empresa possui departamentos;

  • um departamento possui funcionários;

  • um pedido possui itens;

  • uma conta recebe lançamentos;

  • um país possui estados e municípios;

  • um produto pode conter componentes;

  • um gerente pode supervisionar outros funcionários.

Portanto, encontrar uma estrutura pai-filho dentro de um banco relacional não significa encontrar o culpado. O modelo relacional representa hierarquias sem dificuldade. Uma tabela pode referenciar a si mesma, como ocorre numa estrutura de funcionários e gerentes:

CREATE TABLE FUNCIONARIO (
    ID_FUNCIONARIO BIGINT NOT NULL,
    ID_GERENTE     BIGINT,
    NOME           VARCHAR(100) NOT NULL,
    PRIMARY KEY (ID_FUNCIONARIO),
    FOREIGN KEY (ID_GERENTE)
       REFERENCES FUNCIONARIO (ID_FUNCIONARIO)
);

O problema não é existir pai e filho. O problema é o filho somente poder ser encontrado depois que o programa percorre toda a linhagem familiar.

Num modelo hierárquico, a navegação faz parte essencial da estrutura. Imagine:

CLIENTE
  └── CONTA
       └── LANÇAMENTO

Para localizar determinado lançamento, tradicionalmente se encontra o cliente, dentro dele a conta e, dentro dela, o lançamento. É como um detetive que só pode chegar ao apartamento 32 entrando primeiro na delegacia, passando pelo arquivo central e pedindo autorização ao síndico.

No modelo relacional, o lançamento pode possuir identidade própria:

SELECT *
  FROM LANCAMENTO
 WHERE ID_LANCAMENTO = 987654;

Também pode ser encontrado pela conta:

SELECT *
  FROM LANCAMENTO
 WHERE ID_CONTA = 12345;

Ou associado ao cliente:

SELECT L.*
  FROM CLIENTE C
  JOIN CONTA A
    ON A.ID_CLIENTE = C.ID_CLIENTE
  JOIN LANCAMENTO L
    ON L.ID_CONTA = A.ID_CONTA
 WHERE C.ID_CLIENTE = 100;

A família continua existindo. O que desaparece é a obrigação de visitar o avô antes de perguntar pelo neto.

Kojak anotou no bloco:

Hierarquia: liberada por falta de provas. Prisão de caminho: permanece sob investigação.



2. IMS presta depoimento — a cidade construída com ruas predefinidas

O IMS não tentou esconder sua natureza. Ele trabalha com segmentos organizados hierarquicamente. Existe uma raiz e, abaixo dela, segmentos dependentes.

CLIENTE
├── ENDEREÇO
├── TELEFONE
└── CONTA
    └── LANÇAMENTO

Cada ocorrência de CONTA pertence a determinado CLIENTE. Cada LANÇAMENTO está subordinado a uma CONTA. Para navegar, a aplicação utiliza chamadas DL/I, entre elas:

  • GU — Get Unique;

  • GN — Get Next;

  • GNP — Get Next Within Parent;

  • ISRT — Insert;

  • REPL — Replace;

  • DLET — Delete.

Há uma diferença importante entre perguntar o que se deseja e informar como navegar. No IMS, o programa conhece a estrutura e percorre seus caminhos. O DBD descreve a organização do banco. PSBs e PCBs ajudam a definir as visões e os acessos permitidos às aplicações.

Isso não faz do IMS um criminoso antiquado. Seria uma conclusão preguiçosa. IMS é uma tecnologia madura, sofisticada e extremamente eficiente para grandes volumes transacionais e caminhos previsíveis. Índices secundários e logical relationships ampliam as possibilidades de acesso. Seu desempenho, estabilidade e integração com o ambiente transacional ajudaram a sustentar sistemas críticos durante décadas.

O detetive experiente não confunde idade com culpa.

O IMS funciona muito bem quando:

  • as relações pai-filho são naturais e estáveis;

  • os caminhos de navegação são conhecidos;

  • o volume transacional exige comportamento previsível;

  • a hierarquia representa fielmente o domínio;

  • as aplicações foram desenhadas para esse modelo.

As dificuldades aparecem quando surgem muitas relações muitos-para-muitos, quando consultas inesperadas precisam atravessar a árvore em novas direções ou quando uma mudança estrutural afeta muitos programas.

O IMS declarou:

“Eu nunca prometi ser relacional. Se encontraram minha árvore escondida dentro do Db2, interroguem quem fez a migração.”

Kojak concordou. O depoimento era consistente.



3. Db2 entra na sala — tabela não é apenas arquivo com gravata

No modelo relacional, a unidade lógica é a relação, normalmente representada como tabela. Cada tabela deveria expressar um tipo claro de fato.

Por exemplo:

CLIENTE
ID_CLIENTE | NOME | DATA_NASCIMENTO

Cada linha afirma:

Existe um cliente identificado por este código, com este nome e esta data de nascimento.

Outra tabela:

CONTA
ID_CONTA | ID_CLIENTE | DATA_ABERTURA | SITUACAO

Cada linha afirma:

Existe uma conta identificada por este código, relacionada a determinado cliente.

A relação não deveria depender apenas de um programa COBOL saber que CONTA.ID_CLIENTE combina com CLIENTE.ID_CLIENTE. Ela pode e, quando apropriado, deve ser declarada:

ALTER TABLE CONTA
  ADD CONSTRAINT FK_CONTA_CLIENTE
  FOREIGN KEY (ID_CLIENTE)
  REFERENCES CLIENTE (ID_CLIENTE);

Quando a regra existe apenas no programa, temos uma convenção. Quando está declarada como constraint, temos uma regra central protegida pelo SGBD.

Outra característica fundamental: o SQL é declarativo. Em geral, o programador informa o resultado desejado; o otimizador analisa estatísticas, índices, cardinalidades, custos e alternativas para escolher um caminho físico.

SELECT C.NOME,
       A.ID_CONTA,
       SUM(L.VALOR) AS TOTAL
  FROM CLIENTE C
  JOIN CONTA A
    ON A.ID_CLIENTE = C.ID_CLIENTE
  JOIN LANCAMENTO L
    ON L.ID_CONTA = A.ID_CONTA
 WHERE L.DATA_MOVIMENTO >= :WS-DATA-INICIAL
 GROUP BY C.NOME, A.ID_CONTA;

O programa formula a pergunta. O Db2 decide se utilizará determinado índice, qual tabela acessará primeiro e qual estratégia de join será mais adequada.

Essa separação entre visão lógica e implementação física é uma das grandes ideias do modelo relacional. O programa não deveria precisar memorizar cada corredor do depósito.


4. A impressão digital: a chave de 47 bytes

O primeiro indício concreto apareceu nas chaves.

CLIENTE
  CD_EMPRESA + CD_FILIAL + NR_CLIENTE

CONTA
  CD_EMPRESA + CD_FILIAL + NR_CLIENTE + NR_CONTA

LANCAMENTO
  CD_EMPRESA + CD_FILIAL + NR_CLIENTE + NR_CONTA
  + DATA_MOVIMENTO + SEQUENCIA

Chave composta não é ilegal. Às vezes, a identidade verdadeira de um fato é composta. O item de um pedido pode ser identificado pelo pedido e pelo número do item. Uma ocorrência de tabela associativa pode usar as chaves das duas entidades relacionadas.

A pista suspeita é outra: cada descendente carregar todos os códigos de seus ancestrais apenas para reproduzir o caminho antigo.

Uma alternativa seria:

CLIENTE
  ID_CLIENTE PK

CONTA
  ID_CONTA PK
  ID_CLIENTE FK

LANCAMENTO
  ID_LANCAMENTO PK
  ID_CONTA FK

Cada entidade possui identidade própria e relacionamentos explícitos. Alterar um vínculo não exige necessariamente redefinir a identidade inteira do registro.

Mas Kojak não aceitava soluções automáticas. Substituir todas as chaves naturais por números artificiais também pode esconder regras. A decisão correta exige perguntas:

  • A chave natural é realmente estável?

  • Pode mudar por correção, fusão empresarial ou legislação?

  • É grande demais para se propagar por todas as tabelas?

  • Expõe CPF, conta ou outra informação sensível?

  • Possui significado duradouro?

  • A chave técnica substituta será acompanhada de uma UNIQUE para proteger a regra do negócio?

Uma prática frequente é utilizar uma chave substituta como primary key e proteger a chave natural com unique constraint.

CREATE TABLE CLIENTE (
    ID_CLIENTE BIGINT       NOT NULL,
    CPF        CHAR(11),
    NOME       VARCHAR(100) NOT NULL,
    CONSTRAINT PK_CLIENTE
       PRIMARY KEY (ID_CLIENTE),
    CONSTRAINT UK_CLIENTE_CPF
       UNIQUE (CPF)
);

O número técnico fornece estabilidade. A constraint sobre CPF preserva a regra definida pelo negócio — considerando, naturalmente, estrangeiros, dados incompletos e demais exceções reais.


5. O crime do SELECT em série

Kojak encontrou outro padrão no fonte:

  1. selecionar um cliente;

  2. para esse cliente, selecionar suas contas;

  3. para cada conta, selecionar lançamentos;

  4. para cada lançamento, consultar sua descrição;

  5. repetir milhares de vezes.

Em espírito:

SELECT CLIENTE
  SELECT CONTA
    SELECT LANCAMENTO
      SELECT TIPO_LANCAMENTO

Era DL/I encenando uma peça de SQL.

Esse processamento linha a linha pode gerar enorme quantidade de chamadas e o conhecido problema de consultas repetitivas. O pensamento relacional procura operar sobre conjuntos:

SELECT C.ID_CLIENTE,
       A.ID_CONTA,
       T.DESCRICAO,
       SUM(L.VALOR) AS TOTAL
  FROM CLIENTE C
  JOIN CONTA A
    ON A.ID_CLIENTE = C.ID_CLIENTE
  JOIN LANCAMENTO L
    ON L.ID_CONTA = A.ID_CONTA
  JOIN TIPO_LANCAMENTO T
    ON T.ID_TIPO = L.ID_TIPO
 GROUP BY C.ID_CLIENTE,
          A.ID_CONTA,
          T.DESCRICAO;

Isso não significa escrever um SQL gigantesco, impossível de compreender e tratar. Significa identificar quando o banco pode resolver uma operação de conjunto melhor do que o COBOL percorrendo cada galho individualmente.

O desempenho deve ser medido. Um join bem modelado, com estatísticas e índices adequados, pode ser excelente. Um SQL mal escrito também pode ser desastroso. A teoria relacional não dispensa análise do access path, EXPLAIN, cardinalidade, distribuição e custo.

Como diria Kojak, gostar de SQL não fornece álibi para um SELECT * sem critério numa tabela de bilhões de linhas.


6. O cúmplice invisível: integridade mantida apenas pelo COBOL

Em vários sistemas, o programa verifica manualmente se o cliente existe antes de inserir a conta:

EXEC SQL
   SELECT COUNT(*)
     INTO :WS-COUNT
     FROM CLIENTE
    WHERE ID_CLIENTE = :WS-ID-CLIENTE
END-EXEC

IF WS-COUNT > 0
   EXEC SQL
      INSERT INTO CONTA (...)
      VALUES (...)
   END-EXEC
END-IF

O código parece cuidadoso, mas a regra pode estar duplicada em dezenas de programas. Além disso, existe uma janela de concorrência entre verificar e inserir.

A foreign key permite ao banco proteger a relação:

FOREIGN KEY (ID_CLIENTE)
REFERENCES CLIENTE (ID_CLIENTE)

O COBOL continua responsável por tratar SQLCODE, produzir mensagens adequadas e controlar a unidade de trabalho. O COMMIT continua sendo parte da história. A diferença é que a integridade não depende de todos os programas se lembrarem da mesma regra para sempre.

Naturalmente, há ambientes que evitam constraints por razões históricas, cargas em grande volume, replicação, desenho distribuído ou receio de custo. Algumas razões podem ser legítimas; outras apenas repetem crenças não medidas desde 1994.

A pergunta saudável é:

Se o banco não protege esta relação, quem protege, como protege e como provamos que funciona em todos os caminhos de atualização?

Se ninguém consegue responder, temos um suspeito sem vigilância.


7. QSAM — a testemunha que só anda para a frente

QSAM aparece diariamente no processamento batch do z/OS. É usado com datasets sequenciais para entradas, saídas, relatórios, arquivos de erro, cargas e intercâmbios.

READ ARQ-CLIENTES
   AT END
      SET FIM-ARQUIVO TO TRUE
END-READ

O significado dos bytes costuma estar num copybook:

01  REG-CLIENTE.
    05 REG-ID       PIC 9(09).
    05 REG-NOME     PIC X(40).
    05 REG-STATUS   PIC X(01).

QSAM é excelente para uma grande varredura sequencial. Se o objetivo é ler quarenta milhões de registros do começo ao fim, aplicar uma transformação e produzir uma saída, a simplicidade sequencial pode ser uma virtude.

Porém, QSAM não fornece por si só join, foreign key ou integridade referencial entre datasets. O sistema operacional não deduz que os bytes de determinada posição representam uma relação com outro arquivo. Essa semântica vive no copybook, nos programas e nos procedimentos.

Uma curiosidade importante: dataset é um conceito amplo no z/OS. QSAM é um método de acesso, não um banco de dados. Dizer “dataset versus QSAM” seria misturar o recipiente com uma das formas de acessá-lo.

Kojak interrogou o arquivo sequencial. Ele respondeu:

“Eu só leio do começo ao fim. Não fui eu quem prometeu relacionamento.”

Álibi aceito.


8. VSAM — a testemunha com índice e acesso direto

VSAM oferece diferentes organizações. Entre as mais conhecidas:

  • KSDS — registros organizados por chave, com acesso direto e sequencial;

  • ESDS — registros preservados em ordem de entrada, acessíveis também por endereço relativo;

  • RRDS — registros associados a números relativos;

  • LDS — espaço linear utilizado por componentes e casos específicos.

No COBOL, um KSDS pode ser acessado pela chave:

READ ARQ-CLIENTE
   KEY IS WS-ID-CLIENTE
   INVALID KEY
      CONTINUE
END-READ

O KSDS encontra registros rapidamente e pode suportar aplicações muito eficientes. Contudo, dois clusters com campos semelhantes não ganham automaticamente integridade referencial.

Se CONTA contém ID-CLIENTE, é a aplicação que normalmente impede uma conta órfã. Excluir o registro do cliente não dispara por natureza uma verificação relacional em todos os outros arquivos.

VSAM não é um Db2 incompleto. É outra ferramenta, com outro modelo operacional. Pode ser exatamente o que determinada solução necessita. O erro está em copiar um KSDS para uma tabela e acreditar que a presença de SQL realizou toda a modelagem.

Uma tabela usada somente por chave, sem constraints, com ordem física presumida e todas as regras no COBOL pode ser, conceitualmente, um KSDS mais caro usando crachá de banco relacional.


9. A comparação no mural da delegacia

TecnologiaEstrutura predominanteAcesso típicoRelacionamentosOnde vive a semântica
QSAMsequência de registrosleitura e gravação sequencialmantidos pela aplicaçãocopybook e programas
VSAM KSDSregistros indexados por chavechave e sequência de chavemantidos principalmente pela aplicaçãocluster, copybook e programas
IMSsegmentos hierárquicosnavegação DL/Ipai-filho estruturadoDBD, PSB/PCB e aplicação
Db2conjuntos de fatos relacionadosSQL declarativoPK, FK, valores e constraintscatálogo, modelo e aplicação

Nenhuma linha desta tabela declara um vencedor absoluto. O bom arquiteto escolhe conforme:

  • natureza dos dados;

  • padrão de acesso;

  • volume;

  • concorrência;

  • integridade necessária;

  • recuperação;

  • capacidade de mudança;

  • necessidade de consultas novas;

  • conhecimento e operação disponíveis.

Tecnologia não é concurso de beleza. É adequação ao caso.


10. Boa modelagem: a vítima precisa ser identificada

Kojak colocou uma tabela sob a luz e perguntou:

“Cada linha representa exatamente o quê?”

Essa é uma das melhores perguntas de modelagem.

Respostas claras:

  • um cliente;

  • uma conta;

  • um lançamento;

  • a participação de um aluno numa turma;

  • a titularidade de um cliente numa conta durante determinado período.

Resposta suspeita:

“É cliente, contrato, endereço atual, última cobrança e alguns campos reservados que dependem do tipo do registro.”

Provavelmente há vários conceitos misturados.

Uma boa tabela tem identidade clara, atributos coerentes e regras compreensíveis. Os nomes ajudam, mas não bastam. É preciso conhecer o significado, a granularidade e o ciclo de vida do fato.

O teste da dependência

Pergunte sobre cada atributo:

Este valor depende de quê?

Se o limite de crédito pertence à conta, não deve morar em CLIENTE apenas porque hoje existe uma conta por cliente. Se a taxa depende do produto e da vigência, talvez exija uma estrutura histórica própria.

Esse raciocínio conduz à normalização.


11. Normalização — separando suspeitos que estavam na mesma cela

Normalizar não significa fragmentar o banco até que uma consulta precise de 83 joins. Significa reduzir redundâncias e evitar anomalias.

Primeira forma normal

Evite listas escondidas em uma coluna:

TELEFONES = "11999999999;11888888888;11777777777"

Essa estrutura dificulta pesquisa, validação, indexação e alteração individual.

Também desconfie de:

TELEFONE_1
TELEFONE_2
TELEFONE_3

O quarto telefone já está a caminho da delegacia.

Uma tabela CLIENTE_TELEFONE permite representar zero, um ou muitos números, com tipo, preferência e validade.

Segunda forma normal

Se uma tabela possui chave composta, os atributos não-chave devem depender da chave inteira.

Em ITEM_PEDIDO, identificado por ID_PEDIDO + NR_ITEM, o nome do cliente depende do pedido, não do item completo. A descrição permanente do produto depende do produto, não da combinação pedido-item.

Terceira forma normal

Os atributos não-chave não deveriam depender de outros atributos não-chave.

Se CLIENTE contém ID_CIDADE, NOME_CIDADE e UF, e os dois últimos dependem de ID_CIDADE, talvez pertençam a uma tabela CIDADE.

Desnormalização consciente

Há casos legítimos de repetição: snapshots, relatórios históricos, data warehouses, integrações e otimizações comprovadas.

A diferença é simples:

  • redundância acidental cria várias versões da verdade;

  • redundância deliberada possui fonte oficial, momento de cópia e mecanismo de reconciliação.

Desnormalizar antes de medir é apresentar uma confissão antes mesmo de conhecer o crime.


12. Muitos-para-muitos: quando havia mais de dois suspeitos

Um cliente pode participar de várias contas. Uma conta pode ter vários titulares.

Um modelo frágil cria:

ID_CLIENTE_1
ID_CLIENTE_2
ID_CLIENTE_3

Além do limite arbitrário, cada consulta precisa tratar colunas diferentes.

O modelo relacional representa o relacionamento por meio de uma tabela associativa:

CLIENTE
  ID_CLIENTE

CONTA
  ID_CONTA

CONTA_TITULAR
  ID_CONTA
  ID_CLIENTE
  TIPO_TITULARIDADE
  DATA_INICIO
  DATA_FIM

CONTA_TITULAR não é uma gambiarra técnica. Ela representa um fato real:

Este cliente participa desta conta, neste papel e durante este período.

Se o relacionamento possui atributos próprios, ele merece ser tratado como conceito do negócio.


13. NULL, branco e zero: três suspeitos com rostos diferentes

Nos sistemas antigos, é comum encontrar campos nos quais branco, zero, noves e datas impossíveis representam estados especiais.

No banco relacional, NULL representa ausência de valor, mas a ausência precisa ter significado controlado. Ela não deveria significar ao mesmo tempo:

  • não informado;

  • não existe;

  • não se aplica;

  • ainda será calculado;

  • ocorreu erro;

  • veio vazio no arquivo legado.

Esses estados podem exigir uma coluna de situação ou motivo.

Também é perigoso criar defaults apenas para evitar NULL. Uma data 1900-01-01 pode parecer conveniente, mas obriga todas as consultas a conhecer o código secreto. O default deve representar um valor verdadeiro, não uma cortina para esconder desconhecimento.


14. O álibi temporal: como o dado estava ontem?

Muitos modelos funcionam bem até alguém perguntar:

“Qual era a situação da conta no fechamento do mês passado?”

Se cada atualização substitui a linha anterior, a história desaparece.

Para cada data, pergunte:

  • é data de ocorrência?

  • é data de processamento?

  • é início ou fim de vigência?

  • períodos podem se sobrepor?

  • alterações retroativas são permitidas?

  • quem alterou o dado e quando?

  • precisamos reconstruir o estado de uma data passada?

Tempo de negócio e tempo de sistema são conceitos diferentes. Um pagamento pode ocorrer numa sexta-feira, ser recebido no sábado e processado na segunda. Misturar essas datas produz investigações contábeis dignas de uma temporada inteira.


15. Passo a passo da investigação de um modelo

Passo 1 — Escreva as regras em português

Antes do CREATE TABLE, registre frases:

  • um cliente pode participar de várias contas;

  • uma conta pode possuir vários titulares;

  • uma conta pode existir sem lançamentos;

  • cada lançamento pertence a exatamente uma conta;

  • o cancelamento não apaga o lançamento original;

  • a titularidade possui início, fim e tipo.

Essas frases revelam entidades, cardinalidades, opcionalidade e tempo.

Passo 2 — Identifique entidades, eventos e classificações

  • entidades: cliente, conta, produto;

  • eventos: pagamento, transferência, lançamento;

  • classificações: tipo de conta, moeda, situação.

Evite uma tabela genérica que represente tudo por meio de um código de tipo e centenas de colunas opcionais.

Passo 3 — Defina cardinalidades

Pergunte se o relacionamento é obrigatório, opcional, único, múltiplo e temporal. Não deduza a cardinalidade apenas do layout antigo.

Passo 4 — Escolha as chaves

Analise estabilidade, tamanho, significado, privacidade e possibilidade de mudança. Diferencie identidade técnica de unicidade do negócio.

Passo 5 — Declare constraints

Use PRIMARY KEY, FOREIGN KEY, UNIQUE, NOT NULL e CHECK quando correspondem a regras verdadeiras.

Passo 6 — Teste o ciclo de vida

Simule cadastro, correção, cancelamento, reativação, transferência, evento retroativo, auditoria, anonimização e consulta histórica.

Passo 7 — Escreva consultas reais

Valide se o modelo responde às perguntas essenciais do negócio sem depender de códigos secretos e sequências implícitas.

Passo 8 — Projete o físico

Depois do modelo lógico, trate índices, particionamento, clustering, compressão, tablespaces, estatísticas, concorrência, recuperação, retenção e padrões batch.

Um índice encontra rapidamente o dado. Não consegue decidir se o dado deveria estar ali.


16. Cuidado ao prender o culpado: constraints numa base histórica

Ao modernizar um sistema, alguém pode decidir criar todas as foreign keys numa sexta-feira à tarde. Péssimo horário para heroísmo.

Antes de ativar constraints, investigue:

  1. quantos registros órfãos existem;

  2. quais programas atualizam cada tabela;

  3. quais cargas dependem de ordem especial;

  4. como funcionam deleções e cancelamentos;

  5. quais dados chegam atrasados;

  6. como será feita a correção;

  7. qual é o plano de rollback;

  8. qual impacto existe em disponibilidade e desempenho.

Se a foreign key encontrar milhões de órfãos, ela não criou o crime. Apenas acendeu a luz da sala de evidências.

Uma modernização segura pode usar views, serviços, reconciliações, constraints inicialmente informativas quando disponíveis e adequadas, correção gradual dos dados e migração por domínios.


17. Checklist de Kojak para descobrir um IMS usando SQL

Pegue uma tabela e responda:

  1. Cada linha representa exatamente o quê?

  2. Qual regra torna a linha única?

  3. A chave representa identidade ou o caminho até a raiz?

  4. Quais foreign keys existem e quais deveriam existir?

  5. Há registros órfãos?

  6. Existem listas dentro de colunas?

  7. Existem campos numerados como TELEFONE_1, TELEFONE_2 e TELEFONE_3?

  8. O mesmo fato aparece em várias tabelas?

  9. Qual tabela é a fonte oficial?

  10. Algum programa depende de ordem sem ORDER BY?

  11. Existem SELECTs aninhados que imitam pai-filho-neto?

  12. As regras estão no banco ou espalhadas por COBOL, Java, ETL e planilhas?

  13. É possível reconstruir o passado?

  14. Branco, zero, noves e NULL têm significados documentados?

  15. Alterar um relacionamento muda a identidade do registro?

  16. Uma nova consulta exige começar sempre pela mesma tabela raiz?

  17. O desenho nasceu do negócio ou foi copiado de um arquivo?

Quanto mais respostas desconfortáveis, maior a chance de existir um modelo navegacional escondido sob a camada SQL.


Epílogo — Caso encerrado, pirulito devolvido

Kojak reuniu todos no CPD.

QSAM não era culpado. Fazia muito bem seu trabalho sequencial e nunca prometera relacionamentos.

VSAM também possuía um álibi. Sabia localizar registros por chave, mas não alegava conhecer automaticamente as relações de negócio entre clusters.

IMS admitia sua hierarquia desde o primeiro interrogatório. Seus caminhos eram parte do projeto e podiam oferecer enorme desempenho quando combinavam com o problema.

Db2, por sua vez, oferecia tabelas, constraints, SQL declarativo, otimização e operações de conjunto. Mas nenhuma versão moderna do produto poderia impedir uma equipe de reproduzir dentro dele a mentalidade de arquivos e segmentos.

O culpado não era uma tecnologia. Era a migração sem remodelagem, acompanhada pela crença de que mudar READ para SELECT transformaria automaticamente registros em relações.

Uma boa modelagem relacional apresenta:

  • conceitos com fronteiras claras;

  • linhas com identidade inequívoca;

  • atributos dependentes do fato correto;

  • relacionamentos declarados;

  • cardinalidades fiéis ao negócio;

  • regras protegidas perto dos dados;

  • tempo e ausência com significado;

  • redundância consciente, quando necessária;

  • liberdade para consultar por diferentes perspectivas;

  • separação entre a pergunta lógica e o caminho físico.

O programador COBOL olhou novamente para a chave de 47 bytes. Pela primeira vez, não viu apenas campos concatenados. Viu uma árvore genealógica, uma rota de navegação e décadas de decisões arquitetônicas preservadas como impressões digitais.

Kojak colocou o pirulito na boca, caminhou em direção à saída e deixou sua última observação:

“Uma tabela pode morar no Db2 e ainda pensar como arquivo. Quem ama você, banco de dados? Porque seus programas claramente amam o caminho mais longo.”

Naquela noite, ninguém reescreveu o sistema inteiro. Em vez disso, a equipe documentou as regras, mediu os órfãos, identificou as fontes oficiais e começou a melhorar o próximo domínio.

Era menos cinematográfico do que uma prisão.

Mas, em arquitetura de dados, evitar o próximo crime costuma valer mais do que posar ao lado do culpado.



quinta-feira, 6 de julho de 2023

Goblin Slayer — Parte VII : As Referências Escondidas de Goblin Slayer Quando um Programador COBOL Descobre que Kumo Kagyu Não Escreveu Apenas uma História...

 

Bellacosa Mainframe apresenta Goblin Slayer parte vii

☕ Um Café no Bellacosa Mainframe

Goblin Slayer — Parte VII  : As Referências Escondidas de Goblin Slayer

Quando um Programador COBOL Descobre que Kumo Kagyu Não Escreveu Apenas uma História... Ele Escondeu Décadas de RPG, Literatura Fantástica e Cultura Pop Entre as Linhas

"Todo grande sistema possui comentários escondidos no código. Toda grande obra possui referências escondidas no roteiro."


Introdução — Nada em Goblin Slayer Está Ali por Acaso

Uma pessoa assiste Goblin Slayer pela primeira vez.

Ela vê um guerreiro de armadura.

Alguns goblins.

Uma guilda.

Missões.

Magia.

Fim.

Já um veterano de RPG olha para a mesma cena e começa a sorrir.

Porque percebe dezenas de referências.

Kumo Kagyu pertence à geração que cresceu jogando RPG de mesa durante as décadas de 1980 e 1990.

Ele leu fantasia clássica.

Consumiu jogos.

Leu mangás.

Assistiu filmes.

Participou de campanhas que duravam meses.

Goblin Slayer é praticamente uma carta de amor para toda essa cultura.

Quanto mais conhecimento o leitor possui...

Mais referências encontra.


O maior Easter Egg

Talvez o maior segredo da obra seja justamente aquele que quase ninguém percebe.

Nenhum personagem principal possui nome próprio.

Temos:

  • Goblin Slayer

  • Priestess

  • High Elf Archer

  • Dwarf Shaman

  • Lizard Priest

  • Cow Girl

  • Guild Girl

Isso parece estranho apenas para quem nunca jogou RPG.

Nas primeiras campanhas de Dungeons & Dragons era extremamente comum os jogadores lembrarem dos personagens pela classe.

"Meu Clérigo."

"O Anão."

"A Elfa."

"O Guerreiro."

Kumo Kagyu transformou essa tradição em identidade narrativa.


Dungeons & Dragons está por toda parte

É impossível compreender Goblin Slayer sem conhecer Dungeons & Dragons.

As referências aparecem constantemente.

As classes.

Os níveis.

As guildas.

As tavernas.

As missões.

Os monstros.

Os tesouros.

Até a forma como as aventuras começam lembra campanhas clássicas dos anos 1980.


O Mestre nunca aparece

Outro detalhe brilhante.

Quem joga RPG percebe imediatamente.

Existe uma força invisível conduzindo os acontecimentos.

Os aventureiros recebem missões.

Rolam acontecimentos improváveis.

Encontros aleatórios.

Eventos inesperados.

É quase como se um Mestre de Jogo estivesse conduzindo tudo.

Kumo Kagyu nunca diz isso explicitamente.

Mas toda a estrutura narrativa funciona como uma campanha de mesa.


Os Deuses jogam dados

Uma das referências mais inteligentes da série.

Diversas vezes é mencionado que os deuses jogam dados para decidir acontecimentos.

Esse conceito representa exatamente o funcionamento de um RPG de mesa.

No RPG, os dados determinam:

  • sucesso

  • fracasso

  • dano

  • encontros

  • sorte

Na obra, os deuses assumem simbolicamente esse papel.

Goblin Slayer, porém, tenta vencer mesmo quando os "dados" parecem desfavoráveis.


Sword World RPG

Embora D&D seja a influência mais famosa, muitos elementos lembram fortemente Sword World RPG, um sistema japonês criado em 1989 e extremamente popular no Japão.

Algumas semelhanças incluem:

  • guildas de aventureiros;

  • missões graduadas;

  • grupos equilibrados por classes;

  • cidades que funcionam como centros de recrutamento;

  • progressão por experiência.

Isso torna Goblin Slayer uma obra profundamente japonesa em sua estrutura, mesmo quando utiliza uma estética medieval inspirada no Ocidente.


A sombra de Conan

Poucos leitores percebem.

Mas Conan está presente o tempo inteiro.

Não porque Goblin Slayer seja musculoso.

Muito menos porque usa espada.

A influência está na filosofia.

Conan sobrevivia porque:

  • observava;

  • desconfiava;

  • adaptava-se;

  • improvisava.

Goblin Slayer faz exatamente isso.

Ambos vencem pela experiência.

Não por poderes mágicos.


Berserk aparece nas entrelinhas

Outra influência frequentemente apontada pelos fãs é Berserk.

Existem paralelos claros:

  • atmosfera sombria;

  • violência sem glamour;

  • protagonistas marcados pelo trauma;

  • humanidade enfrentando um mundo hostil.

Ao mesmo tempo, Goblin Slayer segue um caminho próprio. Enquanto Berserk trata de um conflito épico entre destino, poder e humanidade, Goblin Slayer concentra seu foco em missões locais, rotina e sobrevivência cotidiana.


O Senhor dos Anéis

As raças clássicas aparecem.

Elfos.

Anões.

Homens.

Lagartos humanoides.

Mas Kumo Kagyu faz pequenas mudanças.

Os elfos são menos idealizados.

Os anões possuem humor peculiar.

As relações entre espécies parecem mais próximas das mesas de RPG do que da alta fantasia de Tolkien.

É uma homenagem sem ser uma cópia.


O Hobbit escondido

Existe outra curiosidade.

Bilbo era pequeno.

Subestimado.

Vencia usando inteligência.

Goblin Slayer também.

Ele nunca derrota monstros porque é mais forte.

Derrota porque pensa diferente.


O Labirinto como personagem

As cavernas não servem apenas como cenário.

São quase personagens.

Essa ideia vem diretamente da tradição dos dungeon crawlers.

Nos RPGs antigos:

a masmorra era o verdadeiro inimigo.

Goblin Slayer preserva exatamente essa filosofia.


As armadilhas

Outro grande Easter Egg.

Quase toda aventura clássica de RPG possuía:

  • armadilhas;

  • corredores estreitos;

  • portas secretas;

  • túneis;

  • emboscadas.

Goblin Slayer usa todos esses elementos.

Não por coincidência.

Mas por tradição.


O capacete

O capacete tornou-se um dos maiores símbolos da franquia.

Existem inúmeras interpretações.

Uma delas diz que Kumo Kagyu queria impedir que o leitor julgasse Goblin Slayer por sua aparência.

Sem rosto.

Sem expressão.

Sem emoções visíveis.

Toda sua personalidade é construída pelas ações.

É exatamente o oposto da maioria dos protagonistas modernos.


A armadura comum

Outra referência interessante.

Heróis normalmente usam armaduras lendárias.

Goblin Slayer usa equipamento simples.

Por quê?

Porque armaduras comuns podem ser substituídas.

Consertadas.

Trocadas.

É uma filosofia extremamente prática.

Quase militar.


O escudo pequeno

Em praticamente toda fantasia medieval...

Escudos enormes representam força.

Goblin Slayer prefere escudos pequenos.

Porque precisa mover-se dentro de cavernas.

É um detalhe que mostra quanto Kumo Kagyu pensou na funcionalidade do equipamento.


O fogo

Sempre que possível...

Goblin Slayer utiliza fogo.

Óleo.

Explosões.

Fumaça.

Isso lembra muito campanhas antigas de RPG.

Jogadores experientes aprendem rapidamente que monstros raramente esperam soluções "não convencionais".


A água

Outro detalhe fantástico.

Goblin Slayer frequentemente utiliza rios.

Inundações.

Poços.

Correntes.

O terreno torna-se arma.

Essa forma de pensar aparece em inúmeros manuais militares e também em campanhas de RPG de mesa.


A Guilda

A Guilda de Aventureiros é muito mais do que um quadro de missões.

Ela lembra as antigas guildas mercantis da Idade Média, mas também reproduz o funcionamento das guildas presentes em inúmeros sistemas de RPG japoneses.

Ela classifica aventureiros.

Organiza recompensas.

Distribui contratos.

Controla reputações.

É praticamente uma agência reguladora da profissão.


As missões de baixo nível

Outro detalhe genial.

Em muitos RPGs...

Jogadores ignoram missões simples.

Querem enfrentar dragões.

Demônios.

Necromantes.

Goblin Slayer faz exatamente o contrário.

Sua vida inteira é construída sobre missões consideradas "sem importância".

É quase uma crítica bem-humorada ao comportamento de muitos jogadores.


O verdadeiro protagonista

Existe uma teoria interessante entre fãs.

Goblin Slayer não seria o herói escolhido.

A verdadeira Hero é outra personagem da história, responsável por enfrentar ameaças de escala mundial.

Enquanto ela lida com reis demônios e crises épicas, Goblin Slayer permanece resolvendo problemas locais que poderiam crescer silenciosamente.

Essa dualidade reforça a ideia de que mundos de fantasia precisam tanto dos grandes heróis quanto daqueles que impedem pequenas ameaças de se tornarem catástrofes.


O mundo continua vivendo

Outro Easter Egg extremamente elegante.

A história não gira ao redor do protagonista.

Outros aventureiros continuam realizando missões.

Outras guerras acontecem.

Outros heróis salvam o mundo.

Goblin Slayer representa apenas uma pequena parte daquele universo.

Isso faz o cenário parecer vivo.


A referência invisível aos Programadores COBOL

Talvez esta seja a analogia perfeita para o Bellacosa Mainframe.

Todo mundo conhece quem criou o aplicativo do banco.

Pouca gente conhece quem mantém o sistema que liquida milhões de transações diariamente.

Da mesma forma, todos celebram o herói que derrota o Rei Demônio.

Poucos lembram daquele aventureiro que passou anos impedindo que aldeias inteiras fossem destruídas antes mesmo de o perigo ganhar proporções épicas.

Goblin Slayer é o sysprog do universo de fantasia.

Seu trabalho é invisível.

Seu sucesso quase nunca aparece nos livros de história.

Mas, se ele deixar de existir, toda a infraestrutura começa a ruir.


Conclusão — O Código-Fonte Invisível da Fantasia

Quanto mais estudamos Goblin Slayer, mais percebemos que sua riqueza não está apenas na narrativa.

Ela está nas camadas escondidas.

Kumo Kagyu reuniu influências de RPG de mesa, literatura fantástica, fantasia clássica, jogos japoneses e estratégias militares para construir um universo que recompensa a atenção aos detalhes.

É exatamente como abrir um antigo sistema COBOL desenvolvido por um arquiteto experiente.

À primeira vista vemos apenas linhas de código.

Depois descobrimos comentários inteligentes.

Rotinas reutilizadas.

Decisões de projeto.

Padrões elegantes.

Pequenos detalhes que revelam décadas de experiência.

Goblin Slayer funciona da mesma maneira.

Na primeira leitura encontramos apenas uma aventura sombria.

Na segunda percebemos um mundo coerente.

Na terceira começamos a enxergar todas as homenagens silenciosas que Kumo Kagyu espalhou pela obra.

E talvez esse seja o maior Easter Egg de todos.

A verdadeira recompensa nunca esteve escondida em um baú dentro de uma masmorra.

Ela sempre esteve escondida entre as linhas da própria história.

Um Café no Bellacosa Mainframe

ARQUIVOS DA GUILDA • CLASSIFICAÇÃO: DARK FANTASY

Goblin Slayer sem Mistérios

O Guia Definitivo da Série Completa

Uma jornada por cronologia, psicologia, biologia, estratégia, engenharia militar, referências culturais, simbolismos e os segredos escondidos de Goblin Slayer.

“Quando um Programador COBOL Descobre que Grandes Obras Também Precisam de um Mapa para Não se Perder na Dungeon.”
Explorar a série
RELATÓRIO DE MISSÃO

Uma série construída como uma campanha de RPG

Goblin Slayer sem Mistérios é uma coleção especial do Bellacosa Mainframe dedicada à análise profunda da obra criada por Kumo Kagyu. Cada capítulo investiga uma camada diferente da franquia, relacionando fantasia sombria, RPG de mesa, estratégia, trauma, sobrevivência, engenharia militar e arquitetura de sistemas.

A coleção foi organizada em ordem cronológica para facilitar a leitura. Você pode começar pela Parte I, seguir capítulo após capítulo ou utilizar os filtros para selecionar assuntos como psicologia, goblins, táticas, história da franquia e cultura otaku.

Todos os títulos abaixo são links HTML reais e permanecem acessíveis mesmo quando o JavaScript estiver desativado. Isso facilita a navegação dos leitores e a descoberta das páginas por mecanismos de busca.

Progresso da campanha 0 de 14 missões visitadas
14 capítulos encontrados
I
Introdução

Goblin Slayer sem Mistérios — Parte I

O ponto de entrada da campanha. Uma análise sobre o herói invisível que não salva o mundo em uma única batalha, mas impede silenciosamente que ele desmorone todos os dias.

Heroísmo Disciplina Mainframe
II
Disciplina

Goblin Slayer sem Mistérios — Parte II

O verdadeiro poder não está na espada, mas na constância de levantar, preparar os equipamentos e executar diariamente o trabalho que quase ninguém deseja assumir.

Rotina Dever Persistência
III
Missão crítica

Goblin Slayer sem Mistérios — Parte III

Nem todo herói enfrenta o Rei Demônio. Alguns garantem que na segunda-feira existirão sistema, salários, luz e uma aldeia inteira ainda de pé.

Disponibilidade Proteção Responsabilidade
IV
Arquitetura

Parte IV — O Arquiteto Invisível de Goblin Slayer

Uma reflexão sobre profissionais que projetam soluções, previnem desastres e permanecem atrás do terminal enquanto o restante do mundo apenas percebe que tudo continua funcionando.

Arquitetura COBOL Prevenção
V
Cronologia

Parte V — A Evolução Cronológica Completa da Franquia

Da publicação original às light novels, mangás, adaptações, spin-offs, filme e temporadas do anime: a evolução de uma história que cresceu release após release.

Web Novel Light Novel Anime
VI
Biologia

Parte VI — A Biologia dos Goblins

Anatomia, comportamento, adaptação, hierarquia e ecologia dos goblins analisados como uma espécie invasora capaz de explorar brechas e evoluir rapidamente.

Ecologia Adaptação Worldbuilding
VII
Referências

Parte VII — As Referências Escondidas de Goblin Slayer

Conan, Berserk, Tolkien, Dungeons & Dragons, Sword World RPG, literatura fantástica, mitologia e cultura pop escondidos entre as linhas da obra de Kumo Kagyu.

RPG Literatura Cultura pop
VIII
Psicologia

Parte VIII — A Psicologia Profunda de Goblin Slayer

Trauma, hipervigilância, isolamento, necessidade de controle, resiliência e reconstrução emocional por meio das relações que lentamente devolvem humanidade ao protagonista.

Trauma Memória Resiliência
IX
Engenharia militar

Parte IX — A Engenharia Militar de Goblin Slayer

Reconhecimento, suprimentos, redundância, controle do terreno, fortificação, retirada e arquitetura operacional transformam batalhas perigosas em vitórias planejadas.

Logística Terreno Contingência
X
Estratégia

Parte X — A Estratégia de Goblin Slayer

Uma análise sobre informação, iniciativa, especialização, probabilidades, redundância e a capacidade de pensar diversos movimentos à frente do adversário.

Planejamento Inteligência Antecipação
XI
100 segredos

Parte XI — Os 100 Segredos de Goblin Slayer

Cem detalhes sobre personagens, mundo, goblins, equipamentos, narrativa, simbolismos, RPG, produção, psicologia e estratégia que podem passar despercebidos até pelos fãs.

Easter eggs Simbolismos Curiosidades
XII
Guia completo

Parte XII — Goblin Slayer sem Mistérios

O mapa da campanha: introdução, sequência recomendada, resumo dos capítulos e orientação para explorar todas as camadas da coleção sem se perder na dungeon.

Índice Mapa Ordem de leitura
FINAL
Síntese definitiva

Por Que Goblin Slayer É uma das Melhores Obras de Dark Fantasy

A conclusão da jornada, reunindo cronologia, psicologia, estratégia, engenharia militar, simbolismos, referências culturais, construção de mundo e impacto na cultura otaku.

Dark Fantasy Síntese Conclusão
BÔNUS
Dossiê militar

A Composição do Exército Goblin em The Fate of an Adventurer

Rei Goblin, estado-maior, Champions, Shamans, arqueiros, infantaria, Riders, logística e cadeia de comando analisados como componentes de uma força militar organizada.

Exército Goblin Hierarquia Ordem de batalha
ROTA RECOMENDADA

Como percorrer esta dungeon

Comece pelas três primeiras partes para compreender a proposta da série. Depois visite o Arquiteto Invisível, conheça a evolução da franquia e aprofunde-se em biologia, referências, psicologia, engenharia militar e estratégia.

  1. 01 Fundamentos do herói invisível
  2. 02 História e evolução da franquia
  3. 03 Biologia e organização dos goblins
  4. 04 Psicologia e simbolismos
  5. 05 Engenharia militar e estratégia
  6. 06 Segredos, guia completo e síntese final
Bellacosa Mainframe Dark Fantasy • Anime • RPG • COBOL • Estratégia

“A vitória não é improviso. É arquitetura.”

quarta-feira, 5 de julho de 2023

💔 O Enjoo do Amor — quando o desejo perde a curiosidade

 


💔 O Enjoo do Amor — quando o desejo perde a curiosidade

(Por Vagner Bellacosa – Bellacosa Mainframe)

Ninguém avisa quando o amor começa a desbotar.
Ele não morre com brigas ou traições espetaculares — morre devagar, nas entrelinhas do cotidiano.
Um dia, aquilo que era risada vira silêncio; o toque, costume; o olhar, distração.
E o que antes era fogo vira cinza morna.

Chamam de “enjoo”, mas é mais profundo que isso.
É a morte da curiosidade.
Quando o outro deixa de ser um mistério a ser descoberto e vira apenas uma presença previsível.
Quando a alma se acostuma demais, o corpo deixa de responder.

No começo, tudo é descoberta.
A voz encanta, o cheiro prende, o gesto fascina.
A dopamina faz festa no cérebro, e a gente acredita que encontrou algo raro, eterno.
Mas o amor é químico e também cotidiano — e a rotina cobra manutenção.
Quando a admiração se apaga, o desejo também recolhe suas malas e vai embora sem aviso.

O “enjoo” chega quando a admiração se perde.
Quando o encanto vira irritação, quando a leveza vira obrigação.
É quando a convivência cansa, não pelo tempo, mas pela falta de frescor.
O mesmo beijo que antes acelerava o pulso agora é apenas gesto automático — uma saudação protocolar entre dois sobreviventes de um amor que já foi.

E então surge o mais cruel dos sentimentos: a indiferença.
Não há mais raiva, nem ciúme, nem saudade.
Há apenas o vazio confortável de quem não sente nada.
O outro passa a ser parte do cenário — presença que não ilumina, ausência que não dói.

Mas nem sempre é culpa de alguém.
Às vezes o “enjoo” é apenas o sinal de que um cresceu e o outro não.
De que um ainda busca horizontes, enquanto o outro se contenta com a sombra.
O amor, quando não se reinventa, se repete — e o repetido, cedo ou tarde, cansa.

No fundo, o desejo não morre — ele muda de endereço.
Vai morar onde ainda há espanto, curiosidade, admiração.
Porque amar, de verdade, é continuar querendo descobrir o outro, mesmo depois de saber tudo.

O “enjoo do amor” é o ponto em que o encanto pede renovação e o coração decide se fica por ternura ou parte por instinto.
E às vezes, partir é apenas reconhecer que o amor foi bonito — mas já foi.


🕯️ Bellacosa Mainframe Chronicles — Reflexões sobre o humano, o tempo e o que se apaga devagar.


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