16 dicembre 2020

​Era una notte buia e tempestosa

​Farneticazioni sulla gestione degli errori

Era una notte buia e tempestosa. Anzi, forse non era tempestosa. E forse non era nemmeno tanto buia, proprio non lo ricordiamo, ma di sicuro era notte. Siamo agli inizi del secolo (e agli albori dei voli low-cost) e ci aggiriamo per l'aeroporto di Orio al Serio, alla ricerca della macchinetta per pagare il parcheggio. La troviamo, c'è una fessura per inserire la carta di credito, senza una precisa indicazione del verso, quindi procediamo a buon senso. "Carta illeggibile, cambiare verso di inserimento" dice la macchinetta. Giriamo la carta e riproviamo. Stesso messaggio. La rovesciamo e proviamo ancora, stesso messaggio, riproviamo con il quarto e ultimo possibile orientamento, ancora lo stesso messaggio. A questo punto, con poche speranze, proviamo nuovamente con la prima variante, non si sa mai.
E infatti il messaggio cambia, diventa "Prego non giocare".
Già, perché in effetti il gioco "metti la carta nella macchinetta" era di gran voga, secondo solo ad Halo, e orde di ragazzini da tutta Italia si aggiravano per l'aeroporto alla ricerca della preziosa macchinetta.
Non sapendo che fare ci siamo rivolti ad un inserviente che ci ha rapidamente spiegato il problema: "guardi che quella carta di credito non è abilitata su quelle macchinette".
Col cavolo "carta illeggibile". La leggeva ma non sapeva cosa farsene. E noi, lì a giocare.

Spesso nello sviluppo delle applicazioni la gestione degli errori è trascurata. Non parliamo degli errori commessi dall'utente, della validazione di quello che l'utente chiede. Questo fa parte della interfaccia ed è tipicamente gestito con grande attenzione. Ci riferiamo ai problemi che l'applicazione incontra durante l'elaborazione interna. Sono errori difficili da gestire per lo sviluppatore perché l'errore avviene in un contesto (l'elaborazione interna, non l'interfaccia utente) dove probabilmente è impossibile generare un messaggio (si deve farlo dopo, se ci si ricorda …), e perché determinare la reale causa del problema può non essere facile.
Il risultato è che quando finalmente il problema filtra fino all'utente si sono perse le informazioni sulla causa, il contesto e di conseguenza le possibili soluzioni. Pensate all'episodio (verissimo) raccontato sopra. È certo che il sistema ha tentato di usare la carta (che ha letto) e ha ricevuto un rifiuto. Ma poi nella intricata gestione interna ha perso parte delle informazioni sul problema e alla fine si è ricordato solo di un fatto: la carta non ha funzionato. E di una sola possibile causa: non ho letto la carta. E questo ha riportato. Poi lo sviluppatore ha pensato bene di fare lo spiritoso, ma per questo lo perdoniamo volentieri. Non lo perdoniamo per averci fatto perdere tempo!


L'effetto è che ogni tanto i messaggi di errore invece di aiutare a risolvere il problema aiutano ad aggravarlo, facendo perdere tempo a chi vorrebbe solo poter lavorare.

Abbiamo incontrato molti casi dove l'errore è più nel messaggio che nell'evento. Proviamo a riassumerne alcuni, un po' come sfogo, un po' nella speranza che qualche sviluppatore ogni tanto consideri anche il punto di vista di chi l'errore lo deve subire.

Il più frequente è il messaggio generico, inutile. Ogni tanto sembra addirittura prenderti in giro. Un esempio potrebbe essere qualcosa del tipo "An error has occurred. The error code is 0x80012345 (Unkown Error)".
Cosa significa unknown in questo contesto? In realtà se hai un codice di errore allora è known, solo che nessuno ha avuto voglia di farsi una lista dei possibili codici e delle relative cause. Poi, in alcuni casi ci provano e mettono nel messaggio un link a una pagina web, che invariabilmente non c'è più (404) oppure, peggio, che non parla del codice in questione. Almeno concludiamo che è realmente unknown, salvo che per lo sviluppatore che ha generato quel codice e ha omesso di documentarlo.

Una seconda categoria è quella del messaggio fuorviante. In Microsys ne parliamo come del "Try…Catch all" (si, lo sappiamo che non esiste). In sostanza provo a fare una cosa, se va male non perdo tempo a distinguere il perché ma produco un unico messaggio, dando per scontato che ci sia una sola possibile causa. Un esempio egregio di questo comportamento è una applicazione (reale) che quando non riesce a fare login al server chiede la password di accesso. Anche se il server non è raggiungibile, e quindi di sicuro il problema non può essere la password. Ovviamente la nuova password inserita dall'utente non sarà meglio della precedente, visto che il server non è raggiungibile. E l'utente penserà di avere sbagliato lui, mentre il problema è della rete, o nei server.


Una terza variante è il software che la sa più lunga dell'utente. Che ignora le impostazioni, o ciò che l'utente chiede, per fare quello che vuole lui. Salvo poi non riuscirci. Magari la cosa è fatta a fin di bene, perché spesso quella tale impostazione o richiesta è sbagliata. Quindi sarebbe ammissibile avvisare l'utente, "sei sicuro che questo sia giusto?", ma non è ammissibile fare come si vuole, salvo poi constatare che non funziona nulla e produrre un messaggio di errore che proprio non dovrebbe apparire. Qui il problema è l'eccesso di intelligenza, che in realtà è poi poco intelligente.
Una variante di questo comportamento, che non genera errori immediati, ma pasticci a scoppio ritardato, sono le applicazioni che ignorano le impostazioni chieste dall'utente, o le impostano come vogliono loro, ovviamente perché la sanno più lunga. Ne conosciamo una che sistematicamente, tutte le volte che viene utilizzata, mette se stessa come il gestore di un certo tipo di eventi. E l'utente può togliere quel flag. Che però verrà re-impostato la volta successiva.

Un'ultima variante di messaggio che non serve è il messaggio che non parla di un errore, ma forse sì. Ad esempio recentemente ci è capitato un caso dove il sistema diceva "questa impostazione non è stata salvata", con una bella barra rossa di fianco ad una impostazione. Nessuna indicazione del perché, e nemmeno se questo sia un problema o se è stato l'utente ad aver omesso il comando di salvare, o forse semplicemente non c'era nulla da salvare.

Gestire bene gli errori non è affatto facile, ed in certi casi può essere persino pericoloso perché può aprire una porta agli hacker che sfruttano proprio la gestione dell'errore per entrare nel sistema. È capitato ad esempio in SharePoint, che fa in generale un buon lavoro nel gestire gli errori e nel lasciare tracce utili a capire cosa sia successo. Purtroppo proprio quelle tracce sono diventate un meccanismo per scardinare la sicurezza del sistema.
Tutto sommato gli errori non dovrebbero mai presentarsi, e raramente si giudica una applicazione dalla qualità dei messaggi di errore. Anzi se vedo l'errore già mi farò una cattiva opinione, indipendentemente da come è gestito l'errore. È quindi comprensibile che sia un aspetto un po' trascurato dello sviluppo software.
E anche quando gli sviluppatori mettono impegno nella gestione degli errori lo fanno quasi sempre per facilitare il debug, raramente con l'intento di rendere la vita facile agli utenti.

Però forse si potrebbe fare un po' meglio di così.

Segui la nostra
pagina su LinkedIn