oracle contract by desing la gestione errori
TRANSCRIPT
Lavorare con le eccezioni
Cos'è una eccezione ?Chiamiamo eccezione un evento indesiderabile ed inaspettatoIl processo passa dall'esecuzione del blocco normale all'esecuzione del blocco delle eccezioni.Il processo chiamante viene informato del fatto che la normale esecuzione del programma si è interrotta a causa di un evento inaspettato.Se possibile, il modulo chiamato indica al chiamante l'evento inaspettato che si è verificato
Classificazione delle eccezioniPreviste,recuperabili, falsi allarmi.
Bisogna preservare il normale flusso del programma (possono essere gestite con sub-block)
Previste ma irrecuperabili.Violazione degli obblighi contrattuali da parte del
modulo chiamante. Sono segnalate al chiamante per la loro gestione.
Impreviste ma gestibiliLoggate in una tabella di errori per successiva analisi
Impreviste ingestibiliLoggate in una tabella di errori
Evitare le eccezioni impreviste
Come evitare le eccezioni impreviste ?L'analisi dovrebbe prevedere:
Lo scenario normale
Uno o più scenari alternativi
Gli scenari di errore
(si veda l'esempio di modulo per l'analisi dei casi d'uso)
Ordinare bene i processi del modulo
Ecco come ordinare i processi nel modulo :Controllo formale dei parametri di ingresso
I parametri rispettano i datatype ed il formato previsto dal modulo chiamato ?
Controllo semantico dei parametri di ingressoI parametri hanno il corretto significato per il modulo ? (ad
esempio il codice impiegato identifica davvero un dipendente ?)
Controllo corretta esecuzione degli algoritmi del modulo
Scrivere il codice cercando di prevenire gli errori
Ordinare bene i processi del modulo
Controllo formale dei parametri di output I parametri rispettano i datatype ed il formato previsto
dal modulo chiamante ?Controllo semantico dei parametri di output
I parametri hanno il corretto significato per il modulo chiamante ?
Controllo che gli errori eventualmente restituiti al modulo chiamato abbiamo un significato chiaro
Chi riceve l'errore deve capire quale tipo di errore si è verificato ed eventualmente ricevere indicazioni su come trattarlo
I tipi di errore Oracle
Nel mondo pl/sql ci sono tre grandi categorie di errori:
Quelli interni definiti dal server oracle
Predefiniti
Definiti dall'utente
I tipi di errore Oracle
Gli errori interni:
Sono quelli generati da un processo interno del database oracle.
Queste eccezioni hanno sempre un codice ma non hanno un nome a meno che questo nome sia assegnato dal motore pl/sql o dall'applicativo. Un esempio di un'eccezione definita internamente è ORA-00060 (deadlock rilevati durante l'attesa della risorsa).
I tipi di errore Oracle
Gli errori predefiniti: Un'eccezione predefinita è un'eccezione definita
internamente da PL / SQL a cui viene assegnato un nome . La maggior parte delle eccezioni predefinite sono definite nel package standard (un package fornito da Oracle che definisce molti elementi di programmazione comuni del linguaggio PL/SQL) .
Un esempio è ORA-00001, a cui viene assegnato il nome DUP_VAL_ON_INDEX in PL/SQL e viene generata quando viene violato il vincolo di unicità creato da un indice “unique” oppure dalla chiave primaria di una tabella.
I tipi di errore Oracle
Gli errori definiti dall'applicativo: Le eccezioni definite dall'applicativo sono quelle inserite
nella sezione “declare” di un blocco PL/Sql.
Oracle mette a disposizione due strumenti per sollevare eccezioni: L'istruzione raise Procedura “raise_application_error”
Le A.P.I. di Oracle per segnalare gli erroriDescrizione Come recuperare l'informazioneCodice dell'errore Variabile sqlcode Questo codice è utile quando
è necessario cercare informazioni generiche su cosa potrebbe aver causato il problema.
Messaggio d'errore Variabile sqlerrm (massimo 512 byte) Oppure
DBMS_UTILITY.FORMAT_ERROR_STACK
Questo testo spesso contiene indicazioni
specifiche quali il nome della constraint o della
colonna che ha generato il problema
Individuare la linea di codice dove è stata sollevata l'eccezione
DBMS_UTILITY.FORMAT_ERROR_BACKTRACE
Questo è di grande aiuto nel rintracciare la
causa degli errori.
Call stack: Questo risponde alla domanda come ho fatto ad arrivare qui ?
DBMS_UTILITY.FORMAT_CALL_STACK
Indica le chiamate fatte per arrivare al punto
in cui si è verificato l'errore
Il controllo dei parametri di inputIl Controllo formale dei parametri eseguito dalle assert
I parametri che non rispettano i datatype previsti generano errori che non possono essere gestiti dal modulo chiamato
Il controllo del processo viene restituito al modulo chiamante con un messaggio di errore che indica quale parametro non rispetta il contratto
Si suggerisce al modulo chiamante come chiamare correttamente il modulo
Sollevare le eccezioni con le assertpackage dbcisAssertFail exception;c_AssertFail constant integer := -20999;pragma exception_init (AssertFail, -20999);procedure assert (p_check in boolean,p_msg in varchar2 := null);end dbc;procedure assert (p_check in boolean,p_msg in varchar2 := null)isbeginif not nvl(p_check,false) -- fail on null inputthenraise_application_error( c_AssertFail, 'Assertion Fail'||': '||substr( nvl(p_msg, 'No Message'), 1, 200));end if;end assert;
Trattandosi di eccezioni che devono essere sollevate dall'applicativo , possiamo utilizzare la procedure “raise_application_error” messaci a disposizione da pl/sql
Il controllo dei parametri di inputCosa controllare
Controllo che i parametri rispettino i datatype previsti ( porre particolare attenzione alle conversioni implicite stringhe => numeri, numeri => stringhe, stringhe => date)
Controllo che il formato dei parametri rispetti quello previsto ( porre particolare attenzione alle stringhe che devono essere trasformate in date utilizzare sempre l'interprete FX => Format eXact e non il formato di default Fill Mode)
Il controllo dei parametri di inputConversioni tra stringhe e numeri controllo formale che una stringa contenga solo numeri
Il controllo dei parametri di input
Le “business rules” del modulo devono determinare il significato semantico dei parametri di ingresso
Il “contratto” stipulato con i moduli chiamanti deve spiegare il significato semantico dei parametri di ingresso
Le “business rules” del modulo determinano quali errori sono “fatali” ed impediscono l'elaborazione del modulo
I messaggi di errore indicano al modulo chiamante quale parametro ha generato l'errore e l'errore generato
Il controllo dei parametri di input
Esempi di controllo <<semantico>> dei parametri di ingresso
Il dato deve avere il significato corretto per il modulo chiamato.
Il codice cliente inputato corrisponde davvero ad un cliente ?
La data inserita nel parametro rientra nella forchetta data min e data max previsti dal modulo?
L'ordine inserito dal cliente supera il fido massimo concesso e non può essere processato?
Il codice dell'articolo corrisponde ad un nostro articolo?
Il controllo esecuzione algoritmoLe “business rules” definiscono gli scenari di errore.
Errori previsti, recuperabili e falsi allarmi
Bisogna preservare il normale flusso del programma mediante l'uso dei sotto-blocchi
Previsti ma irrecuperabili (sono previste apposite eccezioni definite dall'utente )
Il messaggio di errore avvisa il modulo chiamante e l'errore viene scritto nei log per successive analisi
Imprevisti e quindi ingestibili (sono intercettate dal gestore di eccezioni when others)
Il messaggio di errore avvisa il modulo chiamante e l'errore viene scritto nei log per successive analisi
Annidamento - flusso programma exceptions
Begin
BeginExceptionEnd;
BeginEnd;
BeginExceptionEnd;
ExceptionEnd;
Eccezione out
Eccezione gestita dal blocco
Fine esecuzione normale
Eccezione gestita dal blocco
Eccezione gestita dal blocco
Usare l'annidamento per far proseguire il normale flusso del programma
Usare l'istruzione raise o raise_application_error per interrompere il normale flusso del programma
Controllo esecuzione algoritmoIl controllo delle righe estratte
Controllare il numero di righe estratte dal cursore utilizzando l'attributo del cursore sql%rowcount oppure nel caso di “bulk collect” l'attributo “count” della collection.
Gestione degli errori
Quando un'eccezione Oracle può essere anticipata in una sezione di codice,
e l'eccezione può essere gestita in sicurezza,
bisogna racchiudere il codice in un sotto-blocco e gestire l'eccezione (solo quella eccezione)
Il controllo esecuzione algoritmoLe cattive abitudini :
Solleva l'eccezione ed ignorala . La caccia all'errore diventerà difficile e ti impgnerà lungamente
Maschera tutti gli errori. Il modulo chiamante è convinto della corretta esecuzione dell'algoritmo
Maschera tutti gli errori. Le post condizioni sono violate ed inducono in errore il modulo chiamato
Il modulo non è sincero mente mascherando gli errori
Usare correttamente il bloccoexception
Non mascherare l'errore con un blocco exception che non fa nulla!
L'eccezione deve essere almeno sempre loggata.
Caccia al misterioso errore
Usare correttamente il bloccoexception
Attenzione alle modifiche di data-type che possono generare errori difficili da individuare se non correttamente gestiti nel blocco exception
Caccia al misterioso errore
Attenzione alle chiamate di procedure a cascata
L'ultima procedura chiamata B sovrascrive la variabile err_msg settandola a null
Perchè gestire bene gli errori ? Maggiore precisione nell'individuare dove è stata sollevata l'eccezione .
Minore necessità di perdere tempo nel fare debug step by step .
Minore necessità di ricicli
Maggiore possibilità di prevenire proto-attivamente bugs .
Creare una tabella di log erroricreate table LOG_ERRORS(
t_error TIMESTAMP(6), d_error DATE, c_package VARCHAR2(30), c_module VARCHAR2(30), n_sqlcode NUMBER, c_sqlerrm VARCHAR2(1000), c_note VARCHAR2(4000), callstack VARCHAR2(4000), errorstack VARCHAR2(4000), backtrace VARCHAR2(4000), db_instance VARCHAR2(100), host VARCHAR2(100), terminal VARCHAR2(100), ip_adress VARCHAR2(100), session_user VARCHAR2(100));
Timestamp di quando si è verificato l'erroreData errorePackage dove è stato sollevato l'erroreProcedura/funzione sollevato l'erroreCodice dell'erroreMessaggio dell'erroreCampo nel quale inserire i parametri chiamataInserisce stack delle chiamateMessaggio di errore originaleRicostruzione delle chiamate fino all'erroreIstanza del db dove si è verificato l'errorehostTerminale dal quale è stato eseguita la chiamataIndirizzo IPNome della sessione