Su qualunque altra piattaforma il codice è un file in una cartella. Qui no, o almeno non
per tradizione: il codice sta dentro un file sorgente, che è un oggetto di tipo *FILE
in una libreria, e ogni programma è un membro di quel file.
Un file sorgente sta a un progetto come una cartella, ma è un oggetto del database. È il motivo per cui il sorgente si può interrogare in SQL, e anche per cui non ci si può mettere un nome lungo o una sottocartella.
I nomi che si incontrano
Per convenzione, un file sorgente per tipo di linguaggio:
| File | Contiene |
|---|---|
QRPGLESRC |
sorgenti RPG ILE e RPG con SQL incorporato |
QRPGSRC |
sorgenti RPG del vecchio modello, dove ci sono ancora |
QCLSRC |
sorgenti CL |
QDDSSRC |
descrizioni di file: fisici, logici, video, di stampa |
QCMDSRC |
definizioni di comandi |
QSQLSRC |
script SQL |
Il tipo di membro — RPGLE, SQLRPGLE, CLLE, PF, LF, DSPF, PRTF, CMD — è
un attributo del membro, non del file che lo contiene, e decide come l'editor lo colora e
quale compilatore ci si aspetta.
WRKMBRPDM FILE(PRODLIB/QRPGLESRC)
DSPFD FILE(PRODLIB/QRPGLESRC) TYPE(*MBRLIST)
E in SQL, che è il modo comodo per cercare qualcosa in tutti i sorgenti insieme:
SELECT TABLE_NAME, SYSTEM_TABLE_SCHEMA, SOURCE_TYPE, LAST_SOURCE_UPDATE_TIMESTAMP
FROM QSYS2.SYSPARTITIONSTAT
WHERE SYSTEM_TABLE_NAME = 'QRPGLESRC'
Nota
un file sorgente ha righe di lunghezza fissa. I file storici erano da 92
caratteri — dodici di numero riga e data, ottanta di codice — e QRPGLESRC è nato da 112,
cioè cento caratteri utili. Una riga più lunga del record non viene tagliata al momento
giusto con un avviso: viene semplicemente troncata, e il codice che ne esce è sintatticamente
valido e sbagliato. È la ragione per cui certi sorgenti hanno una formattazione così
compatta da sembrare scritta per dispetto.
Il codice sull'IFS
Da diversi rilasci i compilatori accettano anche sorgenti come file dell'IFS, cioè file normali in cartelle normali, con nomi lunghi e senza limite di lunghezza riga.
CRTBNDRPG PGM(PRODLIB/FATTURE) SRCSTMF('/home/dev/fatture/fatture.rpgle')
Il motivo per cui questo conta non è l'estetica: è che un file su una cartella si mette sotto git. Il controllo di versione su membri di file sorgente si è sempre fatto con prodotti dedicati di change management, che funzionano e costano; con i sorgenti sull'IFS si usano gli stessi strumenti del resto del mondo, e chi arriva da fuori sa già usarli.
Consiglio
non è una scelta da fare per tutto il codice in una volta. La strada che funziona è tenere il codice storico dov'è e mettere sull'IFS quello che si scrive da ora, o il singolo applicativo che si sta rifacendo. I due modi convivono senza problemi: il compilatore produce lo stesso oggetto.
Dal sorgente all'oggetto
La compilazione non produce un file eseguibile: produce un oggetto nella libreria che si è indicata, con tutto quello che ne consegue — ha un proprietario, ha dei diritti, ha una descrizione, si salva e si ripristina come qualunque altra cosa.
CRTBNDRPG PGM(PRODLIB/FATTURE) SRCFILE(PRODLIB/QRPGLESRC) SRCMBR(FATTURE)
CRTBNDCL PGM(PRODLIB/LANCIA) SRCFILE(PRODLIB/QCLSRC) SRCMBR(LANCIA)
CRTPF FILE(PRODLIB/ORDINI) SRCFILE(PRODLIB/QDDSSRC) SRCMBR(ORDINI)
L'oggetto ricorda da dove è stato prodotto, e questa è una delle cose più utili del sistema:
DSPOBJD OBJ(PRODLIB/FATTURE) OBJTYPE(*PGM) DETAIL(*SERVICE)
Fra i dati di servizio ci sono file sorgente, membro e data e ora dell'ultimo aggiornamento del sorgente al momento della compilazione. Confrontarla con la data del membro dice se l'oggetto in produzione corrisponde al sorgente che si ha davanti.
Avvertenza
è il controllo da fare prima di toccare qualunque cosa in un ambiente che non si conosce. Un sorgente più recente dell'oggetto significa che qualcuno ha modificato il codice e non lo ha compilato, o che ha compilato altrove: ricompilare a quel punto manda in produzione modifiche che nessuno ha chiesto, e che nessuno ha provato.
SELECT OBJNAME, OBJTEXT, SOURCE_FILE, SOURCE_LIBRARY, SOURCE_MEMBER,
SOURCE_TIMESTAMP, OBJCREATED
FROM TABLE(QSYS2.OBJECT_STATISTICS('PRODLIB', '*PGM'))
ORDER BY SOURCE_TIMESTAMP DESC
L'elenco della compilazione
Ogni compilazione produce un file di spool: il compile listing. Contiene il sorgente numerato, gli errori, e — su richiesta — il codice espanso dopo le copie e dopo la precompilazione SQL.
È il posto in cui si guarda quando un errore non ha senso, perché mostra il codice
come lo ha visto il compilatore, che non è sempre quello che si è scritto: le /COPY
sono state espanse, e in un sorgente con SQL incorporato le istruzioni EXEC SQL sono
state riscritte in chiamate.
Consiglio
compilando con OPTION(*EVENTF) il compilatore produce anche un file di
eventi che gli editor moderni leggono per mostrare gli errori direttamente sulla riga
giusta, invece di costringere a cercarli nel listato. È il modo in cui lavorano RDi e le
estensioni per VS Code.
Che cosa manca, rispetto ad altre piattaforme
Tre cose, e conviene saperlo subito invece di cercarle.
Non c'è un file di progetto. Non esiste un Makefile o un pom.xml di serie: l'ordine
di compilazione — prima i file, poi i moduli, poi i programmi — è conoscenza di chi
lavora lì, o sta dentro un prodotto di change management, o dentro un CL scritto a mano che
compila tutto in fila. Esistono strumenti moderni che colmano questo vuoto, e ne parla il
capitolo sugli strumenti.
Non c'è un ambiente virtuale. La separazione fra collaudo e produzione si fa con le librerie e con la lista librerie: stesso programma, librerie diverse. È il motivo per cui la lista librerie è un argomento da capire bene, e per cui un errore lì costa più che altrove.
Non c'è un pacchetto da distribuire. Si sposta un oggetto da una libreria all'altra, o si salva e si ripristina. Il rilascio in produzione è una copia di oggetti, e chi lo fa a mano prima o poi ne dimentica uno.
Commenti
Nessun commento ancora. Sii il primo a commentare!
Devi avere un account per commentare. Accedi · Registrati