Translate

Mostrar mensagens com a etiqueta Estruturas de Dados. Mostrar todas as mensagens
Mostrar mensagens com a etiqueta Estruturas de Dados. Mostrar todas as mensagens

segunda-feira, 11 de agosto de 2025

Programa COBOL usando ponteiro de memória

 

Bellacosa Mainframe e programas cobol usando ponteiros de memoria

Programa COBOL usando ponteiro de memória

4,424 followers

Salve jovem padawan, nesta inspirada sexta-feira resolvi explorar um tema um pouco mais complexo.

Em minhas aulas sinto uma certa dificuldade em apresentar o tema, às vezes, a explicação acaba confundindo ainda mais. Por isso nada melhor que colocarmos a mão na massa, digo no teclado.

Relebrando conceitos

SET - O comando SET designa um valor para uma referência COBOL.

ADDRESS - Método simples de obter capacidade de endereçamento para áreas de dados de memoria definidas na LINKAGE SECTION usando variáveis de ponteiro e o registro especial ADDRESS

Programa COBOL120.

O programa COBOL120 é bem interessante, no DATA DIVISION teremos duas áreas de memórias distintas:


  1. Working Storage Section
  2. Linkage Section


As variáveis na Working são do gênero Grupo com 4 variáveis do tipo string e inicializadas com valores. Um ponteiro de memória e um índice contador.

Na Linkage temos uma Tabela interna com string de 4 bytes e com 4 ocorrências.

Processamento

O código é simples, contem alguns displays, dois laço Perform Varying e comandos SET e Address of, para capturar o endereço da memória e alocar na nova variáveis. Ao final faço novo display mostrando a tabela inicializada sem MOVE/ACCEPT/REDEFINES.

 *****************************************************************
      * DATA     : 06/09/2024
      * AUTOR    : VAGNER RENATO BELLACOSA
      * OBJETIVO : PROGRAMA EXEMPLO ARQUIVO QSAM LOOP
      * USO DE ENDERECO DE MEMORIA E TABELA INTERNA
      * USO DE ALOCACAO DINAMICA
      * CPD      : INEFE
      *****************************************************************
       IDENTIFICATION DIVISION.
      *************************
       PROGRAM-ID. COBOL120.
       AUTHOR. VAGNER BELLACOSA.
       DATE-WRITTEN. 06/09/24 @ 21:18:00.
       DATE-COMPILED. 2024-09-06.
       SECURITY. TESTE INEFE
       INSTALLATION. INEFE MARIST

      **********************
       ENVIRONMENT DIVISION.
      **********************
      *
       CONFIGURATION SECTION.
      *
       SOURCE-COMPUTER. IBM-I.
       OBJECT-COMPUTER. IBM-I.
       SPECIAL-NAMES. DECIMAL-POINT IS COMMA.
      *
       INPUT-OUTPUT SECTION.
      *

      ***************
       DATA DIVISION.
      ***************
      *
       WORKING-STORAGE  SECTION.
      *
       01 WORK-AREA.
        05 WSS-DATA1           PIC X(4) VALUE 'AAAA'.
        05 WSS-DATA2           PIC X(4) VALUE 'BBBB'.
        05 WSS-DATA3           PIC X(4) VALUE 'CCCC'.
        05 WSS-DATA4           PIC X(4) VALUE 'ZZZZ'.
      *
       77 WSS-PTR POINTER.
       77 WSS-IDX              PIC 9.
      *
       LINKAGE SECTION.
      *
       01 TBL-DATA.
        05 TBL-DATA-ALPHA      PIC X(4) OCCURS 4 TIMES.
      *
      ********************
       PROCEDURE DIVISION.                                              00210000
      ********************

           DISPLAY ' '
           DISPLAY ' '
           DISPLAY ' COBOL120'
           DISPLAY ' USO DE TABELA INTERNA E MOVIMENTACAO POR PONTEIRO'
           DISPLAY ' DE MEMORIA.'
           DISPLAY ' '

      *
           DISPLAY ' TABELA INICIAL - VAZIA'.
           DISPLAY ' '.

           PERFORM VARYING WSS-IDX FROM 1 BY 1
                                 UNTIL WSS-IDX > 4
             DISPLAY ' TBL-DATA-ALPHA [' WSS-IDX '] = '
                       TBL-DATA-ALPHA(WSS-IDX)
           END-PERFORM.

           DISPLAY ' '.

      *
           SET WSS-PTR TO ADDRESS OF WORK-AREA.
           SET ADDRESS OF TBL-DATA TO WSS-PTR.
      *
           DISPLAY ' RECEBI O MESMO ENDERECO DA WORKING'
           DISPLAY ' TABELA INTERNA INICIALIZADA PELO ADDRESS E SET'
           DISPLAY ' '.

           PERFORM VARYING WSS-IDX FROM 1 BY 1
                                 UNTIL WSS-IDX > 4
             DISPLAY ' TBL-DATA-ALPHA [' WSS-IDX '] = '
                       TBL-DATA-ALPHA(WSS-IDX)
           END-PERFORM.

           DISPLAY ' '.

           STOP RUN.

       END PROGRAM COBOL120.
      ********************** FIM PROGRAMA   **************************** 

Como funciona.


Article content


  • SET WSS-PTR TO ADDRESS OF WORK-AREA.


O comando acima obtém o ponteiro de memória da WORK-AREA e aloca na variável WSS-PTR.


  • SET ADDRESS OF TBL-DATA TO WSS-PTR.


No segundo comando SET ADDRESS atribui o endereço do ponteiro na tabela TBL-DATA, que a partir de agora tem o mesmo conteúdo das variáveis.


Article content
 PERFORM VARYING WSS-IDX FROM 1 BY 1
                                 UNTIL WSS-IDX > 4
             DISPLAY ' TBL-DATA-ALPHA [' WSS-IDX '] = '
                       TBL-DATA-ALPHA(WSS-IDX)
           END-PERFORM.

Esse laço lista todas as ocorrencias da Tabela Interna na Sysout.

Espero ter ajudado.


quarta-feira, 25 de outubro de 2023

COBOL Recursivo sem Mistérios

 

Bellacosa Mainframe dicas e pratica em cobol mainframe recursivo

☕ Um Café no Bellacosa Mainframe

COBOL Recursivo sem Mistérios

Como Programar Funções Recursivas e Percorrer Árvores B como um Oficial da Frota Estelar

"A maioria dos programadores COBOL passa décadas escrevendo programas sem nunca utilizar recursividade. Não porque ela não exista. Mas porque o universo do processamento batch sempre favoreceu algoritmos iterativos. Entretanto, quando você entra no mundo de compiladores, parsers, XML, JSON, árvores de decisão, estruturas hierárquicas e inteligência artificial, descobrirá que existe uma arma secreta escondida dentro do Enterprise COBOL."

Prepare seu café.

Hoje o Capitão Kirk autorizou acesso aos bancos de dados mais profundos da USS Enterprise.

Vamos explorar uma tecnologia que muitos acreditam que COBOL "não possui".

Possui.

E muito bem.


O mito

Existe uma frase repetida há décadas:

"COBOL não suporta recursividade."

Isso era verdade...

...há muitos anos.

Desde o Enterprise COBOL moderno, programas podem chamar a si próprios.

Basta utilizar as opções corretas do compilador.

E entender o que realmente acontece na memória.


O que é recursividade?

Recursividade é quando um programa chama...

...ele mesmo.

Exemplo extremamente simples.

Imagine contar regressivamente.

5
4
3
2
1
Fim

Ao invés de fazer:

PERFORM VARYING

fazemos

CONTAR(5)

↓

CONTAR(4)

↓

CONTAR(3)

↓

CONTAR(2)

↓

CONTAR(1)

Cada chamada cria uma nova execução independente.


Pensando como Spock

Spock não resolveria um problema inteiro.

Ele dividiria.

Sempre.

Existe solução?

↓

Resolva um pedaço

↓

O restante é igual

↓

Chame novamente

Isso é exatamente recursividade.


Como o COBOL consegue fazer isso?

Cada chamada cria uma nova área de trabalho.

Ela contém:

  • variáveis locais

  • parâmetros

  • ponteiros

  • retorno

Tudo fica armazenado na pilha (Stack).

Visualmente.

MAIN

↓

PROGRAMA

↓

PROGRAMA

↓

PROGRAMA

↓

PROGRAMA

Cada nível ocupa memória.


Por isso existe um risco

Se esquecer a condição de parada...

Programa

↓

Programa

↓

Programa

↓

Programa

↓

Programa

↓

Programa

↓

Programa

Nunca termina.

Resultado:

Stack Overflow

Ou

S878

S80A

Storage Exhausted

Dependendo do ambiente.


A regra número 1

Toda função recursiva precisa possuir uma condição de parada.

Sempre.

Exemplo.

IF N = ZERO
    EXIT
END-IF

Sem isso...

adeus memória.


Ativando recursividade

No Enterprise COBOL normalmente utiliza-se

RECURSIVE

na identificação do programa.

IDENTIFICATION DIVISION.

PROGRAM-ID. TREESEARCH
    RECURSIVE.

ou opção equivalente do compilador dependendo da versão.

Outra prática comum é utilizar:

RENT

para permitir reentrância.


Reentrante x Recursivo

São conceitos diferentes.

Reentrante

→ vários usuários usam ao mesmo tempo.

Recursivo

→ o programa chama ele próprio.

Pode existir:

✔ Reentrante

sem ser

✔ Recursivo.


Quando utilizar?

Quando o problema possui natureza hierárquica.

Por exemplo.

Árvore.

XML.

JSON.

AST de compilador.

Pastas.

Menus.

Dependências.

Organogramas.

Genealogia.

Árvore de chamadas.


Imagine uma árvore B

Uma árvore B organiza registros.

             40

      20            60

   10   30      50     70

Encontrar um valor nela é extremamente elegante usando recursividade.


Estrutura lógica

Cada nó possui

Valor

Filho esquerdo

Filho direito

No COBOL real normalmente usamos tabelas e índices.

Exemplo didático.

NODE-ID

LEFT-CHILD

RIGHT-CHILD

Nossa missão

Encontrar

50

Algoritmo

Primeiro olhamos

40

50 é maior.

Então ignoramos todo lado esquerdo.

Seguimos para direita.

60

Agora

50 é menor.

Voltamos para esquerda.

Encontramos

50

Fim.


Em pseudocódigo

SEARCH(NODE)

IF NODE = NULL
    NÃO EXISTE

IF NODE = CHAVE
    ENCONTROU

SE CHAVE < NODE
    SEARCH(LEFT)

SENÃO
    SEARCH(RIGHT)

Perceba.

O algoritmo inteiro possui poucas linhas.

Porque ele reutiliza a própria lógica.


Exemplo COBOL simplificado

IDENTIFICATION DIVISION.
PROGRAM-ID. TREESEARCH RECURSIVE.

WORKING-STORAGE SECTION.

01 WS-KEY          PIC 9(4).

LINKAGE SECTION.

01 LK-NODE.
   05 LK-VALUE     PIC 9(4).
   05 LK-LEFT      POINTER.
   05 LK-RIGHT     POINTER.

PROCEDURE DIVISION USING LK-NODE.

    IF LK-NODE = NULL
        GOBACK
    END-IF

    IF WS-KEY = LK-VALUE
        DISPLAY "ENCONTRADO"
        GOBACK
    END-IF

    IF WS-KEY < LK-VALUE
        CALL "TREESEARCH"
             USING LK-LEFT
    ELSE
        CALL "TREESEARCH"
             USING LK-RIGHT
    END-IF.

    GOBACK.

Este exemplo é conceitual. Em aplicações reais, árvores costumam ser representadas por tabelas indexadas, estruturas dinâmicas com ALLOCATE/FREE (quando suportado) ou áreas obtidas por serviços do sistema.


Observe a mágica

O programa nunca pergunta

Estou no nível 2?

Estou no nível 5?

Estou no nível 30?

Ele simplesmente chama ele mesmo.


Visualizando a pilha

SEARCH(40)

↓

SEARCH(60)

↓

SEARCH(50)

↓

Encontrado

Depois começa retornar.

SEARCH(50)

↓

SEARCH(60)

↓

SEARCH(40)

↓

MAIN

É literalmente uma subida e descida.


O retorno automático

Cada chamada lembra onde parou.

Imagine.

A chama B

↓

B chama C

↓

C chama D

Quando D termina.

Volta para C.

Depois B.

Depois A.

Sem que você precise controlar isso.


Onde COBOL utiliza isso na prática?

Mais do que muitos imaginam.

Ferramentas IBM fazem uso intenso.

Compiladores COBOL.

Parser SQL.

Parser XML.

JSON Parser.

XPath.

XSD.

Analisadores sintáticos.

Motores de regras.


Árvore B em bancos

Db2 utiliza árvores B (B-Trees).

Quando fazemos

SELECT

WHERE CPF

O banco NÃO lê milhões de registros.

Ele navega pela árvore.

Raiz

↓

Nó

↓

Folha

Pouquíssimos acessos.


Curiosidade

Quando você cria

CREATE INDEX

Na prática.

Está construindo uma enorme árvore balanceada.


Então...

Todo programador COBOL usa árvore B.

Mesmo sem perceber.


Mas...

Devemos escrever árvore recursiva sempre?

Não.

Existe um preço.


CPU

Cada chamada possui custo.

Salvar registradores

↓

Criar stack frame

↓

Passar parâmetros

↓

Retornar

Tudo isso consome CPU.


Memória

Cada chamada cria.

Variáveis

Endereço retorno

Parâmetros

Estado

Imagine 100.000 níveis.

Pode explodir.


Comparando

Iterativo

WHILE

Consome

CPU menor

Memória fixa

Recursivo

CPU maior

Stack crescente

Então por que usar?

Porque alguns problemas ficam absurdamente mais simples.

Exemplo.

Árvore.

Iterativo

300 linhas

Recursivo

40 linhas

Mais fácil.

Mais elegante.

Menos bugs.


Quando evitar?

Processamento sequencial.

Leitura VSAM.

Arquivo QSAM.

Loops simples.

Relatórios.

Batch tradicional.

Nestes casos.

PERFORM VARYING

vence.


Tail Recursion

Existe uma otimização famosa.

Tail Recursion.

Função termina chamando ela mesma.

Alguns compiladores eliminam o crescimento da pilha.

Infelizmente.

Nem todo compilador COBOL faz isso.

Portanto.

Nunca conte com essa otimização.


Cuidado com milhões de chamadas

Imagine uma árvore degenerada.

10

 \

 20

   \

   30

     \

     40

Ela parece uma lista.

A recursividade fará milhares de chamadas.

Ruim.

Árvores balanceadas evitam isso.


B-Tree resolve exatamente este problema

Ela mantém altura pequena.

Mesmo com milhões de registros.

É justamente por isso que bancos usam B-Tree.

Não Binary Tree simples.


Dica de ouro

Nunca escreva recursividade sem antes responder:

Qual é minha condição de parada?

Se não conseguir responder.

Ainda não terminou o algoritmo.


Outra dica

Desenhe.

Sempre.

Árvores ficam muito mais fáceis no papel.


Debug

Durante testes faça:

DISPLAY

Mostrando o nível.

DISPLAY "LEVEL=" WS-NIVEL

Assim você visualiza a profundidade.


Performance em Mainframe

No IBM Z.

CPU é dinheiro.

Cada microssegundo importa.

Por isso.

Recursividade costuma aparecer mais em:

  • middleware

  • compiladores

  • parsers

  • XML

  • JSON

  • IA

  • engines

Do que em batch financeiro.


Curiosidade histórica

Nos anos 70.

Poucos compiladores COBOL aceitavam recursividade.

A memória era extremamente cara.

Muitas máquinas tinham poucos megabytes.

Era impensável desperdiçar stack.

Hoje.

Servidores IBM Z possuem centenas de gigabytes.

O cenário mudou.


Boas práticas

✔ Sempre tenha condição de parada clara.

✔ Documente a lógica antes de codificar.

✔ Prefira árvores balanceadas.

✔ Limite profundidade quando possível.

✔ Evite variáveis globais compartilhadas.

✔ Teste casos extremos.

✔ Monitore consumo de CPU e memória.

✔ Utilize recursividade apenas quando ela realmente simplifica o problema.

✔ Faça revisão de código focando em chamadas recursivas.

✔ Meça desempenho antes de concluir que a solução é "rápida".


Armadilhas comuns

❌ Esquecer a condição de parada.

❌ Modificar dados globais inesperadamente.

❌ Assumir que toda árvore é balanceada.

❌ Ignorar consumo de stack.

❌ Trocar elegância por complexidade desnecessária.

❌ Usar recursividade onde um PERFORM VARYING resolveria de forma mais simples.


Recursividade e Enterprise COBOL

As versões modernas do IBM Enterprise COBOL oferecem suporte a programas recursivos, mas é importante observar alguns detalhes:

  • Declare o programa como RECURSIVE quando necessário.

  • Utilize opções de compilação adequadas ao ambiente, frequentemente combinadas com RENT em aplicações compartilhadas.

  • Consulte sempre o padrão adotado pela sua empresa e a documentação da versão do compilador em uso, pois políticas de compilação variam entre instalações.

Em ambientes CICS, IMS ou aplicações de alta concorrência, também é essencial compreender os conceitos de reentrância, armazenamento automático e áreas de trabalho para evitar efeitos colaterais entre execuções simultâneas.


Missão para o Padawan COBOL

Depois de dominar este artigo, experimente implementar os seguintes desafios:

  1. Fatorial usando recursividade.

  2. Sequência de Fibonacci (comparando desempenho com versão iterativa).

  3. Percorrer uma árvore binária em ordem (in-order).

  4. Percorrer uma árvore em pré-ordem (pre-order).

  5. Percorrer uma árvore em pós-ordem (post-order).

  6. Simular um índice de clientes usando uma árvore binária simples.

  7. Comparar o tempo de busca entre uma tabela sequencial e uma árvore.

  8. Criar um visualizador com DISPLAY mostrando o nível de cada chamada recursiva.

Cada exercício ajudará você a entender não apenas como a recursividade funciona, mas quando ela é realmente a melhor ferramenta.

Conclusão — O Holodeck da Recursividade

Existe uma lição que diferencia um programador comum de um verdadeiro oficial da Frota Estelar.

O iniciante procura resolver problemas escrevendo mais código.

O engenheiro experiente procura resolver problemas encontrando a estrutura correta.

A recursividade é exatamente isso: uma mudança de perspectiva. Em vez de atacar um problema gigantesco de uma única vez, você o divide em pequenas partes idênticas, permitindo que o próprio algoritmo repita a solução até alcançar a condição de parada.

No universo do COBOL, ela não substitui os tradicionais PERFORM VARYING, nem foi criada para processar milhões de registros sequenciais de um batch financeiro. Seu verdadeiro poder aparece quando trabalhamos com estruturas hierárquicas: árvores B, XML, JSON, compiladores, interpretadores, mecanismos de regras, grafos e diversos algoritmos modernos que fazem parte da computação atual.

Como diria o Sr. Spock:

"A solução mais elegante normalmente é aquela que respeita a estrutura natural do problema."

Quando você compreender essa filosofia, deixará de enxergar a recursividade como um truque de linguagem e passará a vê-la como uma ferramenta de modelagem.

E esse é um dos momentos em que um Padawan COBOL começa a trilhar o caminho para se tornar um verdadeiro Mestre do Mainframe.


quinta-feira, 5 de maio de 2022

DSA para Programadores COBOL Padawan

 

Bellacosa Mainframe apresenta DSA para programadores

☕ Um Café no Bellacosa Mainframe

DSA para Programadores COBOL Padawan

Você Não Precisa Decorar 500 Problemas do LeetCode. Precisa Aprender a Reconhecer Padrões.

"Todo programador iniciante acredita que grandes desenvolvedores conhecem milhares de algoritmos. Depois de alguns anos de experiência, descobre que eles conhecem apenas algumas dezenas de padrões... e sabem exatamente quando utilizá-los."


Existe uma pergunta que aparece frequentemente entre jovens programadores COBOL que desejam migrar para o universo moderno da Engenharia de Software:

"Preciso aprender LeetCode para conseguir boas oportunidades?"

Minha resposta normalmente surpreende.

Não.

Você precisa aprender como pensar.

LeetCode é uma academia.

DSA (Data Structures and Algorithms) é aprender anatomia.

Um fisiculturista pode decorar todos os exercícios da academia.

Um médico entende músculos, ossos, tendões e articulações.

Quem entende anatomia consegue criar novos exercícios.

Quem entende DSA consegue resolver problemas que nunca viu antes.

Essa é exatamente a diferença entre decorar soluções e compreender padrões.

E essa diferença vale tanto para um desenvolvedor Java quanto para um veterano de COBOL com trinta anos de experiência em sistemas bancários.


O Programador COBOL Já Conhece DSA (Mesmo Sem Saber)

Essa talvez seja a maior surpresa.

Muitos profissionais de Mainframe acreditam que DSA é uma invenção recente.

Não é.

Na verdade, você trabalha com isso há décadas.

Veja alguns exemplos.

Quando você faz uma leitura sequencial de um arquivo VSAM...

...está explorando uma estrutura de dados.

Quando faz um SEARCH ALL...

...está utilizando Binary Search.

Quando usa tabelas OCCURS...

...está manipulando Arrays.

Quando organiza registros por chave...

...está trabalhando com algoritmos de ordenação.

Quando utiliza um índice alternativo no VSAM...

...está explorando conceitos semelhantes às árvores de busca.

O que mudou foi apenas a nomenclatura.


O Grande Erro de Quem Estuda LeetCode

Imagine que alguém queira aprender COBOL.

Então começa resolvendo programas aleatórios.

Um dia faz folha de pagamento.

No outro faz cálculo de imposto.

Depois processamento de boletos.

Na semana seguinte faz conciliação bancária.

Será que ele aprenderá COBOL?

Provavelmente não.

Porque cada programa utiliza conceitos diferentes.

Com DSA acontece exatamente o mesmo.

Resolver problemas aleatórios é uma forma extremamente lenta de aprender.

Muito melhor é dominar um padrão de cada vez.

Quando você aprende Sliding Window...

...de repente resolve cinquenta problemas diferentes.

Quando entende HashMap...

...mais cinquenta deixam de parecer difíceis.

É um efeito multiplicador.


Pensando Como um Analista de Sistemas

Um analista experiente nunca começa programando.

Ele começa fazendo perguntas.

Da mesma forma, um bom solucionador de problemas faz um diagnóstico antes de escrever uma linha de código.

Seu raciocínio deveria seguir algo parecido com isto:

Que tipo de dado eu possuo?

↓

Qual estrutura representa melhor esses dados?

↓

Existe um padrão conhecido?

↓

Qual algoritmo resolve isso?

↓

Quanto custa em tempo?

↓

Quanto custa em memória?

Perceba que programação é apenas o último passo.

O verdadeiro trabalho acontece antes.


Arrays: O Arquivo Sequencial da Programação

Se existe uma estrutura que todo programador COBOL domina intuitivamente, é o Array.

Em COBOL:

01 CLIENTES.
   05 CLIENTE OCCURS 1000 TIMES.
      10 NOME PIC X(30).

Isso é um Array.

Na maioria das linguagens modernas:

clientes[1000]

É exatamente o mesmo conceito.

O interessante é que vários algoritmos famosos trabalham exclusivamente sobre Arrays.

Entre eles:

  • Prefix Sum

  • Sliding Window

  • Kadane

  • Binary Search

Cada um resolve um tipo específico de problema.


Prefix Sum: Quando Somar Milhões de Registros Precisa Ser Rápido

Imagine um banco.

Existe um histórico diário de saldo.

O gerente pergunta:

"Qual foi a movimentação entre os dias 500 e 1800?"

A solução ingênua seria somar tudo novamente.

Mas isso custa:

O(n)

Prefix Sum cria uma tabela acumulada.

Depois disso qualquer consulta vira praticamente instantânea.

Essa ideia aparece em:

  • Data Warehouses

  • BI

  • Analytics

  • Processamento Financeiro

  • Mainframe Batch

Embora muitos profissionais não percebam, diversas rotinas históricas de fechamento utilizam exatamente esse princípio.


Sliding Window: Não Recalcule o Que Você Já Sabe

Imagine um programa que precisa descobrir os três maiores dias consecutivos de vendas.

Um iniciante faz isto:

Soma dia 1

Soma dia 2

Soma dia 3

Depois recomeça tudo.

Um desenvolvedor experiente pensa diferente.

"Já conheço dois dos três valores."

Então remove apenas o elemento que saiu da janela e adiciona o próximo.

É como acompanhar uma esteira rolante.

Você não desmonta a esteira inteira para observar o próximo objeto.

Apenas acompanha seu movimento.

Esse padrão reduz muitos problemas de O(n²) para O(n).


Binary Search: Muito Além de Procurar

Todo mundo conhece Binary Search como uma busca em listas ordenadas.

Mas existe um detalhe interessante.

Hoje ele é muito mais utilizado para responder perguntas como:

"Qual é o menor valor possível?"

"Qual é a menor capacidade de armazenamento?"

"Qual é a menor velocidade aceitável?"

Sempre que existe uma resposta monotônica, Binary Search pode aparecer.

É por isso que ele continua sendo um dos algoritmos preferidos em entrevistas.


Strings: O Mundo dos Textos

Mainframes trabalham intensamente com texto.

CPF.

Nome.

Código de Agência.

Número da Conta.

Mensagens.

Arquivos CNAB.

Tudo isso são Strings.

Existem alguns padrões clássicos.

Two Pointers

Muito útil para:

  • remover espaços

  • comparar extremos

  • detectar palíndromos

É simples.

Dois ponteiros caminham em velocidades diferentes ou em sentidos opostos.


KMP

Imagine procurar uma palavra dentro de um documento de centenas de megabytes.

Sem estratégia...

...você volta inúmeras vezes ao início.

KMP evita repetir trabalho.

Ele aprende durante a própria busca.

É um excelente exemplo de algoritmo inteligente.


HashMap: A Memória Instantânea

HashMap talvez seja a estrutura que mais transforma problemas difíceis em problemas simples.

Imagine a pergunta:

"Este CPF já apareceu?"

Sem HashMap:

Procure tudo novamente.

Com HashMap:

Consulte diretamente.

É praticamente um índice em memória.

Quem trabalhou com índices DB2 entende rapidamente essa ideia.

Não percorremos a tabela inteira.

Consultamos uma estrutura otimizada.


Pilhas (Stacks): A Forma Natural de Resolver Alguns Problemas

Uma Stack segue a regra:

Last In

First Out

Ou seja:

O último que entra é o primeiro que sai.

Pense numa pilha de JCLs impressos.

O último colocado em cima será retirado primeiro.

Stacks aparecem em:

  • compiladores

  • interpretadores

  • validação de parênteses

  • chamadas de funções

  • expressões matemáticas

Sempre que existir necessidade de "voltar" ao estado anterior, existe uma boa chance de uma Stack resolver o problema.


Filas: O Modelo Natural do Batch

Se existe uma estrutura familiar ao mundo Mainframe é a Queue.

Os Jobs entram.

Esperam.

São executados.

Saem.

JES2 e JES3 vivem exatamente desse conceito.

Fila.

Primeiro que entra.

Primeiro que sai.

O mesmo vale para sistemas de mensagens como IBM MQ.


Linked Lists: Quando a Ordem Importa Mais que a Posição

Em um Array sabemos exatamente onde cada elemento está.

Em uma Linked List sabemos apenas quem é o próximo.

Isso muda completamente a forma de navegar pelos dados.

Um algoritmo famoso utiliza dois ponteiros.

Um anda normalmente.

Outro corre duas posições.

É o famoso algoritmo da Tartaruga e da Lebre.

Ele consegue descobrir ciclos sem utilizar memória adicional.

Uma verdadeira obra de elegância.


Árvores: Muito Mais Presentes do Que Você Imagina

Quando pensamos em árvores normalmente lembramos da faculdade.

Mas elas aparecem diariamente.

Diretórios.

Menus.

JSON.

XML.

LDAP.

Catálogos.

Organogramas.

Até um Plano de Contas contábil é uma árvore.

Quando aprendemos percursos como:

  • Preorder

  • Inorder

  • Postorder

  • Level Order

Estamos aprendendo maneiras diferentes de visitar essa hierarquia.


Grafos: O Modelo Universal

Existe uma frase famosa na Ciência da Computação:

"Tudo pode ser modelado como um grafo."

Internet.

Rotas.

Redes sociais.

Dependências.

Fluxos.

Microserviços.

Tudo isso pode ser representado por nós ligados entre si.

Os principais algoritmos são:

  • BFS

  • DFS

  • Dijkstra

  • Topological Sort

Se você entende esses quatro...

...já resolve uma enorme quantidade de problemas reais.


Programação Dinâmica: A Arte de Não Fazer o Mesmo Trabalho Duas Vezes

Esse talvez seja o assunto que mais assusta iniciantes.

Mas a ideia é incrivelmente simples.

Imagine calcular Fibonacci.

Sem memória:

Fib(40)

↓

Fib(39)

↓

Fib(38)

↓

...

Os mesmos cálculos aparecem centenas de milhares de vezes.

Programação Dinâmica guarda os resultados.

Quando precisar novamente...

...apenas consulta.

No Mainframe fazemos isso frequentemente.

Tabelas em memória.

Caches.

Arquivos temporários.

Tudo isso segue exatamente essa filosofia.


Greedy: A Melhor Decisão Agora

Alguns problemas permitem escolher sempre a melhor opção local.

Quando isso acontece...

...Greedy produz soluções extremamente rápidas.

Mas cuidado.

Nem todo problema aceita essa abordagem.

Saber reconhecer quando Greedy funciona é tão importante quanto conhecer o algoritmo.


Manipulação de Bits: O Poder Escondido do Hardware

Bits ainda são fundamentais.

Operações como:

AND

OR

XOR

SHIFT

São extremamente rápidas.

Mainframes utilizam instruções de hardware especializadas justamente para explorar esse tipo de operação.

Muitos algoritmos de criptografia, compressão e otimização dependem delas.


Estruturas Avançadas

Quando os problemas ficam maiores surgem novas ferramentas.

Segment Trees.

Fenwick Trees.

Sweep Line.

Meet in the Middle.

Essas técnicas aparecem menos no dia a dia, mas são muito comuns em competições de programação e entrevistas de empresas de tecnologia.

Elas demonstram que um mesmo problema pode ser atacado por diferentes estratégias, cada uma adequada a um cenário específico.


O Que Realmente Avaliam em uma Entrevista Técnica?

Muitos imaginam que a empresa quer saber se você decorou o algoritmo de Dijkstra.

Na realidade ela observa outra coisa.

Seu raciocínio.

Ela quer entender se você consegue:

  • Identificar a estrutura de dados correta.

  • Escolher o algoritmo adequado.

  • Explicar por que essa escolha é eficiente.

  • Comparar alternativas.

  • Analisar complexidade de tempo e memória.

  • Escrever um código claro e correto.

A implementação é importante, mas a capacidade de justificar as decisões costuma pesar ainda mais.


O Caminho de Estudos para um COBOL Padawan

Se eu estivesse orientando um jovem programador COBOL hoje, seguiria esta ordem:

  1. Arrays e Strings.

  2. Hash Maps.

  3. Stacks e Queues.

  4. Linked Lists.

  5. Árvores.

  6. Grafos.

  7. Recursão.

  8. Heaps.

  9. Programação Dinâmica.

  10. Técnicas avançadas.

Depois disso, sim, começaria a resolver problemas no LeetCode, HackerRank ou plataformas semelhantes.

Porque, nesse momento, cada exercício deixaria de ser um enigma e passaria a ser um reconhecimento de padrões.


Conclusão: O Verdadeiro Poder Está na Forma de Pensar

Existe um mito de que grandes programadores possuem uma memória extraordinária e conhecem milhares de algoritmos. A realidade é bem diferente. Eles desenvolveram um repertório de padrões e sabem identificar rapidamente qual deles se aplica a um problema.

O programador COBOL possui uma vantagem importante nessa jornada. Décadas trabalhando com arquivos sequenciais, VSAM, DB2, índices, tabelas OCCURS, processamento batch e transações CICS desenvolveram uma disciplina de raciocínio que continua extremamente valiosa. O desafio não é abandonar esse conhecimento, mas traduzi-lo para a linguagem moderna das Estruturas de Dados e Algoritmos.

Quando você perceber que um SEARCH ALL é uma busca binária, que uma tabela OCCURS é um array, que uma fila JES2 segue o princípio de uma queue, ou que um índice DB2 representa uma estrutura otimizada para acesso eficiente, verá que DSA não é um universo distante do Mainframe. É a formalização de conceitos que sempre estiveram presentes.

No fim das contas, programar bem nunca foi sobre decorar centenas de soluções. Sempre foi sobre observar, modelar e resolver problemas da forma mais elegante possível. É essa mentalidade que transforma um Padawan COBOL em um verdadeiro Arquiteto de Software, capaz de navegar tanto pelos sistemas legados que movem bancos e governos quanto pelas tecnologias modernas que definem o futuro da computação.


terça-feira, 26 de janeiro de 2021

☕🔥 25 CODING PATTERNS — O “DNA INVISÍVEL” QUE TODO PROGRAMADOR DE MAINFRAME USA (MESMO SEM PERCEBER)

 

Bellacosa Mainframe apresenta 25 coding patterns

☕🔥 25 CODING PATTERNS — O “DNA INVISÍVEL” QUE TODO PROGRAMADOR DE MAINFRAME USA (MESMO SEM PERCEBER)

Existe uma verdade que separa programadores comuns de engenheiros realmente perigosos:

🔥 os melhores não decoram código…

eles reconhecem padrões.

E isso vale para:

  • Python

  • Java

  • C

  • COBOL

  • Assembler

  • PL/I

  • DB2 SQL

  • CICS

  • z/OS

Porque no fundo…

programação é:

resolver problemas repetitivos de maneiras inteligentes.

E quando analisamos esses Coding Patterns ao estilo Bellacosa Mainframe…

descobrimos algo fascinante:

🔥 o Mainframe já utilizava muitos desses conceitos MUITO antes deles virarem moda em entrevistas LeetCode.


☕🔥 O QUE SÃO CODING PATTERNS?

São modelos mentais reutilizáveis.


☕ Em vez de decorar solução…

você aprende:

COMO PENSAR

☕ Bellacosa Mainframe Analysis™

Coding Pattern é como:

🔥 um PROC JCL mental reutilizável.


☕ Porque problemas diferentes frequentemente compartilham:

  • estrutura

  • lógica

  • fluxo

  • comportamento


☕🔥 1. TWO POINTERS — O “MATCHING” CLÁSSICO DO MAINFRAME

Dois ponteiros percorrendo estruturas simultaneamente.


☕ Muito usado em:

  • merge

  • comparação

  • busca

  • matching


☕ Isso lembra MUITO:

🔥 SORT/MERGE no z/OS.


☕ Exemplo clássico Mainframe

Comparar:

ARQUIVO CLIENTE
VS
ARQUIVO PAGAMENTO

☕ Dois ponteiros avançam conforme chave.


☕ COBOL usa isso há décadas.


☕🔥 2. SLIDING WINDOW — O “BUFFER DINÂMICO”

Padrão extremamente poderoso.


☕ A ideia:

uma janela percorre dados continuamente.


☕ Exemplo moderno

  • stream

  • logs

  • monitoramento

  • analytics


☕ No Mainframe isso lembra:

  • leitura sequencial VSAM

  • análise SMF

  • monitoramento RMF


☕ Excelente para:

🔥 reduzir complexidade absurda.


☕🔥 3. PREFIX SUM — O “ACUMULADOR CORPORATIVO”

Muito usado em:

  • estatísticas

  • relatórios

  • batch processing


☕ Bellacosa Mainframe Analysis™

Isso é praticamente:

🔥 processamento batch financeiro clássico.


☕ Exemplo bancário

Saldo acumulado:

saldo_anterior + movimento

☕ Mainframe vive disso.


☕🔥 4. MERGE INTERVALS — O “CONSOLIDADOR DE JANELAS”

Combinar intervalos sobrepostos.


☕ Aplicações reais

  • agendas

  • reservas

  • processamento temporal

  • janelas batch


☕ Isso lembra muito:

🔥 scheduler corporativo.


☕ JES2/JES3 possuem conceitos semelhantes de coordenação temporal.


☕🔥 5. BINARY SEARCH — O “CATÁLOGO INDEXADO” DO DB2

Busca dividindo espaço pela metade.


☕ O ganho é brutal:

O(log n)

☕ Bellacosa Mainframe Analysis™

É praticamente:

🔥 acesso indexado DB2/VSAM KSDS.


☕ Índices existem exatamente para evitar:

table scan infernal

☕🔥 6. SORTING PATTERNS — O REINO ABSOLUTO DO MAINFRAME

Aqui o Mainframe reina historicamente.


☕ SORT sempre foi:

🔥 uma arte no z/OS.


☕ DFSORT e SyncSort são monstruosamente otimizados.


☕ Grandes bancos literalmente dependem disso.


☕ Exemplo:

  • fechamento bancário

  • consolidação

  • ranking

  • billing


☕🔥 7. FAST & SLOW POINTERS — DETECTANDO CICLOS E ANOMALIAS

Dois ponteiros em velocidades diferentes.


☕ Excelente para:

  • loops

  • listas

  • estruturas cíclicas

  • detecção de comportamento


☕ Isso lembra:

🔥 monitoramento operacional.


☕ Em sistemas críticos:

detectar loop cedo evita desastre.


☕🔥 8. BACKTRACKING — A “BUSCA EXAUSTIVA INTELIGENTE”

Testa possibilidades recursivamente.


☕ Parece caro?

E é.


☕ Mas resolve problemas extremamente complexos.


☕ Exemplo corporativo

  • otimização

  • roteamento

  • IA

  • scheduling


☕🔥 9. DIVIDE AND CONQUER — O “PARALEL SYSPLEX” MENTAL

Dividir problema gigante em partes menores.


☕ Mainframe faz isso há décadas.


☕ Exemplos:

  • Parallel Sysplex

  • workload balancing

  • batch parallelism


☕ Isso escalou o mundo corporativo.


☕🔥 10. LINKED LISTS — O “ENCADENAMENTO” CLÁSSICO

Estruturas ligadas dinamicamente.


☕ Mainframe conhece isso profundamente.

Especialmente em:

  • buffers

  • control blocks

  • cadeias de memória


☕ Assembler vive disso.


☕🔥 11. STACKS & QUEUES — O “CICS” DA LÓGICA

Agora entramos numa das estruturas mais importantes da computação.


☕ Queue

FIFO.


☕ Stack

LIFO.


☕ Isso aparece em TODO lugar.


☕ Bellacosa Mainframe Analysis™

CICS trabalha pesado com conceitos de filas e pilhas operacionais.


☕ MQ então?

🔥 literalmente vive disso.


☕🔥 12. MONOTONIC STACK — O “OTIMIZADOR SILENCIOSO”

Pattern avançado.


☕ Excelente para:

  • análise sequencial

  • máximos/mínimos

  • otimização temporal


☕ Muito útil em:

  • mercado financeiro

  • séries temporais

  • observabilidade


☕🔥 13. EXPRESSION EVALUATION — O “COMPILADOR INTERNO”

Avaliação de expressões.


☕ Compiladores COBOL fazem isso constantemente.


☕ Exemplo:

COMPUTE TOTAL = A + B * C

☕ Existe parsing por trás.


☕🔥 14. STRING MANIPULATION — O IMPÉRIO DO COBOL

Mainframe ama texto estruturado.


☕ Exemplos:

  • EBCDIC

  • layouts

  • copybooks

  • parsing bancário


☕ COBOL virou mestre nisso.


☕🔥 15. HASHMAPS — O “CATÁLOGO RACF” MODERNO

Busca rápida por chave.


☕ Isso lembra:

  • tabelas de controle

  • catálogos

  • cache

  • diretórios RACF


☕ Extremamente eficiente.


☕🔥 16. TREES & BST — A HIERARQUIA CORPORATIVA

Estruturas hierárquicas.


☕ Mainframe usa isso em:

  • catálogos

  • RACF

  • hierarquias de storage

  • índices


☕🔥 17. PATH SUM — O “FLUXO TRANSACIONAL”

Analisar caminhos possíveis.


☕ Isso aparece em:

  • antifraude

  • IA

  • workflows

  • análise financeira


☕🔥 18. HEAPS — O “TOP N” CORPORATIVO

Excelente para encontrar:

  • maiores

  • menores

  • prioridades


☕ Exemplo bancário

🔥 TOP clientes por volume.


☕🔥 19. TOP K FREQUENT — O “RMF ANALYTICS”

Análise estatística frequente.


☕ Muito usado em:

  • observabilidade

  • logs

  • IA

  • SIEM


☕🔥 20. MERGE K SORTED LISTS — O “INTEGRADOR CORPORATIVO”

Combinar múltiplas listas ordenadas.


☕ Isso é MUITO Mainframe.


☕ Exemplo:

  • consolidar filiais

  • processamento distribuído

  • múltiplos datasets


☕🔥 21. DYNAMIC PROGRAMMING — O “OTIMIZADOR MATEMÁTICO”

Agora entramos na elite.


☕ DP resolve problemas reutilizando resultados anteriores.


☕ Isso reduz explosão computacional.


☕ Bellacosa Mainframe Analysis™

DP lembra:

🔥 cache inteligente corporativo.


☕🔥 22. GREEDY — O “DECIDA AGORA”

Escolha local imediata.


☕ Funciona muito bem em:

  • scheduling

  • roteamento

  • alocação


☕🔥 23. BFS & DFS — O “NAVEGADOR” DAS ESTRUTURAS

Traversal em grafos.


☕ Muito usado em:

  • redes

  • IA

  • dependências

  • análise de infraestrutura


☕🔥 24. GRAPH ALGORITHMS — O “MAPA DO MUNDO DIGITAL”

A internet inteira é um grafo.


☕ Sistemas corporativos modernos também.


☕ Isso impacta:

  • redes

  • supply chain

  • fraudes

  • relacionamentos


☕🔥 25. DESIGN PROBLEMS — O VERDADEIRO NÍVEL SENIOR

Aqui termina o tutorial…

e começa engenharia real.


☕ Porque agora o problema deixa de ser:

como codar

e passa a ser:

como arquitetar

☕🔥 O MAINFRAME SEMPRE FOI “PATTERN-DRIVEN”

Essa talvez seja a maior conclusão.


☕ Mainframe nunca foi apenas linguagem.

Sempre foi:

  • arquitetura

  • repetibilidade

  • previsibilidade

  • padrões operacionais


☕ Por isso sistemas z/OS sobrevivem décadas.


☕🔥 CONCLUSÃO — PROGRAMAR NÃO É ESCREVER CÓDIGO… É RECONHECER PADRÕES

Os melhores engenheiros não decoram respostas.

Eles identificam:

  • estruturas

  • comportamentos

  • padrões invisíveis

E talvez essa seja a maior ironia da computação moderna:

enquanto muita gente acha que esses Coding Patterns nasceram com entrevistas FAANG…

🔥 o Mainframe já resolvia muitos desses problemas silenciosamente há mais de 40 anos.

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