Gestione delle Eccezioni: rescue

Un programma in esecuzione può passare attraverso vari problemi inaspettati . Un file che vorrebbe leggere potrebbe non esistere; il disco potrebbe essere pieno quando desidera salvare dei dati; l'utente potrebbe fornirgli dei dati inaccettabili.

ruby> file = open("un_file")
ERR: (eval):1:in `open': No such file or directory - some_file

Un programma robusto gestirà tali situazioni sensibilmente e in maniera elegante. Rispettare queste aspettative potrebbe esserre un compito esasperante. Dai programmatori C ci si aspetta che controllino il risultato di ogni chiamata di sistema che potrebbe possibilmente fallire, e che decidano immediatamente cosa fare:

FILE *file = fopen("un_file" , "r");
if (file == NULL) {
  fprintf( stderr, "Il file non esiste ." );
  exit(1);
}
byte_letti = fread( buf, 1, byte_desiderati, file );
if (byte_letti != byte_desiderati ) {
  /* effettua ulteriori gestioni delle eccezioni... */
}
...

Questa è una pratica talmente noiosa che i programmatori tendono a curarsene sempre meno ed a dimenticarla, ed il risultato è un programma che non gestisce bene le eccezioni. D'altra parte, fare il lavoro per bene può rendere i programmi difficili da leggere , poiché c'è così tanta roba per le gestione degli errori da nascondere il codice significativo.

In ruby, come in molti linguaggi moderni, possiamo gestire le eccezioni per blocchi di codice in modo [compartimentato], ottenendo un risultato sorprendentemente efficiente ma senza caricare in modo eccessivo il programmatore o chiunque tenti di leggere il codice in seguito. Il blocco di codice segnalato con begin viene eseguito finchè non c'è un'eccezione, che causa il trasferimento del controlload un blocco di gestione dell'eccezione, che viene segnalato da rescue. Se non c'è un eccezione, il codice rescue non viene usato. Il metodo seguente restituisce la prima linea di un file di testo, o nil se c'è un eccezione:

def prima_linea( filename )
  begin
    file = open("un_file")
    info = file.gets
    file.close
    info  # l'ultima cosa valutata è il valore di ritorno
  rescue
    nil   # non possiamo leggere il file? Allora non restituiamo una stringa
  end
end

Ci saranno volte in cui vorremo essere in grado di aggirare un problema in maniera creativa . Qui, se il file desiderato fosse stato indisponibile, avremmo potuto usare lo standard input ad esempio:

begin
  file = open("un_file")
rescue
  file = STDIN
end

begin
  # ... processa l'input ...
rescue
  # ... e gestiamo ogni altra eccezioni qui.
end

retry può essere usato insieme al codice in rescue per ricominciare il codice in begin ancora. Esso ci permette di riscrivere il codice dell'esempio precedente in maniera leggermente più compatta:

fname = "un_file"
begin
  file = open(fname)
  # ... processa l'input ...
rescue
  fname = "STDIN"
  retry
end

In ogni caso, c'è un difetto qui. Un file non esistente farà si che questo codice entri in un ciclo infinito. Avrete bisogno di stare attenti per simili trappolenell'uso di retry per la gestione delle eccezioni.

Ogni libreria di ruby solleva un'eccezione se accadono degli errori, e potete sollevare esplicitamente delle eccezioni anche voi dal vostro codice. Per sollevare un eccezione usate raise. Accetta un argomento, che dovrebbe essere una stringa che descrive l'eccezione. L'argomento è opzionale ma non dovrebbe essere omesso. Si potrà accedere in seguito ad esso tramite la variabile globale speciale $!.

ruby> raise "errore di prova"
   test error
ruby> begin
    |   raise "prova2"
    | rescue
    |   print "Erroe: " ,$!, ""
    | end
Errore: prova2
   nil

Ti potrebbe interessare anche

commenta la notizia

C'è 1 commento
Sara
Hai dubbi su questo articolo?