![]() ![]() |
|
![]() ![]() |
Nell'eseguire i casi di prova può succedere che si ottengano
risultati inattesi o addirittura che il programma non termini.
Scoperto il malfunzionamento dobbiamo attivarci per identificare le possibili cause e correggere il codice incriminato. Questa attività è detta debugging. Oltre alla tecnica elementare del tracciamento con messaggi sullo standard output, Java 6 mette a disposizione meccanismi più eleganti e sofisticati (stack tracing, logging e asserzioni), ed Eclipse offre un potente ambiente integrato (debugger) per esaminare passo-passo l'esecuzione del codice offrendo la possibilità di correggere il programma mentre viene eseguito. |
![]() ![]() |
|
![]() ![]() |
La tecnica del tracciamento è quella più banale per
cercare gli errori e probabilmente l'avete già adottata in
questi mesi.
Il tracciamento consiste nell'inserire opportuni messaggi di stampa per evidenziare il valore di alcune variabili nei punti dove l'errore sembra manifestarsi, oppure anche solo per controllare che certe porzioni di codice vengano effettivamente eseguite.
Nel seguire il flusso di esecuzione di un programma con messaggi di tracciamento è buona regola visualizzare i valori dei parametri ricevuti in ingresso da ogni metodo invocato e il valore che sta per essere restituito all'uscita dal metodo.
|
![]() ![]() |
|
![]() ![]() |
Il problema principale è che questi messaggi vengono introdotti
solo per il debug e quindi devono essere tolti prima di rilasciare il
programma, col rischio di:
Un problema secondario è che i messaggi inseriti in punti diversi del programma dovrebbero essere differenti, altrimenti potrebbero essere confusi.
|
![]() ![]() |
|
![]() ![]() |
Per risolvere il problema secondario descritto sopra, in Java basta
stampare una traccia dello stack dei record di attivazione, che descrive come il
programma sia giunto in un certo punto.
Permane però il problema principale della tecnica di tracciamento, cioè che tutte le modifiche apportate al codice originale devono essere rimosse manualmente prima del rilascio.
|
![]() ![]() |
|
![]() ![]() |
A partire da Java 1.4, la classe Logger permette di inserire messaggi di
tracciamento che possono essere attivati e disattivati più
facilmente (senza dover ricorrere a soluzioni ad hoc comunque
possibili, come l'introduzione di metodi ausiliari).
L'idea è che invece di stampare direttamente sul flusso System.out si utilizzi un oggetto di logging.
L'uso della classe Logger prevede quindi che i messaggi di tracciamento possano eventualmente restare nel codice rilasciato, purché disattivati.
|
![]() ![]() |
|
![]() ![]() |
Molti errori sono dovuti alla violazione di alcune ipotesi ritenute
implicite dal programmatore, ma non garantite di fatto dal codice
scritto (es. accredito di importi negativi su un conto).
Un'asserzione è una condizione logica che si ritiene essere valida in un preciso punto del programma. A partire da Java 1.4 è stato aggiunto il comando assert che verifica se un'asserzione è violata e solleva un'opportuna eccezione quando questo accade. Però è possibile decidere al momento in cui il programma viene eseguito se abilitare o disabilitare le asserzioni (come default sono disabilitate) e se non sono abilitate l'interprete le ignora senza compromettere minimamente la performance del sistema (invece i comandi condizionali richiederebbero comunque la valutazione dell'espressione).
|
![]() ![]() |
|
![]() ![]() |
La sintassi del comando assert è la seguente:
assert booleanExpression : expression;Dove expression (opzionale) è una qualsiasi espressione che produca un valore di qualsiasi tipo purché non void (tipicamente può essere un messaggio di tracciamento). Dal punto di vista semantico il comando visto sopra è equivalente a: if (!booleanExpression) throw new AssertionError(expression); Si valuta booleanExpression e se questa risulta falsa si solleva un'eccezione di tipo AssertionError che reca come messaggio (la rappresentazione come stringa di) il valore prodotto da expression. Le asserzioni devono essere usate con cautela, tenendo in mente che servono specialmente nella fase di progettazione del codice, ma saranno disabilitate in fase di utilizzo dell'applicazione. Ad esempio è buona norma:
|