Sebenta · COBOL (UC02840)
Introdução
COBOL (COmmon Business-Oriented Language) é uma das linguagens mais antigas em uso activo. Criada em 1959 sob liderança de Grace Hopper, foi desenhada para aplicações de negócio: processamento de transacções, contabilidade, gestão de stocks, cálculo de salários. Sessenta e cinco anos depois, continua a correr em mainframes IBM processando triliões de dólares todos os dias.
Aprender COBOL hoje não é nostalgia — é estratégia de carreira. As estimativas dizem que 80% das transacções de cartões de crédito passam por COBOL, e a maioria dos sistemas core de bancos, seguradoras e governos continua a depender desta linguagem. Os programadores que aprenderam COBOL nos anos 70/80 estão a reformar-se em massa. Os bancos pagam fortunas a quem souber manter os seus sistemas legacy.
Esta sebenta cobre COBOL básico até saberes ler, modificar e escrever programas business simples.
1. COBOL em contexto
História breve
- 1959: Grace Hopper e o CODASYL committee criam COBOL.
- 1968: ANSI COBOL primeira standard.
- 1985: COBOL-85, ainda dominante em muitos sistemas.
- 2002: Object-COBOL (COBOL com OOP).
- 2014: COBOL 2014 (latest standard).
Onde corre
- Mainframes IBM z/OS — 80%+ do COBOL em produção.
- Unisys ClearPath, NEC ACOS.
- PC/Linux com GnuCOBOL (open source) ou Micro Focus.
Setor por setor
- Banca: core banking (Santander, JP Morgan, Bank of America).
- Seguros: cálculo de prémios, sinistros (Generali, AXA).
- Governo: segurança social, IRS (Portugal, EUA, Reino Unido).
- Telecom: billing (Verizon, AT&T).
- Retail: stocks, payroll (Walmart, Tesco).
- Logística: reservas (companhias aéreas).
Carreira COBOL hoje
- Salários acima da média (€50k-€100k em Portugal, $120k-$200k EUA).
- Pouca concorrência — escassez de programadores.
- Trabalho estável — sistemas que não desaparecem.
- Mas: rotina pode ser monótona; muito código legacy spaghetti.
2. Setup
GnuCOBOL
Compilador open source. Permite aprender COBOL sem mainframe.
Ubuntu/Debian:
sudo apt install gnucobol
Fedora:
sudo dnf install gnucobol
Mac:
brew install gnucobol
Windows: instalador no site gnucobol.sourceforge.io.
Verifica:
cobc --version
IDE
- OpenCobolIDE (Linux/Mac/Windows) — IDE dedicada.
- VSCode + extensão "COBOL" da BroadCOM (excelente).
- Eclipse + IBM Z Open Editor (mainframe-style).
Compilar e correr
cobc -x hello.cob -o hello # -x = executable
./hello
# Subprogram (módulo)
cobc -m subprog.cob # -m = module (.so)
# Free format (sem formato em colunas)
cobc -free -x moderno.cob -o moderno
3. Estrutura de um programa
Hello world
IDENTIFICATION DIVISION.
PROGRAM-ID. HELLO-WORLD.
PROCEDURE DIVISION.
DISPLAY "Olá mundo!".
STOP RUN.
Formato em colunas (fixed)
COBOL clássico exige indentação rigorosa:
Col 1-6: Numeração (opcional, ignorada)
Col 7: Indicador
espaço = código normal
* = comentário
/ = page break
- = continuação
Col 8-11: Area A (DIVISION, SECTION, paragraph)
Col 12-72: Area B (statements, declarações)
Col 73+: Identificação (ignorada)
Exemplo:
123456 78901234567890...72
IDENTIFICATION DIVISION.
PROGRAM-ID. EXEMPLO.
PROCEDURE DIVISION.
DISPLAY "Olá".
Formato livre (moderno)
Com flag -free (GnuCOBOL) ou em COBOL 2002+:
IDENTIFICATION DIVISION.
PROGRAM-ID. EXEMPLO.
PROCEDURE DIVISION.
DISPLAY "Olá".
STOP RUN.
Recomendado em código novo. Para esta UC vamos usar o formato clássico (mais comum em legacy).
As 4 DIVISIONS
IDENTIFICATION DIVISION. * obrigatória, metadados
PROGRAM-ID. NOME-PROG.
AUTHOR. JOÃO SILVA.
DATE-WRITTEN. 2026-05-25.
ENVIRONMENT DIVISION. * opcional, hardware/files
CONFIGURATION SECTION.
SOURCE-COMPUTER. PC.
OBJECT-COMPUTER. PC.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
* definições de ficheiros aqui
DATA DIVISION. * opcional, variáveis
FILE SECTION.
* estruturas dos ficheiros
WORKING-STORAGE SECTION.
* variáveis do programa
LINKAGE SECTION.
* parâmetros (subprograms)
PROCEDURE DIVISION. * obrigatória, lógica
DISPLAY "Olá".
STOP RUN.
4. Tipos de dados — PICTURE
A PICTURE (ou PIC) define tipo e tamanho de uma variável.
Caracteres especiais
| Char | Significado |
|---|---|
9 |
dígito numérico |
X |
qualquer carácter (alfanumérico) |
A |
letra alfabética |
V |
ponto decimal implícito |
S |
sinal (+/-) |
Z |
dígito com supressão de zero |
$, ,, ., -, +, / |
edição (para output formatado) |
Exemplos
01 WS-NOME PIC X(30). * 30 chars
01 WS-INICIAL PIC A. * 1 letra
01 WS-IDADE PIC 9(3). * 3 dígitos (0-999)
01 WS-SALARIO PIC 9(7)V99. * 7 inteiros + 2 decimais
01 WS-TEMPERATURA PIC S9(3)V99. * com sinal
01 WS-TELEFONE PIC 9(9).
01 WS-NIF PIC 9(9).
* Edição (formato visual)
01 WS-PRECO-EDIT PIC ZZ,ZZ9.99. * 12345.67 → "12,345.67"
01 WS-DATA-EDIT PIC 9999/99/99. * "20260525" → "2026/05/25"
VALUE — inicialização
01 WS-CONTADOR PIC 9(5) VALUE 0.
01 WS-EOF PIC X VALUE "N".
01 WS-NOME PIC X(30) VALUE "Anónimo".
01 WS-FLAG PIC X VALUE SPACE. * literais especiais
01 WS-ZEROS PIC 9(5) VALUE ZEROS.
01 WS-HIGH PIC X VALUE HIGH-VALUES. * todos os bits a 1
01 WS-LOW PIC X VALUE LOW-VALUES. * todos a 0
Literais especiais: SPACE/SPACES, ZERO/ZEROS, HIGH-VALUES, LOW-VALUES, QUOTE/QUOTES.
Grupos (records)
Permite agrupar campos:
01 WS-CLIENTE.
05 WS-ID PIC 9(6).
05 WS-NOME PIC X(30).
05 WS-MORADA.
10 WS-RUA PIC X(40).
10 WS-CIDADE PIC X(20).
10 WS-CP PIC 9(4)-9(3).
05 WS-IDADE PIC 9(3).
05 WS-SALARIO PIC 9(7)V99.
Níveis:
- 01 = record principal.
- 02-49 = subgrupos / campos.
- 66, 77, 88 = especiais.
Acesso por campo individual ou pelo grupo:
MOVE "Ana" TO WS-NOME.
MOVE 25 TO WS-IDADE.
DISPLAY WS-CLIENTE. * imprime tudo concatenado
Tabelas (arrays)
01 WS-NOTAS.
05 WS-NOTA OCCURS 5 TIMES PIC 9(3).
PROCEDURE DIVISION.
MOVE 18 TO WS-NOTA(1).
MOVE 14 TO WS-NOTA(2).
MOVE 12 TO WS-NOTA(3).
PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > 5
DISPLAY WS-NOTA(WS-I)
END-PERFORM.
Tabelas multi-dimensionais com OCCURS aninhado:
01 WS-MATRIZ.
05 WS-LINHA OCCURS 3 TIMES.
10 WS-CEL OCCURS 4 TIMES PIC 9(3).
* Acesso: WS-CEL(2, 3)
5. Operações básicas
MOVE — atribuição
MOVE "Ana" TO WS-NOME.
MOVE 25 TO WS-IDADE.
MOVE WS-A TO WS-B.
MOVE WS-CLIENTE TO WS-CLIENTE-BACKUP. * grupo inteiro
* MOVE com truncagem
MOVE "Hello World" TO WS-CURTO. * WS-CURTO PIC X(5) → "Hello"
Aritmética básica
01 WS-A PIC 9(5) VALUE 100.
01 WS-B PIC 9(5) VALUE 30.
01 WS-RES PIC 9(5).
* ADD
ADD WS-A TO WS-B. * B = A + B (130)
ADD WS-A TO WS-B GIVING WS-RES. * RES = A + B
ADD 1 TO WS-CONTADOR.
* SUBTRACT
SUBTRACT WS-B FROM WS-A. * A = A - B
SUBTRACT WS-B FROM WS-A GIVING WS-RES.
* MULTIPLY
MULTIPLY WS-A BY WS-B. * B = A * B
MULTIPLY WS-A BY WS-B GIVING WS-RES.
* DIVIDE
DIVIDE WS-A BY WS-B GIVING WS-RES.
DIVIDE WS-A BY WS-B GIVING WS-RES REMAINDER WS-REM.
COMPUTE — expressões
COMPUTE WS-RES = WS-A + WS-B - 5.
COMPUTE WS-MEDIA = (WS-N1 + WS-N2 + WS-N3) / 3.
COMPUTE WS-IVA = WS-PRECO * 0.23.
COMPUTE WS-TOTAL = WS-PRECO + WS-IVA.
COMPUTE é mais legível para fórmulas. Suporta +, -, *, /, ** (exponenciação).
ACCEPT e DISPLAY
DISPLAY "Nome: ".
ACCEPT WS-NOME.
DISPLAY "Idade: ".
ACCEPT WS-IDADE.
DISPLAY "Olá " WS-NOME ", " WS-IDADE " anos".
* Múltiplas linhas com separadores
DISPLAY "Nome: " WS-NOME
"Idade: " WS-IDADE
"Salário: " WS-SALARIO.
6. Estruturas de controlo
IF / ELSE
IF WS-IDADE >= 18
DISPLAY "Adulto"
ELSE
DISPLAY "Menor"
END-IF.
* Condições compostas
IF WS-NOTA >= 10 AND WS-PRESENCAS >= 60
DISPLAY "Aprovado"
ELSE
DISPLAY "Reprovado"
END-IF.
* Se / senão se aninhado
IF WS-NOTA >= 18
DISPLAY "Excelente"
ELSE
IF WS-NOTA >= 14
DISPLAY "Bom"
ELSE
IF WS-NOTA >= 10
DISPLAY "Suficiente"
ELSE
DISPLAY "Reprovado"
END-IF
END-IF
END-IF.
Comparações: =, >, <, >=, <=, NOT =. Lógicas: AND, OR, NOT.
EVALUATE (switch)
EVALUATE WS-DIA
WHEN 1 THRU 5
DISPLAY "Dia útil"
WHEN 6
DISPLAY "Sábado"
WHEN 7
DISPLAY "Domingo"
WHEN OTHER
DISPLAY "Inválido"
END-EVALUATE.
* Múltiplos critérios
EVALUATE WS-ESTADO ALSO WS-IDADE
WHEN "A" ALSO 0 THRU 17
DISPLAY "Activo, menor"
WHEN "A" ALSO 18 THRU 64
DISPLAY "Activo, adulto"
WHEN OTHER
DISPLAY "Outro"
END-EVALUATE.
PERFORM — chamar paragraph
PROCEDURE DIVISION.
MAIN.
PERFORM INICIALIZAR.
PERFORM PROCESSAR.
PERFORM FINALIZAR.
STOP RUN.
INICIALIZAR.
DISPLAY "Início".
MOVE 0 TO WS-CONTADOR.
PROCESSAR.
DISPLAY "A processar...".
FINALIZAR.
DISPLAY "Fim".
PERFORM N TIMES
PERFORM 10 TIMES
DISPLAY "Olá"
END-PERFORM.
PERFORM UNTIL
MOVE 1 TO WS-I.
PERFORM UNTIL WS-I > 10
DISPLAY WS-I
ADD 1 TO WS-I
END-PERFORM.
PERFORM VARYING (for loop)
PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > 10
DISPLAY WS-I
END-PERFORM.
* Decremento
PERFORM VARYING WS-I FROM 10 BY -1 UNTIL WS-I < 1
DISPLAY WS-I
END-PERFORM.
* Aninhado
PERFORM VARYING WS-I FROM 1 BY 1 UNTIL WS-I > 3
PERFORM VARYING WS-J FROM 1 BY 1 UNTIL WS-J > 3
DISPLAY WS-I "," WS-J
END-PERFORM
END-PERFORM.
7. Ficheiros sequenciais
Setup do ficheiro
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT CLIENTES-FILE
ASSIGN TO "clientes.dat"
ORGANIZATION IS LINE SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD CLIENTES-FILE.
01 CLIENTE-REC.
05 CLI-NOME PIC X(30).
05 CLI-IDADE PIC 9(3).
05 CLI-SALARIO PIC 9(7)V99.
LINE SEQUENTIAL = ficheiro de texto (uma linha por record).
SEQUENTIAL = ficheiro binário (records de tamanho fixo).
Ler ficheiro
WORKING-STORAGE SECTION.
01 WS-EOF PIC X VALUE "N".
PROCEDURE DIVISION.
OPEN INPUT CLIENTES-FILE.
PERFORM UNTIL WS-EOF = "Y"
READ CLIENTES-FILE
AT END
MOVE "Y" TO WS-EOF
NOT AT END
DISPLAY CLI-NOME ", " CLI-IDADE
END-READ
END-PERFORM.
CLOSE CLIENTES-FILE.
STOP RUN.
Escrever ficheiro
OPEN OUTPUT CLIENTES-FILE.
MOVE "Ana Silva" TO CLI-NOME.
MOVE 25 TO CLI-IDADE.
MOVE 1500.00 TO CLI-SALARIO.
WRITE CLIENTE-REC.
MOVE "Bruno Costa" TO CLI-NOME.
MOVE 32 TO CLI-IDADE.
MOVE 2200.00 TO CLI-SALARIO.
WRITE CLIENTE-REC.
CLOSE CLIENTES-FILE.
Modos de abertura
INPUT— só leitura.OUTPUT— escrita (sobrescreve).EXTEND— append.I-O— leitura + escrita.
Ficheiros indexados (KSDS)
Para acesso por chave (como dicionário):
SELECT CLIENTES-FILE
ASSIGN TO "clientes.idx"
ORGANIZATION IS INDEXED
ACCESS MODE IS DYNAMIC
RECORD KEY IS CLI-ID.
* READ direct por chave:
MOVE 12345 TO CLI-ID.
READ CLIENTES-FILE
INVALID KEY
DISPLAY "Não encontrado"
NOT INVALID KEY
DISPLAY CLI-NOME
END-READ.
8. Subprograms
Subprogram
SOMA.cob:
IDENTIFICATION DIVISION.
PROGRAM-ID. SOMA.
DATA DIVISION.
LINKAGE SECTION.
01 LK-A PIC 9(5).
01 LK-B PIC 9(5).
01 LK-RES PIC 9(6).
PROCEDURE DIVISION USING LK-A LK-B LK-RES.
COMPUTE LK-RES = LK-A + LK-B.
GOBACK.
Programa principal
MAIN.cob:
IDENTIFICATION DIVISION.
PROGRAM-ID. MAIN-PROG.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-X PIC 9(5) VALUE 100.
01 WS-Y PIC 9(5) VALUE 250.
01 WS-RES PIC 9(6).
PROCEDURE DIVISION.
CALL "SOMA" USING WS-X WS-Y WS-RES.
DISPLAY "Resultado: " WS-RES.
STOP RUN.
Compilar e correr:
cobc -m soma.cob # módulo (.so / .dll)
cobc -x main.cob -o main
./main
BY REFERENCE vs BY VALUE vs BY CONTENT
CALL "SOMA" USING BY REFERENCE WS-X * default — modificável
BY VALUE WS-Y * só leitura
BY CONTENT WS-Z * cópia, modificável dentro
9. Boas práticas
Convenções
- MAIÚSCULAS em código (convenção forte).
- Prefix
WS-em working-storage. - Prefix por record (
CLI-,EMP-,PED-). - Paragraph names verbosos:
PROCESSAR-CLIENTE,LER-FICHEIRO-VENDAS. - Comentários generosos — código COBOL legacy é difícil de ler.
Estilo
* ─────────────────────────────────────────────
* Paragraph: PROCESSAR-VENDA
* Função: Calcula totais e aplica IVA
* Inputs: WS-VENDA-BRUTO
* Outputs: WS-VENDA-LIQUIDO
* ─────────────────────────────────────────────
PROCESSAR-VENDA.
COMPUTE WS-IVA = WS-VENDA-BRUTO * 0.23.
COMPUTE WS-VENDA-LIQUIDO = WS-VENDA-BRUTO + WS-IVA.
Anti-patterns
GO TO— evita (causa "spaghetti code"; raro em COBOL moderno).- Paragraphs gigantes (200+ linhas) — divide.
- Variáveis com nomes genéricos (
WS-A,WS-X). - Esquecer
END-IF,END-PERFORM,END-EVALUATE— não-terminator é legacy mas perigoso.
10. Mainframe na prática
Stack típica IBM
- z/OS: sistema operativo.
- CICS: transaction processor (interactivo).
- IMS: hierarchical database / TP monitor.
- DB2: relational DB.
- VSAM: ficheiros indexados nativos.
- JCL: Job Control Language (lança jobs batch).
JCL exemplo
//MYJOB JOB (ACCT),'PROCESS DAILY',MSGCLASS=X
//STEP1 EXEC PGM=COBPROG
//STEPLIB DD DSN=MY.LOADLIB,DISP=SHR
//INFILE DD DSN=MY.INPUT.DATA,DISP=SHR
//OUTFILE DD DSN=MY.OUTPUT.DATA,DISP=(NEW,CATLG,DELETE),
// SPACE=(CYL,(10,5)),DCB=(RECFM=FB,LRECL=80)
//SYSOUT DD SYSOUT=*
COBOL + DB2 (embedded SQL)
EXEC SQL
SELECT NOME, SALARIO
INTO :WS-NOME, :WS-SALARIO
FROM EMPREGADOS
WHERE ID = :WS-ID
END-EXEC.
: prefixa variáveis COBOL no SQL. Pré-processador converte para CALL adequado.
COBOL + CICS
EXEC CICS
RECEIVE MAP("MAPA1")
MAPSET("MAPSET1")
END-EXEC.
EXEC CICS
SEND MAP("MAPA2")
MAPSET("MAPSET1")
END
END-EXEC.
11. Modernização
COBOL não está estagnado:
- Object-COBOL (COBOL 2002+): classes, herança, interfaces.
- Cloud COBOL: Micro Focus na AWS, IBM Cloud Pak for Applications.
- COBOL → Java/C# transpiler: alguns bancos migrando.
- Reverse engineering tools: documentar e modernizar codebases legacy.
A maioria do código continua COBOL clássico. Aprender o velho é mais útil que o novo, para mercado de trabalho.
12. Próximos passos
- JCL — Job Control Language para mainframes.
- DB2 ou IMS — bases de dados em mainframe.
- CICS — processamento transaccional.
- REXX — scripting em mainframes.
- Stored procedures DB2.
- z/OS basics.
Glossário
- JCL: Job Control Language, lança jobs batch em mainframe.
- CICS: Customer Information Control System, transaction processor.
- DB2: relational DB da IBM, dominante em mainframe.
- VSAM: Virtual Storage Access Method, ficheiros indexados.
- PICTURE / PIC: define tipo e formato de variável.
- PERFORM: chama paragraph ou faz loop.
- WORKING-STORAGE: secção de variáveis do programa.
- FILE SECTION: estruturas dos ficheiros usados.
- LINKAGE SECTION: parâmetros recebidos de subprogram.
- GOBACK: fim de subprogram, volta ao caller.
- STOP RUN: termina o programa principal.
Recursos
- GnuCOBOL Manual: gnucobol.sourceforge.io.
- "Murach's Mainframe COBOL" — livro de referência.
- IBM Z Xplore — curso gratuito IBM (com mainframe real).
- OpenMainframeProject — comunidade.
- COBOL on YouTube: COBOLcurmudgeon, Open Mainframe Project.
COBOL não é "sexy" mas é dinheiro. Aprender COBOL aos 20 anos significa salário acima da média até à reforma. As empresas que dependem disto não conseguem encontrar pessoas. Se a parte técnica não te assusta (sintaxe arcaica, formatação rígida, falta de features modernas), é uma carreira sólida.