MokaHints
Debugging a livelli
a cura di 
Andrea Trentini
Configurare la quantità e la qualità dell'output di debugging di un prodotto.  Una proposta di "debugging convention"... non tanto sulla forma dell'output quanto sul "cosa far vedere e quando"

    Il problema in questione

    Quando scrivete codice vi capita di mettere le cosiddette "print di debug" ? Penso di sì, lo fanno tutti, specie se, come in java, il debugger è qualcosa di poco usabile...
    In inglese si dice "instrumentating code" (se volete darvi un tono ;-), vuol dire semplicemente intercalare il normale codice sorgente con delle istruzioni di tipo "System.out.println(...)" (anche su stderr va bene) per vedere i valori di certe variabili importanti nei momenti cruciali.
    Però poi il prodotto va distribuito... lo lasciate così? Inoltre, ancora durante lo sviluppo, non è detto che vi interessino sempre e tutte le "print" che avete messo...
    Sarebbe bello poter attivare e disattivare le "print" a seconda dei momenti semplicemente cambiando una variabile e ricompilando il sorgente... e magari si potrebbero anche attivare parzialmente, per categorie ad esempio.
     
     
     

    Soluzione proposta

    In java è possibile usare un analogo di "#IFDEF DEBUG" del C, è sufficiente usare variabili "final static" e tutti gli "if" valutati su tali variabili verranno in realtà valutati a compile time (es. un if su una variabile booleana final static falsa NON verrà nemmeno tradotto in bytecode!).
    Se si decidono un po' di categorie di debugging (es. NORMALE, PROFONDO, CICLI, RETE, DB, etc.) è possibile categorizzare le "print" e attivarle solo quando richiesto.
    Basta definire una variabile final static boolean per ogni categoria (io uso sempre una classe astratta che chiamo Debug) e condizionare tutte le "print" in base a queste variabili.
    Per abilitare e disabilitare le "print" basta editare il sorgente di Debug e mettere a true o false le variabili opportune...
     
     
     

    Esempio

    Diciamo di avere questa classe Debug:

    public abstract class Debug
    {
       /** eccezioni */
       public final static boolean EXCEP = true;
       public final static boolean DEEP_EX = true;

       /** system.out... (generiche) */
       public final static boolean PRINT = true;
       public final static boolean DEEP = false;

       /** system.out... (contatori dei loop) */
       public final static boolean LOOP = false;
    }

    Nel codice potremo quindi mettere statement del tipo:

     if(Debug.PRINT) System.out.println(p);
     ...
     if(Debug.DEEP) System.out.println(Integer.toString(current));

    etc. etc.

    E piloteremo così tutto il "debugging output" del nostro programma semplicemente attivando o meno le variabili booleane (e ricompilando, mi raccomando!).
    A fine sviluppo (cioè mai ;-) potrete mettere a false tutto e il vostro programma girerà silenzioso come un gatto addormentato...
     
     
     

    Note

    Chiaramente questo è solo l'inizio, ognuno poi deve decidere quali sono le classi di messaggi che gli interessano (nel mio esempio li catalogo sia per quantità che per qualità) e quale sia il formato di uscita. Sarebbe infatti bello definirsi un formato standard per questo tipo di output (un qualcosa che contenga informazioni dettagliate sul contesto), ma questa è un'altra storia... ;-)

MokaHints 

Consigli utili per il programmatore Java
www.mokabyte.it/mokahints