Translate

quarta-feira, 20 de julho de 2022

Criando Sua Própria Função Intrínseca no COBOL

 

Bellacosa Mainframe crie sua propria função intrinseca no Cobol Mainframe

☕ Um Café no Bellacosa Mainframe

Criando Sua Própria Função Intrínseca no COBOL

O Guia do Programador COBOL Padawan para Expandir os Poderes da Linguagem com a Ajuda do Capitão Kirk

"O universo não se expande porque alguém pediu permissão. Ele se expande porque alguém teve coragem de explorar o desconhecido."

— Capitão James T. Kirk (adaptado para Bellacosa Mainframe)


Introdução — "Mas... eu posso criar uma nova FUNCTION no COBOL?"

Essa é uma das perguntas que quase nenhum curso responde.

Durante décadas, programadores COBOL aprenderam algo parecido com isto:

  • FUNCTION CURRENT-DATE

  • FUNCTION UPPER-CASE

  • FUNCTION LOWER-CASE

  • FUNCTION LENGTH

  • FUNCTION RANDOM

E a conclusão natural era:

"Essas funções fazem parte da linguagem. Não posso criar outras."

Durante muitos anos isso realmente era verdade.

Mas a IBM resolveu mudar isso.

Hoje, no Enterprise COBOL moderno, você pode criar suas próprias funções, reutilizáveis exatamente como uma FUNCTION nativa da linguagem.

É quase como ensinar novos truques ao compilador.

Se você já trabalhou com:

  • Java (methods)

  • C (functions)

  • Python (def)

  • C# (methods)

vai perceber que finalmente o COBOL ganhou algo semelhante.

E a melhor parte?

Isso continua extremamente eficiente para ambientes bancários.

Hoje vamos descobrir como.

E, como sempre, o Capitão Kirk nos acompanhará nessa missão.


A ponte da Enterprise

Imagine a USS Enterprise.

Cada oficial possui uma especialidade.

Spock calcula.

Scotty cuida do motor.

McCoy resolve problemas médicos.

Kirk apenas chama quem precisa.

Ele não faz tudo.

Ele reutiliza especialistas.

Uma User-Defined Function faz exatamente isso.

Você cria um especialista.

Depois qualquer programa COBOL pode chamá-lo.


Antes disso...

Durante mais de 50 anos havia apenas dois caminhos.

Opção 1

Escrever código repetido.

CALCULA-JUROS.

CALCULA-DESCONTO.

CALCULA-IDADE.

Copiado dezenas de vezes.


Opção 2

Criar um subprograma

CALL "JUROS"

Funciona.

Mas possui custo.

Existe:

  • parameter list

  • linkage

  • transferência de controle

  • convenções de chamada

Embora eficiente, ainda existe overhead.


As User Defined Functions diminuem bastante esse problema.


O que é uma User-Defined Function?

É uma função escrita pelo próprio programador.

Ela recebe parâmetros.

Executa lógica.

Retorna um único valor.

Exemplo imaginário:

FUNCTION CALCULA-CPF()

ou

FUNCTION REMOVE-ESPACOS()

ou

FUNCTION SOMA-IMPOSTOS()

Ela parece uma função da linguagem.

Mas foi você quem escreveu.


Desde quando isso existe?

No mundo IBM Mainframe, o suporte chegou com o IBM Enterprise COBOL 5 (introduzido em 2013), quando a linguagem passou a incorporar recursos modernos alinhados aos padrões mais recentes do COBOL. As capacidades foram ampliadas e refinadas nas versões 6.1, 6.2, 6.3, 6.4 e 6.5, que hoje são as mais encontradas em ambientes z/OS corporativos.

Na prática, é nas versões Enterprise COBOL 5.x e, principalmente, 6.x que esse recurso se tornou realmente utilizável em projetos modernos.


Precisa instalar alguma coisa?

Boa notícia.

Não.

Nada.

Se o compilador suporta User-Defined Functions, elas já fazem parte do compilador.

Você apenas compila normalmente.

Não existe:

  • DLL

  • Plugin

  • Biblioteca externa


Como funciona?

A arquitetura é simples.

Programa A

↓

FUNCTION MINHA-FUNCTION()

↓

User Defined Function

↓

Retorna resultado

Muito parecido com isto:

resultado =
FUNCTION JUROS(valor)


Estrutura geral

Ela lembra um programa COBOL.

IDENTIFICATION DIVISION

FUNCTION-ID.

ENVIRONMENT DIVISION.

DATA DIVISION.

PROCEDURE DIVISION.

END FUNCTION.

Observe algo curioso.

Não usamos

PROGRAM-ID

Usamos

FUNCTION-ID

Esse é o detalhe que transforma um programa em uma função.


Exemplo 1

Dobrando um número

IDENTIFICATION DIVISION.
FUNCTION-ID. DOBRO.

DATA DIVISION.

LINKAGE SECTION.

01 L-VALOR PIC S9(9) COMP-5.

01 L-RETORNO PIC S9(9) COMP-5.

PROCEDURE DIVISION USING L-VALOR
                   RETURNING L-RETORNO.

    COMPUTE L-RETORNO = L-VALOR * 2

    GOBACK.

END FUNCTION DOBRO.

Bonito.

Limpo.

Pequeno.


Agora o programa principal.

DISPLAY FUNCTION DOBRO(15)

Saída

30

Muito elegante.


Exemplo 2

Maior entre dois números

FUNCTION MAIOR(A,B)

Dentro:

IF A > B
   MOVE A TO RETORNO
ELSE
   MOVE B TO RETORNO
END-IF

Depois:

DISPLAY FUNCTION MAIOR(25 19)

Resultado

25


Exemplo 3

Calcular idade

FUNCTION IDADE(DATA-NASCIMENTO)

Internamente:

CURRENT-DATE

Subtrai

Retorna idade.

Depois:

DISPLAY FUNCTION IDADE(19980412)

Muito mais legível.


Onde declarar parâmetros?

Na

LINKAGE SECTION

Exemplo

01 PARAM1.

01 PARAM2.

Depois

PROCEDURE DIVISION USING
PARAM1
PARAM2
RETURNING RESULTADO

Muito parecido com um subprograma.


Como chamar?

COMPUTE WS-TOTAL =
FUNCTION JUROS(1000 15)

Ou

MOVE FUNCTION DOBRO(5)
TO WS-VALOR

Ou

DISPLAY FUNCTION TEXTO()


Posso chamar outras FUNCTIONS?

Sim.

Inclusive funções intrínsecas.

FUNCTION UPPER-CASE()

Dentro da sua função.

Exemplo

FUNCTION UPPER-CASE(cliente)

Retorna

JOÃO


Posso chamar um CALL?

Também.

CALL "ROTINA"

Nada impede.

Mas cuidado.

Funções devem ser pequenas.


O Capitão Kirk explica

Imagine que Kirk pede um café.

Ele não desmonta o replicador.

Ele apenas diz:

CAFÉ()

O replicador faz todo o trabalho.

Isso é encapsulamento.


Performance

Excelente.

Muito melhor do que copiar código.

Muito melhor para manutenção.

Além disso:

✔ reutilização

✔ cache de instruções

✔ otimização do compilador

✔ menor duplicação


Um detalhe importante

Funções devem retornar UM único valor.

Não dez.

Se precisa retornar muitas estruturas:

Use

CALL

Não FUNCTION.


Posso acessar arquivos VSAM?

Tecnicamente pode.

Mas...

Não deveria.

Funções devem ser previsíveis.


Boa função:

CALCULA

Ruim:

ABRE VSAM

FAZ I/O

ATUALIZA DB2

ENVIA MQ


O perigo dos efeitos colaterais

Imagine:

FUNCTION SALDO()

Você espera apenas consultar.

Mas internamente:

UPDATE DB2

Isso é perigoso.

Uma função deve produzir sempre o mesmo resultado para a mesma entrada, sempre que possível.


Erros comuns

1 Repetir lógica

Ao invés de:

FUNCTION IMPOSTO()

o programador copia:

COMPUTE...

100 vezes.


2 Fazer função enorme

Ruim

900 linhas

Boa

20

40

60 linhas


3 Muitos parâmetros

FUNCTION CALCULA(
A
B
C
D
E
F
G
H)

Já virou um monstro.


4 Fazer I/O

Evite.


5 Alterar estado global

Funções devem ser independentes.


Truques interessantes

Criar biblioteca matemática

FUNCTION MEDIA()

FUNCTION DESVIO()

FUNCTION MEDIANA()


Biblioteca financeira

JUROS

IOF

IR

TAXA


Biblioteca bancária

VALIDA-CPF

VALIDA-CNPJ

MOD11

DIGITO


Biblioteca texto

REMOVE-ESPACOS

NORMALIZA

CAPITALIZA


Organização recomendada

COPYBOOKS

FUNCTIONS

SUBPROGRAMAS

PROGRAMAS

Cada função em seu próprio membro.

Muito semelhante à organização de uma biblioteca reutilizável.


Boas práticas

✔ Nomeie funções de forma descritiva (CALCULA-JUROS, VALIDA-CPF, NORMALIZA-NOME).

✔ Mantenha apenas uma responsabilidade por função.

✔ Evite acessar arquivos, filas MQ ou banco de dados dentro de funções de cálculo.

✔ Prefira funções determinísticas: mesma entrada, mesma saída.

✔ Documente parâmetros e tipo de retorno.

✔ Teste cada função de forma isolada antes de utilizá-la em produção.

✔ Centralize funções reutilizáveis em bibliotecas compartilhadas pela equipe.

✔ Utilize compilação otimizada nas versões atuais do Enterprise COBOL para aproveitar as melhorias do compilador.


Quando usar FUNCTION e quando usar CALL?

SituaçãoFUNCTIONCALL
Cálculos rápidos✅ Excelente✔ Possível
Manipulação de texto✅ Excelente✔ Possível
Validação de CPF/CNPJ✅ Ideal✔ Possível
Retornar um único valor✅ Melhor escolha✔ Possível
Atualizar Db2❌ Evite✅ Recomendado
Processar VSAM❌ Evite✅ Recomendado
Enviar mensagens MQ❌ Evite✅ Recomendado
Processamento complexo com vários retornos❌ Não indicado✅ Ideal

Um exemplo prático: função para calcular desconto

Imagine uma empresa que aplica um desconto de 10% sobre qualquer valor informado. Em vez de repetir o cálculo em dezenas de programas, criamos uma função reutilizável.

Função

IDENTIFICATION DIVISION.
FUNCTION-ID. CALC-DESCONTO.

DATA DIVISION.

LINKAGE SECTION.
01 LK-VALOR     PIC S9(7)V99 COMP-3.
01 LK-RETORNO   PIC S9(7)V99 COMP-3.

PROCEDURE DIVISION
    USING LK-VALOR
    RETURNING LK-RETORNO.

    COMPUTE LK-RETORNO =
        LK-VALOR * 0.90

    GOBACK.

END FUNCTION CALC-DESCONTO.

Programa chamador

IDENTIFICATION DIVISION.
PROGRAM-ID. TESTE.

DATA DIVISION.
WORKING-STORAGE SECTION.

01 WS-VALOR     PIC S9(7)V99 VALUE 1000.
01 WS-FINAL     PIC S9(7)V99.

PROCEDURE DIVISION.

    MOVE FUNCTION CALC-DESCONTO(WS-VALOR)
        TO WS-FINAL

    DISPLAY "Valor original : " WS-VALOR
    DISPLAY "Valor final    : " WS-FINAL

    STOP RUN.

Saída esperada:

Valor original : 1000.00
Valor final    :  900.00

Perceba como o programa principal permanece limpo. Toda a regra de negócio fica encapsulada em um único lugar. Se amanhã o desconto passar para 12%, basta recompilar a função.


A visão do Capitão Kirk

No final da missão, Kirk reúne sua tripulação na ponte da Enterprise.

Spock observa:

"Capitão, seria lógico repetir o mesmo algoritmo em 147 programas?"

Kirk sorri.

"Claro que não, Spock. Criamos uma função, compartilhamos conhecimento e seguimos explorando."

Scotty complementa:

"Quanto menos motores improvisados, menos explosões na sala de máquinas."

McCoy, olhando para um enorme programa COBOL cheio de código duplicado, comenta:

"Ele está vivo... mas não por muito tempo."

Essa é a verdadeira filosofia das User-Defined Functions: transformar conhecimento reutilizável em componentes pequenos, claros e confiáveis.

Cuidados e atenção 

Como compilar e ajustar sua função intrinseca no Cobol 6.4

https://eljefemidnightlunch.blogspot.com/2022/07/alerta-vermelho-na-enterprise.html

O que são Funções Intrincsecas no Cobol

https://eljefemidnightlunch.blogspot.com/2022/09/funcoes-intrinsecas-no-enterprise-cobol.html



Conclusão — Seu próximo passo como Padawan COBOL

As User-Defined Functions representam uma das evoluções mais elegantes do COBOL moderno. Elas aproximam a linguagem das práticas de engenharia de software utilizadas em linguagens contemporâneas, sem abrir mão da robustez que tornou o COBOL o alicerce de bancos, seguradoras e grandes empresas por décadas.

Para um Padawan COBOL, dominar esse recurso significa deixar de escrever programas monolíticos e começar a construir bibliotecas reutilizáveis de regras de negócio. Isso reduz duplicação de código, facilita testes, melhora a manutenção e torna o desenvolvimento muito mais organizado.

No universo Bellacosa Mainframe, criar uma nova função é como adicionar um novo oficial especializado à tripulação da USS Enterprise. Cada função tem uma missão específica, executa seu trabalho com excelência e permite que o programa principal permaneça simples, elegante e focado em coordenar a missão.

Porque, no fim das contas, os melhores sistemas corporativos não são aqueles que possuem mais linhas de código, mas aqueles em que cada componente conhece exatamente seu papel — assim como cada oficial da Frota Estelar conhece sua estação na ponte de comando.


Sem comentários:

Enviar um comentário