Disegnare applicazioni pl/sql robuste ed affidabili con la metodologia "contract by design" .
La corretta gestione degli errori e la creazione di log utili per il debug
2. Lavorare con le eccezioni
Cos'竪 una eccezione ?
Chiamiamo eccezione un evento indesiderabile ed
inaspettato
Il 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
3. Classificazione delle eccezioni
Previste,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 gestibili
Loggate in una tabella di errori per successiva
analisi
Impreviste ingestibili
Loggate in una tabella di errori
4. 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)
5. 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 ingresso
I 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
6. 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
9. 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
10. 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).
11. 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.
12. 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
13. Le A.P.I. di Oracle per segnalare gli errori
Descrizione Come recuperare l'informazione
Codice 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.
17. Il controllo dei parametri di input
Il 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
18. Sollevare le eccezioni con le assert
package dbc
is
AssertFail 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
Trattandosi di eccezioni
che devono essere
sollevate
dall'applicativo ,
possiamo utilizzare la
procedure
raise_application_error
messaci a disposizione
da pl/sql
19. Il controllo dei parametri di input
Cosa 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)
20. Il controllo dei parametri di input
Controllo formale delle date con il formato Format eXact
21. Il controllo dei parametri di input
Controllo formale delle date con il formato Format eXact
22. Il controllo dei parametri di input
Conversioni tra stringhe e numeri controllo formale che una
stringa contenga solo numeri
23. 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
24. 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?
26. Il controllo esecuzione algoritmo
Le 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
27. Annidamento - flusso programma
exceptions
Begin
Begin
Exception
End;
Begin
End;
Begin
Exception
End;
Exception
End;
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
30. Controllo esecuzione algoritmo
Il 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.
32. 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)
34. Il controllo esecuzione algoritmo
Le 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
35. Usare correttamente il blocco
exception
Non mascherare l'errore con un blocco exception che non
fa nulla!
L'eccezione deve essere almeno sempre loggata.
Caccia al misterioso errore
36. Usare correttamente il blocco
exception
Attenzione alle modifiche di data-type che possono
generare errori difficili da individuare se non correttamente
gestiti nel blocco exception
Caccia al misterioso errore
37. Attenzione alle chiamate di procedure a cascata
L'ultima
procedura
chiamata B
sovrascrive
la variabile
err_msg
settandola a
null
39. 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 .
40. Creare una tabella di log errori
create 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'errore
Data errore
Package dove 竪 stato sollevato l'errore
Procedura/funzione sollevato l'errore
Codice dell'errore
Messaggio dell'errore
Campo nel quale inserire i parametri chiamata
Inserisce stack delle chiamate
Messaggio di errore originale
Ricostruzione delle chiamate fino all'errore
Istanza del db dove si 竪 verificato l'errore
host
Terminale dal quale 竪 stato eseguita la chiamata
Indirizzo IP
Nome della sessione