Executando verificação de segurança...
10

[CENTS PELO CHAO] VELHARIA: CODIGOS EM COBOL, DATAFLEX e CLIPPER (e nao se apegue a sua stack atual)

Meus 2 cents:

Remexendo em diretorios antigos a procura de um arquivo, acabei me deparando com alguns backups de sistemas a muito esquecidos.

Sao de sistemas coorporativos da decada de 80/90 e em linguagens antigas.

Por diversao, selecionei alguns trechos para representar a velharia encontrada - entao acomode-se em volta da fogueira e vamos falar sobre equipamentos e linguagens de uma era onde dinossauros ainda pastavam por estas paragens.

Os em COBOL e DATAFLEX eram executados em supermicros da EDISA ED680 / SID SMX 300 (UNIX SYSTEM V) atraves de terminais seriais (VT100/VT200) de fosforo verde.

Ja o em CLIPPER rodava em um PCs comuns (provavelmente 386DX ou 486DX)

As datas no titulo de cada linguagem eh o periodo aproximado onde aquele codigo rodou.

No final tem um fechamento sobre o assunto.


COBOL, cerca de 88/91

Este rodava em um equipamento SID 3900, um supermini (eram equipamentos inspirados em mainframes mas bem mais baratos) - o equivalente em termos de nicho seriam os servidores DELL Poweredge R6XX/R7XX atuais. Na epoca (anos 80) tinhamos a reserva de informatica, entao o padrao eram equipamentos fabricados no Brasil (importar era bem complicado, quando nao impossivel).

Este SID era composto de 3 modulos:

  • O de processamento e comunicacao, do tamanho de uma geladeira duplex grande

https://en.wikipedia.org/wiki/Superminicomputer

  • O de armazenamento (o disk pack), do tamanho de uma maquina de lavar grande (mas dava para trocar os 'packs', onde cada 'pack' - do tamanho de uma pizza gigante - armazenava 1Mb)

https://en.wikipedia.org/wiki/Disk_pack
https://en.wikipedia.org/wiki/History_of_IBM_magnetic_disk_drives#IBM_1311

  • O de armazenamento/transporte/backup, uma unidade de fita, tambem do tamanho de uma geladeira duplex - Usavamos como hoje se usa um pendrive, para gravar dados e levar para outros locais (p.ex. envio de dados para o governo, como a RAIS).

https://en.wikipedia.org/wiki/9-track_tape

O PROGRAMA

IDENTIFICATION DIVISION.
PROGRAM-ID.    MP003.
AUTHOR.        CPD.
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SPECIAL-NAMES.
   DECIMAL-POINT IS COMMA.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
   SELECT INDMAT ASSIGN TO DISK
          ORGANIZATION  IS INDEXED
          ACCESS  MODE  IS DYNAMIC
          RECORD  KEY   IS CHAMA.
   SELECT RELATO ASSIGN TO PRINTER.
   SELECT INDFOR ASSIGN TO DISK
          ORGANIZATION  IS INDEXED
          ACCESS  MODE  IS DYNAMIC
          RECORD  KEY   IS CHAFOR.
   SELECT INDREQ ASSIGN TO DISK
          ORGANIZATION  IS INDEXED
          ACCESS  MODE  IS DYNAMIC
          RECORD  KEY   IS CHAREQ.
   SELECT ARQSOR ASSIGN TO DISK
          ORGANIZATION  IS SEQUENTIAL.
   SELECT CADPRE ASSIGN TO DISK
          ORGANIZATION  IS INDEXED
          ACCESS  MODE  IS DYNAMIC
          RECORD  KEY   IS CHAPRE.
   SELECT CADMREQ ASSIGN TO DISK
          ORGANIZATION  IS INDEXED
          ACCESS  MODE  IS DYNAMIC
          RECORD  KEY   IS CHANREQ.
DATA DIVISION.
FILE SECTION.
*
COPY "/fontes/INDMAT.BOK".
FD  INDFOR
   LABEL RECORD IS STANDARD
   RECORD CONTAINS 164 CHARACTERS
   VALUE OF FILE-ID IS "INDFOR.MAT".
01  REGFOR.
   02 CHAFOR      PIC 9(05).
   02 NOMFOR      PIC X(30).
   02 DADFOR.
      03 ENDFOR      PIC X(30).
      03 CIDFOR      PIC X(20).
      03 UFFOR       PIC X(02).
      03 CEPFOR      PIC 9(05).
      03 CGCFOR      PIC 9(14) COMP-3.
      03 INSFOR      PIC 9(12) COMP-3.
      03 TELFOR      PIC 9(07) COMP-3.
      03 CCFOR       PIC 9(04).
      03 VALTRA      PIC 9(11)V99 COMP-3.
      03 VALTRAN     PIC 9(11)V99 COMP-3.
      03 FILLER      PIC X(15).
FD  RELATO
   LABEL RECORD  IS  OMITTED
   VALUE OF FILE-ID IS "/dev/pct27".
01  REG-IMP             PIC X(82).
WORKING-STORAGE SECTION.
01  CONF                PIC X(01) VALUE SPACES.
01  WFORN               PIC 9(05) VALUE ZEROS.
01  WCHAM               PIC 9(05) VALUE ZEROS.
01  WERR1               PIC X(01) VALUE SPACES.
01  CONTP               PIC 9(03) VALUE ZEROS.
01  CONTL               PIC 9(02) VALUE 62.
01  WCHA.
   02 CHAX             PIC 9(05) VALUE ZEROS.
01  CAB1.
   02 FILLER           PIC X(16) VALUE "CPD - EMITIU EM ".
   02 DIALP            PIC 9(02).
   02 FILLER           PIC X(01) VALUE "/".
   02 MESLP            PIC 9(02).
   02 FILLER           PIC X(01) VALUE "/".
   02 ANOLP            PIC 9(02).
   02 FILLER           PIC X(08) VALUE SPACES.
   02 FILLER           PIC X(32) VALUE
   "MP-003  DEMONSTRATIVO DE COMPRAS".
   02 FILLER           PIC X(08) VALUE SPACES.
   02 FILLER          PIC X(05) VALUE "PAG: ".
   02 PG-CB            PIC ZZZ.
   02 FILLER           PIC X(02) VALUE SPACES.
01  CAB2.
   02 FILLER           PIC X(42) VALUE SPACES.
   02 FILLER           PIC X(19) VALUE
   "MATERIAL/FORNECEDOR".
   02 FILLER           PIC X(21) VALUE SPACES.
*
SCREEN SECTION.
COPY "/fontes/TELMAT.BOK".
td TELA1.
   01 lin 04.
      02 col 15 pc x(38) va "** DEMONSTRATIVO DE COMPRAS (MATERIAL/" inverted.
      02 col 54 pc x(14) va "FORNECEDOR) * * " inverted.
PROCEDURE DIVISION.
INICIO.
   clear screen
   show TELA
   show TELA1.
   posit 04 70
   display "IMPRESSAO".
INIC1.
   posit 10 10
   display
    "DATA DA SEMANA :       A      ".
   posit 10 27
   accept DATA-A.
      IF DIA-A < 01 OR DIA-A > 31 PERFORM MENSA GO TO INICIO.
      IF MES-A < 01 OR MES-A > 12 PERFORM MENSA GO TO INICIO.
   posit 10 36
   accept DATA-B.
      IF DIA-B < 01 OR DIA-B > 31 PERFORM MENSA GO TO INICIO.
      IF MES-B < 01 OR MES-B > 12 PERFORM MENSA GO TO INICIO.
INIC2.
   posit 23 14
   display
      "CONFIRME  S=SIM / N=NAO:  ".
   posit 23 39
   accept CONF.
IF CONF = "N"    STOP RUN.
   IF CONF NOT = "S" GO TO INIC2.
   MOVE DATA-A TO DATA-X DATENT
   MOVE DATA-B TO DATA-Y DATSAI.
INIC3.
   OPEN INPUT INDREQ CADPRE CADMREQ.
   OPEN OUTPUT ARQSOR.
   accept DATA-I from DATE.
   MOVE MES-I TO MESLP.
   MOVE   DIA-I  TO DIALP.   MOVE ANO-I TO ANOLP.
   MOVE   DIA-A  TO DIALP1.  MOVE MES-A TO MESLP1.
   MOVE   DIA-B  TO DIALP2.  MOVE MES-B TO MESLP2.
   MOVE  62  TO  CONTL. MOVE ZEROS TO CONTP.
INIC4.
   READ INDREQ NEXT AT END CLOSE INDREQ ARQSOR CADPRE
   CADMREQ GO TO INIC5.
   MOVE DATQ TO DATAZ.  MOVE DIAZ TO DIAW.
   MOVE MESZ TO MESW.   MOVE SOLQ TO WCHA.
   MOVE WCHA TO CHANREQ. READ CADMREQ INVALID KEY
   posit 20 10
   display CHANREQ
   accept WERR1
GO TO INIC4.
   IF DATA-X NOT = DTADE OR DATA-Y NOT = DTAA GO TO INIC4.
   IF PUNQ     = ZEROS AND FORQ = 00035 GO TO INIC44.
   IF PUNQ NOT = ZEROS GO TO INIC44.
   MOVE MATQ  TO  MATPRE.  MOVE FORQ  TO  FORPRE.
   READ CADPRE INVALID KEY
   posit 20 10
   display MATPRE
   posit 20 20
   display FORPRE
   accept WERR1
   GO TO INIC4.
INIC44.
   MOVE MATQ  TO  MATSOR.  MOVE FORQ  TO  FORSOR.
   MOVE DATAW TO  DATSOR.  MOVE QTDQ  TO  QTDSOR.
   IF PUNQ =  ZEROS AND FORQ = 00035  MOVE ZEROS TO
   WVALOR     GO TO INIC45.
   IF PUNQ =  ZEROS MOVE PREUN TO WVALOR
   ELSE
   MOVE PUNQ  TO  WVALOR.
   COMPUTE WVALOR = WVALOR * QTDQ.
INIC45.
   MOVE WVALOR  TO  VALSOR. WRITE REGSOR. GO TO INIC4.
INIC5.
   posit 16 04. display "** AGUARDE A CLASSIFICACAO * * "
   EXEC "sgrsort -o CADSOR @0 +10 CADSOR".
   clear line 16
   OPEN INPUT ARQSOR INDFOR INDMAT.
   OPEN OUTPUT RELATO.
INIC6.
   READ ARQSOR AT END CLOSE ARQSOR INDFOR INDMAT RELATO
EXEC "rm CADSOR"
STOP RUN.
   MOVE MATSOR TO MAT-ANT.  MOVE FORSOR TO FOR-ANT.
   MOVE  1  TO  TIPO.
   PERFORM CABECA  GO TO INIC8.
INIC7.
   READ ARQSOR AT END GO TO FIM.
   IF MATSOR NOT = MAT-ANT PERFORM QUE-MAT.
   IF FORSOR NOT = FOR-ANT PERFORM QUE-FOR.
   IF CONTL > 61  PERFORM CABECA.
INIC8.
   IF TIPO = ZEROS GO TO INIC9.
   MOVE MATSOR TO CHAMA.  READ INDMAT.
   MOVE CHAMA  TO WCHAM.
   MOVE WCHAM  TO COD04.  MOVE NOMEMA  TO MAT04.
   MOVE UMA    TO MED04.  MOVE ZEROS   TO TIPO.
   ADD 3 TO CONTL.
   WRITE REG-IMP FROM CAB4 AFTER 2 LINES.
   MOVE SPACES TO REG-IMP. WRITE REG-IMP AFTER 1 LINE.
INIC9.
   MOVE FORSOR  TO  CHAFOR.   READ INDFOR.
   ADD QTDSOR  TO  AC-QT-FOR.
   ADD QTDSOR  TO  TOT-QT-FOR.
   ADD VALSOR  TO  AC-VR-FOR.
   ADD VALSOR  TO  TOT-VR-FOR.
   GO TO INIC7.
QUE-FOR.
   IF CONTL > 55 PERFORM CABECA.
   MOVE CHAFOR  TO  WFORN.
   MOVE WFORN   TO  COD05.   MOVE NOMFOR  TO  FOR05.
   MOVE AC-QT-FOR  TO  QTD05.  MOVE AC-VR-FOR  TO  VL05.
   MOVE ZEROS  TO  AC-QT-FOR AC-VR-FOR. MOVE FORSOR TO FOR-ANT.
   ADD 1 TO CONTL.
   WRITE REG-IMP FROM CAB5 AFTER 1 LINE.
QUE-MAT.
   PERFORM QUE-FOR.
   MOVE TOT-QT-FOR  TO  TQTD.  MOVE TOT-VR-FOR  TO  TVL.
   ADD 1 TO CONTL.
   WRITE REG-IMP FROM CAB6 AFTER 1 LINE.
   MOVE ZEROS TO TOT-QT-FOR TOT-VR-FOR. MOVE 1 TO TIPO.
   MOVE MATSOR TO MAT-ANT. MOVE SPACES TO REG-IMP.
MENSA.
   posit 23 14
   display
   "DATA INVALIDA - TECLE ENTER".
   ALARM.
CABECA.
   MOVE ZEROS TO CONTL.  ADD 1 TO CONTP.
   MOVE CONTP TO PG-CB.
   WRITE REG-IMP FROM CAB1 AFTER PAGE.
   WRITE REG-IMP FROM CAB2 AFTER 1 LINE.
   WRITE REG-IMP FROM CAB3 AFTER 2 LINES.
   ADD 4 TO CONTL.
FIM.
PERFORM QUE-MAT.
   CLOSE ARQSOR INDFOR INDMAT RELATO.
EXEC "CADSOR".
STOP RUN.

DATAFLEX, cerca de 92/94

Este rodava em um equipamento SID SMX 300 - que era um supermicro, um parente bem mais proximo dos servidores atuais. Rodava um UNIX like, tinha HD interno (uns 128Mb creio) e fita de backup.

  • O equipamento em si lembra este aqui (nao achei foto dele, mas este IBM eh bem semelhante, o SID era um pouco mais alto e mais comprido)

https://www.computinghistory.org.uk/det/4805/IBM-RS-6000-Model-550L/

  • A fita de backup era semelhante a esta

https://en.wikipedia.org/wiki/Quarter-inch_cartridge

O PROGRAMA

/TELA
==============================================================================
|SVT002                   CADASTRO DE VALE TRANSPORTE                __/__/__|
==============================================================================

    REGISTRO : _______.        FILIAL : ___.       C/C : ___.

    NOME     : ______________________________

    TURNO    : _ (1 - SEG A SEX / 2 - SEG A SAB / 3 -  6 x 2 )

    EMPRESA 1   : ___.  ______________________________  MEIO : ___________
    QTDE P/ DIA : ___.  QTDE NO MES : ___.
    EMPRESA 2   : ___.  ______________________________  MEIO : ___________
    QTDE P/ DIA : ___.  QTDE NO MES : ___.

    VALOR TOTAL : _________.__         CODIGO REGIAO: __. ____________________
==============================================================================
|MENSAGEM: ______________________________ _                                  |
==============================================================================
/*
AUTOPAGE TELA
NAME JDATA
NAME JREGISTRO JFILIAL JCENTRO
NAME JNOME
NAME JTIPO
NAME JEMP1 JNEMP1 JMEIO1
NAME JQTD1 JQDD1
NAME JEMP2 JNEMP2 JMEIO2
NAME JQTD2 JQDD2
NAME JVRTOTAL JREGIAO JNREG
NAME JMENSAGEM JRESPOSTA
FORMAT JRESPOSTA {CAPSLOCK,CHECK='S/N'}

NUMBER VALOR VQTDG VEMP1 VEMP2
STRING JMEIO 1 JQUAL TIPO_OLD 1

OPEN ARQVT
OPEN ARQEMP
OPEN ARQFUNC
OPEN ARQREG
OPEN ARQUTI

FILE_MODE ARQEMP  READ_ONLY
FILE_MODE ARQUTI  READ_ONLY
FILE_MODE ARQREG  READ_ONLY

CLEAR ARQUTI
CLEAR ARQVT
CLEAR ARQEMP
CLEAR ARQFUNC
CLEAR ARQREG

PAGE TELA
KEYPROC ON

MOVE 1 TO ARQUTI.RECNUM
FIND EQ ARQUTI.RECNUM

REPEAT
CLEARFORM TELA
DISPLAY DATASYS TO JDATA

ENTERGROUP

ENTRA:

      ENTRY ARQVT.CODIGO_FUN_VT  JREGISTRO {AUTOFIND}
      CLEAR ARQFUNC
      MOVE JREGISTRO TO ARQFUNC.REGISTRO_FUN
      FIND EQ ARQFUNC.REGISTRO_FUN
      [ FINDERR ] GOTO ENTRA
      DISPLAY ARQFUNC.NOME_FUN TO JNOME
      DISPLAY ARQFUNC.TURNO_FUN TO JTIPO
      MOVE  ARQFUNC.COD_FILIAL_FUN  TO JFILIAL
      ENTRY ARQVT.CODIGO_FIL_VT  JFILIAL
      MOVE  ARQFUNC.COD_DEPTO_FUN TO JCENTRO
      ENTRY ARQVT.CENTRO_CUS_VT  JCENTRO
      MOVE  ARQFUNC.TURNO_FUN TO TIPO_OLD
      ENTRY ARQFUNC.TURNO_FUN JTIPO
      IF JTIPO EQ '1' MOVE ARQUTI.SEG_SEX_UTI TO VQTDG
      ELSE
         IF JTIPO EQ '2' MOVE ARQUTI.SEG_SAB_UTI TO VQTDG
         ELSE
            IF JTIPO EQ '3' MOVE ARQUTI.SIX_TWO_UTI TO VQTDG

EMP1:
      ENTRY ARQVT.COD_EMP_1_VT   JEMP1
      CLEAR ARQEMP
      MOVE JEMP1 TO ARQEMP.CODIGO_EMP
      FIND EQ ARQEMP.CODIGO_EMP
      [ FINDERR ] GOTO EMP1

      DISPLAY ARQEMP.NOME_EMP TO JNEMP1
      ENTRY ARQVT.QTDE_VT_1_VT JQTD1
      IF JQTD1 EQ 0 GOTO EMP1
      MOVE ARQEMP.PR_UN_EMP TO VEMP1
      CALC (JQTD1*VQTDG) TO JQDD1
      MOVE JQDD1 TO ARQVT.QTDE_MES_1_VT
      MOVE ARQEMP.TIPO_TRANS_EMP TO JMEIO
      IF JMEIO EQ '1' MOVE 'RODOVIARIO' TO JQUAL
      ELSE
         IF JMEIO EQ '2' MOVE 'METROVIARIO' TO JQUAL
         ELSE
            IF JMEIO EQ '3' MOVE 'FERROVIARIO' TO JQUAL
            ELSE
               IF JMEIO EQ '4' MOVE 'MARITMO' TO JMEIO1
      DISPLAY JQUAL TO JMEIO1

      CALC (JQDD1*VEMP1) TO VALOR
      CALC ((JQDD2*VEMP2)+VALOR) TO VALOR

      MOVE VALOR TO JVRTOTAL
      ENTRY ARQVT.VALOR_PAGO_VT  JVRTOTAL

REG:
      ENTRY ARQVT.COD_REGIAO_VT  JREGIAO
      CLEAR ARQREG
      MOVE JREGIAO TO ARQREG.CODIGO_REGIAO
      FIND EQ ARQREG.CODIGO_REGIAO
      DISPLAY ARQREG.NOME_REGIAO  TO JNREG
      REREAD

ENDGROUP

GOSUB CONFIRMA
IF JRESPOSTA EQ 'S' BEGIN
   MOVE JQDD1 TO ARQVT.QTDE_MES_1_VT
   MOVE JQDD2 TO ARQVT.QTDE_MES_2_VT
   move datasys to arqvt.data_alt_vt
   SAVERECORD ARQVT
   IF JTIPO NE TIPO_OLD SAVERECORD ARQFUNC
END

UNLOCK
CLEAR ARQVT
CLEAR ARQFUNC
CLEAR ARQEMP
LOOP

CONFIRMA:
    DISPLAY 'DADOS CORRETOS? (S/N)' TO JMENSAGEM
    MOVE 'S' TO JRESPOSTA
    ACCEPT JRESPOSTA
    RETURN

KEYPROC KEY.SAVE
        move datasys to arqvt.data_alt_vt
        saverecord arqvt
        clearform jregistro thru jresposta
        return entra

CLIPPER 5.2, cerca de 92/94

Este ja rodava em micro comuns - provavelmente 386DX, 486DX e talvez nos primeiros "pentium". O padrao ainda era tela de texto com 80 colunas x 24 linhas, mas telas graficas com CGA/EGA e posteriormente VGA, rodando eventualmente o Windows 3.11 nao era incomum - e com o windows 95 batendo as portas.

O CLIPPER rodava em DOS - mesmo quando no Windos 95 abria-se a tela DOS (o CMD ainda existente no Windows 11).

Com a introducao do Windos 95 e a GUI, os 'CLIPPEIROS' comecaram a migrar para outras linguagens como o VISUAL FOXPRO, mas foi o DELPHI que acabou dominando o cenario para desenvolvimento DESKTOP. A Web ainda era basicamente HTML + CGI, nao tinha substancia o bastante para fazer sistemas nela.

O PROGRAMA

Function pedfor()
local cTit := 'Faz o Pedido para Fornecedores'
privat getlist := {}
privat numero, codfor, data, import, regped, obs1
WinDados(cTit)

sele PEDFOR

@ 01,03 say 'Pedido'
@ 03,03 say 'Fornecedor'
@ 05,03 say 'Data'
@ 07,03 say 'Import Via'
@ 09,03 say 'Reg.Pedidos'
@ 11,03 say 'Observacao'

while TRUE
    copy fields blank to memory
    @ 01, 14 get m->numero pict '@!'         valid leitura(PEDFOR,m->numero)
    @ 03, 14 get m->codfor pict '@re 99,999' valid existe(FORNECEDORES,m->codfor,03,23,{|| field->razao_soc })
    @ 05, 14 get m->data                     when default(@data,date())
    @ 07, 14 get m->import pict '@r 99'      valid existe(IMPORT,m->import,07,20,{|| field->importvia })
    @ 09, 14 get m->regped pict '@r 99'      valid existe(REGPED,m->regped,09,20,{|| field->regped })
    @ 11, 14 get m->obs1
    read
    ESC_EXIT
    Grava(PEDFOR,2)
    EntraItens(PEDXFOR,m->numero,LIVROS)

    sele PEDFOR
end
fecha()
return NIL

******************************
Function EntraItens(nAreaPri,cChavePri,nAreaSec)
Local nJanela, nInicial, bTela, bGets, bTit, nTemp, nTelas, cIsbn, cTitulo

privat getlist := {}

privat pedido, item, codlivro, quantidade, invoice, datainv, datarec, naviso, oaviso, preco

privat aItens, nItens

nJanela  := 1
nInicial := Wselect()+1
m->aItens   := {}
m->nItens   := 0
nTelas   := 0

bTela := { |x| TelaItens(x) }
bGets := { |x,y| GetItens(x,y) }
bTit  := { |x| TitItens(x) }

sele (nAreaPri)

Set SoftSeek On
seek (cChavePri)
Set SoftSeek Off

whil !eof() .and. (nAreaPri)->pedido == cChavePri
    if  procura(LIVROS,(nAreaPri)->codlivro,2)
        cIsbn   := LIVROS->isbn
        cTitulo := LIVROS->titulo
    else
        loop
    end
    aadd(m->aItens,cIsbn)
    aadd(m->aItens,(nAreaPri)->item)
    aadd(m->aItens,(nAreaPri)->codlivro)
    aadd(m->aItens,cTitulo)
    aadd(m->aItens,(nAreaPri)->invoice)
    aadd(m->aItens,(nAreaPri)->datainv)
    aadd(m->aItens,(nAreaPri)->naviso)
    aadd(m->aItens,(nAreaPri)->datarec)
    aadd(m->aItens,(nAreaPri)->oaviso)
    aadd(m->aItens,(nAreaPri)->preco)
    aadd(m->aItens,(nAreaPri)->quantidade)
    skip
    nTelas++
end

if  (nTelas == 0)

    eval ( bTela, nInicial )
    eval ( bGets, nAreaPri, nInicial )

else

    for nTemp := 1 to nTelas

        nJanela++

        eval ( bTela, nInicial )

        DevPos( 00, 00 ) ; DevOut( "I S B N" )
        DevPos( 00, 26 ) ; DevOut( "Item" )
        DevPos( 00, 41 ) ; DevOut( "Cod. Livro" )
        DevPos( 01, 00 ) ; DevOut( "Titulo" )
        DevPos( 02, 00 ) ; DevOut( "Invoice" )
        DevPos( 02, 35 ) ; DevOut( "Data da Invoice" )
        DevPos( 03, 00 ) ; DevOut( "Aviso" )
        DevPos( 03, 35 ) ; DevOut( "Data Rec." )
        DevPos( 05, 00 ) ; DevOut( "Preco" )
        DevPos( 05, 35 ) ; DevOut( "Quantidade" )

        m->nItens++
        SetPos( 00, 09 ) ; AAdd( GetList, _GET_( m->aItens[m->nItens], "m->aItens[m->nItens]",, {| oObjGet | AssociaObj(LIVROS,{ || field->codlivr }, 2, oObjget ), AssociaObj(LIVROS,{ || field->titulo }, 3, oObjget )  } , ) )
        Atail(GetList):cargo := m->nItens
        m->nItens++
        SetPos( 05, 56 ) ; AAdd( GetList, _GET_( m->aItens[m->nItens], "m->aItens[m->nItens]", "@r 999",, ) )

    next

end

if  !(nJanela == 1)
    WSelect(nInicial)
     eval( btit, nInicial )
end

ReadEspecial(GetList,nInicial,bTela,bGets,bTit,00,05,11,nAreaPri);getlist := {}

if UpDated()

    for nTemp := 1 to m->nItens step 11

        m->item         := aItens[nTemp+01]

        if  !empty(m->quantidade)
            procura(nAreaPri,cChavePri+strzeros(m->item,2))
            if  eof()
                m->pedido       := cChavePri
                m->item         := aItens[nTemp+01]
                Grava(nAreaPri,2)
            end
        end
    next nTemp
end
return NIL

***************************************************
Function AssociaObj( nArea, bCampo, nDestino, oGet)
Local nOldArea := select(), lRet := FALSE
sele (nArea)
seek (m->aItens[oGet:cargo])
if  !(eof())
    m->aItens[oGet:cargo+nDestino] := eval( bCampo )
end
lRet := !(eof())
sele (nOldArea)
return lRet

CONCLUSAO

Estas nao foram as unicas linguagens que utilizei ao longo dos anos - das "esotericas" de cabeca lembro:

Tem mutas outras, mas no fundo nao importa muito.

Atualmente uso PHP, python e React/Next.js nos sistemas do dia-a-dia (e C quando preciso falar com dispositivos IoT).

Mas o que quero registrar eh o seguinte: as vezes ficamos preocupados com a stack que usamos, se eh o ideal, se tem mercado, etc.

Logico que precisa-se ficar atento ao mercado para nao ficar obsoleto - mas sem tanto stress.

Se voce leu os programas que mostrei - vai notar que de um modo geral eles sao legiveis, mesmo sendo de linguagens com 30 anos ou mais.

Como diz o @maniero, se voce aprendeu os fundamentos eh provavel que vai conseguir seguir a vida de dev sem maiores problemas.

Por exemplo o low-code / no-code que estao tao na moda, ainda precisam de quem entenda de algoritmos e regras de negocio para faze-los funcionar bem - isso nao mudou e eh improvavel que mude muito.

Enfim - mantenha a cabeca aberta a oportunidades e nao se apegue muito a sua stack atual: ela provavelmente morrera ou se tornara irrelevante dentro de no maximo 10 anos - e se o rei esta morto, viva o rei !

Carregando publicação patrocinada...
1

Todo mundo ama falar de inovação, mas poucos lembram quem segurou as pontas no começo.
Essas "velharias" que hoje parecem ultrapassadas foram a base de muita coisa que ainda roda por aí — inclusive onde menos se espera.

Será que a stack que você ama hoje vai sobreviver aos próximos 10 anos? Ou vai virar arqueologia digital também?

1
1

Pode discorrer mais sobre isso? De fato COBOL costuma ter implementações mais rápidas que muita coisa por aí e tem instruções que ajudam fazer coisas que muita linguagem não é capaz em termos de otimização, mas queria saber mais sobre esse foco.

1

Muito bom, eu ainda brinco com clipper por aqui hahahaha, na verdade com Harbour .
Dias atrás recebi um contato de uma vaga que tava pagando 8k para trabalhar com essa lang, mas como não domino completamente eu passei para um dinossauro amigo meu.
É aquele lance, o importante é se a lang ainda paga as contas.

1

Bacana ter postado isso e as dicas finais para os iniciantes.

Foi você que fez? Me desculpe, mas seria bom deixar claro para as outras pessoas, e não posso dizer que esses códigos são os piores que já, porque vi muita coisa grotesca e eu mesmo cometi vários dos erros que vi aí em cima no começo também, não nasci gênio, eu melhorei me dedicando muito e com gana de evoluir sempre, mas esses códigos são bem mal-feitos ;)

Algumas coisas não são tão legíveis e é até o um dos problemas de certos mecanismos, por exemplo o private que é totalmente desnecessário desde o Clipper 5 é uma das maiores aberrações da computação chamada de escopo dinâmico, mas amplamente adotado no "ERP" de maior faturamento do Brasil e o principal motivo de código dele ser uma das maiores bombas que existe, fora a parte fora do código que é pior. Eu falo mais sobre escopo dinâmico aqui: https://pt.stackoverflow.com/q/342846/101, agradeça todos os dias por nunca ter que trabalhar com isso (ele foi adotado em algo que era para ser só um scriptizinho em um banco de dados e virou feature de linguagem em grandes projetos, mais ou menos como aconteceu como o JavaScript e PHP, que possuem tipagem fraca, algo que o Clipper não tem.

Clipper ainda existe agora modernizado, o original é cheio de problemas.

S2


Farei algo que muitos pedem para aprender a programar corretamente, gratuitamente (não vendo nada, é retribuição na minha aposentadoria) (links aqui no perfil também).

1

Meus 2 cents:

Os codigos estao horriveis mesmo - mas tenho de fazer uma confissao: para caber na publicacao tive de retalhar varias partes, como tirar comentarios, funcoes, linhas, etc. Procurei deixar legivel para quem ver ter uma ideia de como funcionava.

O do Clipper em especial eh medonho - era de um ERP com algumas centenas de programas e um makefile linguica enorme - alem do fato dele ser da epoca da transicao do clipper padrao (que basicamente era a sintaxe do dbase e compilado) para uma transposicao tentando imitar o C e incorporar as primeiras ideias de programacao OOP. Junte isso a equipes enormes e total ausencia de sistemas de testes, qualidade, etc - a tempestade perfeita. Funcionava basicamente com durex e oracoes.

Nem coloquei porque nao cabia no contexto - mas tem codigo de aplicacoes feitos para Access e alguns para ASP que dao medo.