PL\SQL è un linguaggio procedurale ma è possibile adottare uno stile di scrittura orientato alla programmazione ad oggetti.
In un package PL\SQL è frequente dover definire un modello dati in memoria a supporto degli algoritmi di elaborazione.
Per far ciò, io personalmente preferisco utilizzare TYPE RECORD definiti all’interno del package stesso invece di TYPE OBJECT, perché ciò rende il package auto consistente.
Dato un TYPE RECORD è possibile definire uno o più RECORD di questo tipo di dato. L’inizializzazione di queste variabili può essere effettuati in punti diversi del codice nei modi più diversi, ma non si ha alcuna garanzia che il record venga inizializzato sempre in modo completo e corretto.
Questo rischio aumenta quando è necessario estendere il TYPE RECORD aggiungendo un attributo per esempio.
Il rischio è che, le procedure che utilizzano tali RECORD, risentano della inizializzazione incoerente di questi e che ciò produca errori a run-time.
Il concetto di costruttore è una soluzione efficace a questo problema: quando si usa una struttura dati, prima di usarla, è necessario avere garanzia che essa sia stata correttamente inizializzata.
Nel nostro caso l’idea è di considerare un TYPE RECORD l’equivalente di una CLASS e definire una FUNCTION che svolga il ruolo di costruttore.
Il costruttore accetta in ingresso tutta una serie di parametri che consentono di inizializzare il RECORD e restituisce il RECORD stesso.
La regola non scritta, si parla appunto di stile di programmazione, è che prima di usare RECORD di questo tipo si invoca sempre il suo costruttore.
SUBTYPE tItemId IS VARCHAR2(50); SUBTYPE tCurrency IS NUMBER; TYPE tItem IS RECORD( id tItemId ,descr VARCHAR2(255) ,price tCurrency ,qty NUMBER ,total tCurrency );
FUNCTION itemNew RETURN tItem IS this tItem :=NULL; BEGIN this.qty := 0; this.total := 0; RETURN this; END; FUNCTION itemNew( id IN tItemId ,descr IN VARCHAR2 ,price tCurrency ,qty NUMBER ) RETURN tItem IS this tItem :=itemNew(); BEGIN this.id := id; this.descr := descr; this.price := price; this.qty := qty; RETURN this; END;
DECLARE item tItem := itemNew(); BEGIN item := itemNew(id=>'ID123',descr=>'HAMMER',price=>1.3,qty=>2); END;
Questo approccio può sembrare costoso a prima vista ma in realtà è semplice e facilmente ripetibile.
Il suo utilizzo rende il codice facilmente comprensibile.
Inoltre nel caso in cui si debba estendere il il TYPE RECORD, alterando il costruttore, avremo garanzia che l’intervento venga effettuato in modo coerente in tutti i punti del codice in cui il costruttore è invocato.
Il consiglio è di predisporre sempre un costruttore base non accetta alcun parametro e che inizializza tutti gli attributi ad un valore di default: nel gergo dei programmatori C un costruttore VOID.
Naturalmente sfruttando l’OVERLOADING è possibile definire una famiglia di costruttori che espongono parametri diversi in base alle varie esigenze applicative.