Last Updated on 30 Aprile 2020 by Roberto De Pedrini
In generale i programmatori RPG e COBOL non sono abituati a lavorare sotto il controllo di un software ALM (Application Lifecycle Management) o di gestione delle versioni. In passato ho avuto la fortuna di usare uno di questi prodotti (era Turnover della Softlanding) e devo dire che adesso che non lo uso più ne sento la mancanza. Qualunque sia il motivo di questa non scelta – soldi, pigrizia o semplice ignoranza – tutti i programmatori RPG e COBOL che lavorano in un team hanno il problema della allocazione di un membro origine per evitare che più persone lavorino sullo stesso membro origine pestandosi i piedi. Molti si sono arrangiati creando in casa un semplice comando di check-out e modificando il comando STRSEU per impedire l’accesso al membro origine al secondo programmatore. Ma come ottenere lo stesso risultato da RDi? Anni fa, con una RFE, chiesi a IBM l’aggiunta di qualche ‘exit point’ da usare per crearsi in casa un semplice ALM, ma naturalmente IBM declinò. Continuai ad indagare e finalmente arrivai a scoprire che la comunicazione tra RDi e IBM i è il classico DDM (distributed data management), quindi passa attraverso il programma specificato nel parametro DDMACC (Accesso richiesta DDM/DRDA) degli attributi di rete, che può essere impostato con il seguente comando:
CHGNETA DDMACC(libreria/programma)
Le modifiche a questo parametro hanno effetto immediato e si riferiscono alle applicazioni DDM e DRDA. I lavori attualmente in esecuzione sul sistema non usano il nuovo valore, perché si accede al valore DDMACC solo quando un lavoro viene avviato per la prima volta, quindi occorre disconnettere e riconnettere RDi dal server IBM i. È chiaro che una soluzione di questo tipo può essere presa in considerazione solo se lo sviluppo avviene su un server dedicato e non su quello di produzione.
Il programma riceve un parametro con un po’ di informazioni – tra cui profilo utente, libreria, file sorgente, membro origine e tipo di richiesta – e restituisce un flag che può assumere due valori: *ON = richiesta accettata; *OFF = richiesta respinta.
Di seguito trovate un esempio di programma DDMACC:
***************************************************************************
**
** Accesso richiesta DDM/DRDA (DDMACC) comando CHGNETA.
**
***************************************************************************
H DFTACTGRP(*NO) ACTGRP(*CALLER) BNDDIR('QC2LE')
***************************************************************************
**
** Campi
**
***************************************************************************
DreturnCode S 1A
Desito S 1A
DmembroEditabile S N
***************************************************************************
**
** Strutture dati
**
***************************************************************************
DddmRequest DS QUALIFIED
D input 1A
D output 1A
D update 1A
D delete 1A
Dvalues DS QUALIFIED
D user 10A
D application 10A
D subApplication 10A
D objectName 10A
D objectLibrary 10A
D member 10A
D format 10A
D length 5S 0
D sourceRemoteLocation...
D 10A
D sourceSystemName...
D 10A
D other 2000A
***************************************************************************
**
** Costanti
**
***************************************************************************
DREQUEST_ACCEPTED...
D C *ON
DREQUEST_REJECTED...
D C *OFF
***************************************************************************
**
** Parametri
**
***************************************************************************
C *ENTRY PLIST
C PARM returnCode
C PARM values
***************************************************************************
**
** Main
**
***************************************************************************
*INLR = *ON;
returnCode = REQUEST_ACCEPTED;
IF values.application <> '*DDM' OR values.subApplication <> 'OPEN';
RETURN; // La richiesta non mi interessa: richiesta accettata.
ENDIF;
IF values.member >= 'RSE0000000' AND values.member <= 'RSE9999999';
RETURN; // Membri di lavoro creati da RDi.
ENDIF;
ddmRequest = values.other;
IF ddmRequest.input = *ON;
RETURN; // E' una richiesta di sola lettura: richiesta accettata.
ENDIF;
// Inserire qui il controllo del check-out del membro origine.
// Per esempio, controllare che il membro origine sia nella libreria di sviluppo.
IF values.objectLibrary = 'SVILUPPO';
RETURN; // Richiesta accettata.
ENDIF;
// Se arrivo qui la richiesta è da respingere.
returnCode = REQUEST_REJECTED;
In caso di richiesta respinta in RDi appare questo messaggio un po’ criptico, quindi consiglio di avvisare l’utente anche con una email: