Newsgroup: it.comp.java
Titolo: [LUNGO] Strategia di buona programmazione con le eccezioni

Sto cercando di capire che strategia adottare nella gestione delle
Eccezioni, al fine di:
- Rendere l'applicazione più robusta possibile;
- Informare l'utente dell'anomalia e lasciargli possibilità
alternative di azione;
- Limitare il carico dovuto alla gestione delle eccezioni;
finora ho elaborato questa strategia, basandomi sul "Thinking in
Java":
1. Cattura sempre le eccezioni. Eckel dice che quelle Runtime non
dovrebbero essere catturate: causando un'uscita forzata indicano un
bug; secondo me devo catturarle.
2. Gestisci le eccezioni nel contesto corrente al fine di forzare il
sistema ad uno stato consistente ("clean");
3. Avvisa il contesto superiore che lo stato è stato forzato,
indicandone il motivo attraverso il nome di classe dell'eccezione;
4. Ripeti la procedura 2-3 per ogni constesto;
5. Il contesto radice deve essere gestito dall'utente secondo le
seguenti opzioni: (Annulla, Ripeti, Non so)
6. Annulla: forza il sistema allo stato consistente precedente (se non
ci riesce, esegue Non so);
8. Ripeti: tenta un Annulla e riprova l'azione (presuppone che
l'utente abbia rimosso la causa del problema);
9. Non so: esegue una copia dello Stack trace sul file di Log a fini
di debug (Bug Report).
10. Al fine di forzare ad uno stato consistente, puoi usare il metodo
finalize() solo quando sono necessarie "le maniere forti". Nota che
questo metodo può essere invocato solo dal Garbage Collector: non si
sa a priori quando. Per questo motivo bisogna evitarlo.
Ho delle perplessità sul punto 1 e sul punto 10. Potete aiutarmi???
a proposito del punto 1, sul "Thinking in Java" trovo, alle pagg.
551-552:
"Keep in mind that you can only ignore RuntimeExceptions in your
coding, since all other handling is carefully enforced by the
compiler. The reasoning is that a RuntimeException represents a
programming error:
1. An error you cannot catch (receiving a null reference handed to
your method by a client programmer, for example) .
2. An error that you, as a programmer, should have checked for in
your code (such as ArrayIndexOutOfBoundsException where
you should have paid attention to the size of the array).
You can see what a tremendous benefit it is to have exceptions in this
case, since they help in the debugging process."
Non sono d'accordo.
Se qualcuno cambia i permessi di accesso ad un file, la mia
applicazione rileverà una SecurityException. Devo informare l'utente
dell'accaduto, e non si tratta di un errore di programmazione!

 dell'accaduto, e non si tratta di un errore di programmazione!
Se ho capito quello che intende dire l'autore del libro, credo che
suggerisca di evitare cose tipo:
try
    {
    ...
    }
catch(RuntimeException re)
    {
    }
Ma che piuttosto si faccia cosi':
try
    {
    ...
    }
catch(SecurityException se)
    {
    }
Non so dirti poi se problemi di accesso ad un file causino una eccezione
RuntimeException (come ad esempio una SecurityException) o piuttosto
una IOException (come ad esempio FileNotFoundException etc. etc.).
Boh! 8-) Dipende credo dal modo in cui vi accedi (con i FileDescriptor
ho visto ora che ti tira dietro una SecurityException :)
Ciao!
Andrea

 dell'accaduto, e non si tratta di un errore di programmazione!
Esattamente. 
-- 
Life's something u don't get out alive..
ObjectZone - 
http://space.tin.it/computer/csadun

Vediamo se ho capito.
Il tuo approccio si articola in due fasi:
design time -
Prima stabilisci quali sono i possibili stati inconsistenti, poi li
classifichi secondo il tipo di risposta: recoverable e
non-recoverable. Per fare questo ti aiuti con modelli a reti
Stato/Transizione (giusto?).
Nella mia (brevissima) esperienza professionale mi è capitato di
trafficare con diagrammi di macchine a stati finiti; il limite di
questo formalismo è che in genere i sottostati associabili ai
rispettivi sottosistemi sono in numero molto elevato. Dovendo
modellizzare un intero sistema, gli stati possibili e le transizioni
si moltiplicano, e il risultato è un intreccio di complessità
scoraggiante. 
Insomma considero ancora aperto il problema di trovare quel formalismo
di modellazione che invece di complicare il nostro lavoro lo
semplifichi.
sviluppo -
Gli stati eccezionali vengono gestiti in modo trasparente rispetto ai
contesti superiori quando è possibile un recovery, altrimenti si
avvisa il contesto superiore con un rethrow. Al limite, il contesto
superiore è interamente dedicato alla gestione dei recovery/avvisi;
Ovvero: definisci un manager delle eccezioni tra il soprasistema e il
suo sottosistema (ma per ogni livello della gerarchia?).
Mi interessa capire a fondo questa tecnica. Puoi produrre un esempio
completo in cui si vede al lavoro una di queste classi manager? 
Alla luce di quanto discusso finora, modifico il mio approccio in
questo modo:
Le eccezioni vanno classificate secondo il tipo di stato unclean che
segnalano: uno stato recoverable e uno stato non-recoverable.
Ulteriormente possiamo discriminare tra gli stati recoverable quelli
che il sistema può gestire effettuando un retry a partire da stati
diversi (anche indicati dall'esterno), e stati ingestibili dal sistema
che quindi richiedono sempre un intervento esterno (di un altro
sistema o dell'utente) oppure richiedono una terminazione graceful del
processo (qui il sistema si limita a spostarsi "verso" lo stato più
"vicino" ad uno stato clean al fine di limitare i "danni").
Le opzioni gestite dall'utente diventano:
Annulla (non modificato)
Ripeti (non modificato)
Termina: effettua il Report sul log, poi forza il sistema allo stato
"più pulito" e infine termina il processo avvisando l'utente
dell'accaduto.


Alleluiah! :-)
Ciao,
    Bruno.
---
| Bruno Bossola
| A Java Software Engineer :-)
| 
http://digilander.iol.it/bbossola

 dell'accaduto.
In genere, l'azione ritornata da codice di handling io la vedo come 
relativa solo al *passo fallito* del processo handled - non come istruzione 
per fare qualcos'altro. Mi spiego: di per se' "termina" significa 
"termina", il piu' velocemente possibile. Se devo fare un log (ovvero 
qualcosa di radicalmente diverso da "terminare", e' compito dell'exception 
handler farlo, non del codice chiamante - anche perche' il codice 
chiamante, essendo in un failure state, puo' non essere in grado di fare 
alcunche' che terminare.
