lancio dell'eccezione di runtime nell'applicazione Java

11

Lavoro come imprenditore per la progettazione di applicazioni Java aziendali per il mio cliente nel ruolo di lead tecnico. L'applicazione verrà utilizzata dagli utenti finali e ci sarà un team di supporto che supporterà l'applicazione quando partiremo.

Gli altri lead tecnici con cui sto lavorando hanno l'impressione che la gestione delle eccezioni renderà il codice sporco. Il sistema deve generare eccezioni controllate solo dal livello di servizio e il resto del codice deve generare eccezioni di runtime da tutti gli altri livelli in modo che non sia necessario gestire le eccezioni non controllate.

Che cos'è la necessità di lanciare un'eccezione non controllata in un'applicazione aziendale?

Dalla mia esperienza passata in merito alle eccezioni di runtime:

1) Le eccezioni non verificate rendono il codice imprevedibile perché non vengono visualizzate nemmeno in Javadoc.

2) Lancio Le eccezioni non controllate in un'applicazione di business non hanno senso perché quando le lanci e vanno dritte in faccia agli utenti, come la spieghi all'utente? Ho visto abbastanza applicazioni web che mostrano 500 -Internal Error. Contact Administrator che non significa nulla per un utente finale o per il team di supporto che gestisce l'applicazione.

3) Lanciare le eccezioni del runtime costringe gli utenti della classe a lanciare l'eccezione a camminare attraverso il codice sorgente per eseguire il debug e vedere perché viene generata l'eccezione. Questo può essere evitato solo se il Javadoc dell'eccezione di runtime risulta essere ottimamente documentato che non è mai un caso.

    
posta randominstanceOfLivingThing 25.01.2013 - 06:41
fonte

5 risposte

12

Le eccezioni controllate sono un'espressione fallita nella progettazione della lingua. Ti costringono ad avere astrazioni estremamente permeabili e codice sporco. Dovrebbero essere evitati il più possibile.

Come per i tuoi punti:

1) Le eccezioni controllate rendono il codice sporco e non meno imprevedibile perché mostrano ovunque .

2) In che modo un'eccezione controllata viene mostrata all'utente meglio? L'unica vera differenza tra le eccezioni controllate e non controllate è tecnica e riguarda solo il codice sorgente.

3) Hai mai sentito parlare di tracce dello stack? Ti dicono esattamente dove è stata lanciata l'eccezione, indipendentemente dal fatto che sia selezionata o deselezionata. In realtà, le eccezioni controllate tendono ad essere peggio per il debug perché sono spesso impacchettate che portano a tracce di stack più lunghe e brutte, o addirittura perse del tutto perché il wrapping è stato fatto male.

Esistono due tipi di eccezioni: quelli che si verificano "normalmente" e tipicamente gestiti molto vicino a dove si verificano, e quelli che sono veramente eccezionali e possono essere gestiti genericamente in un livello molto alto (basta interrompere l'azione corrente e registralo / mostra un errore).

Le eccezioni controllate erano un tentativo di mettere questa distinzione nella sintassi del linguaggio nel punto in cui sono definite le eccezioni. I problemi con questo sono

  • La distinzione dipende in realtà dal chiamante , non dal codice che genera l'eccezione
  • È completamente ortogonale al significato semantico di un'eccezione, ma legarla alla gerarchia delle classi ti costringe a mescolare i due
  • L'intero punto delle eccezioni è che puoi decidere a quale livello catturarle senza rischiare di perdere un errore in modo silenzioso o di dover inquinare il codice a livelli intermedi o; le eccezioni controllate perdono quel secondo vantaggio.
risposta data 25.01.2013 - 10:07
fonte
2

La mia opinione è che il tipo di eccezione generata dipende da cosa sta facendo il tuo codice.

Lancio eccezioni controllate quando mi aspetto che possano accadere abbastanza spesso (ad esempio, gli utenti inseriscono dati oscuri) e mi aspetto che il codice chiamante gestisca la situazione.

Eseguo eccezioni non selezionate / di runtime (non tutte le volte che sono spuntate) quando ho una situazione rara che non mi aspetto che il codice chiamante possa gestire. Un esempio potrebbe essere una sorta di errore relativo alla memoria strana che non mi aspetto mai di verificarsi. Deselezionati sono i tipi di errori che ci si aspetta di far cadere l'applicazione.

Nessuna eccezione dovrebbe apparire davanti a un utente senza un certo livello di supporto. Anche se è solo un "per favore taglia e incolla questo dump di errore ad una email". Niente è più fastidioso per un utente di quanto non sia stato detto che c'è un errore, ma non viene dato alcun dettaglio o azione che possono intraprendere per avviare la correzione.

La mia ipotesi è che la filosofia che menzioni provenga da una delle due fonti:

  • Programmatori pigri che cercano di evitare di lavorare.
  • O sviluppatori che hanno dovuto supportare il codice che è andato dall'altra parte. cioè la gestione dell'errore eccessivo. Il tipo di codice che contiene grandi quantità di gestione delle eccezioni, molte delle quali non fa nulla o, peggio, viene utilizzato per il controllo del flusso e altri scopi non corretti.
risposta data 25.01.2013 - 07:11
fonte
1

Se non vuoi eccezioni di runtime non controllate, allora perché stai usando java? Esiste la possibilità di eccezioni di runtime quasi ovunque - in particolare NullPointerException, ArithmeticException, ArrayIndexOutOfBounds eccezioni, ecc.

E quando si leggono i file di registro di alcuni sistemi J2EE, come, ad esempio, un'installazione di SAP NetWeaver, noterete che tali eccezioni si verificano letteralmente in ogni momento.

    
risposta data 25.01.2013 - 09:20
fonte
1

Ci sono alcune regole per la gestione delle eccezioni che dovresti tenere a mente. Ma prima, è necessario ricordare che le eccezioni fanno parte dell'interfaccia esposte dal codice; documentali . Questo è particolarmente importante quando l'interfaccia è pubblica, ovviamente, ma è anche un'ottima idea nelle interfacce private.

Le eccezioni dovrebbero essere gestite solo nel punto in cui il codice può fare qualcosa di sensato con loro. L'opzione di gestione peggiore è di non fare nulla su di loro, che dovrebbe essere fatto solo quando è esattamente l'opzione corretta. (Quando ho una tale situazione nel mio codice, includo un commento in tal senso, quindi so che non mi preoccupo del corpo vuoto.)

La seconda opzione peggiore è lanciare un'eccezione non correlata senza l'originale allegato come causa. Il problema qui è che l'informazione all'interno dell'eccezione originale che consentirebbe la diagnosi del problema è persa; stai creando qualcosa con cui nessuno può fare nulla (oltre a lamentarsi del fatto che "non funziona", e sappiamo tutti quanto odiamo questi segnalazioni di bug).

Molto meglio sta registrando l'eccezione. Ciò consente a qualcuno di scoprire qual è il problema e risolverlo, ma è necessario registrare l'eccezione solo nel punto in cui sarebbe altrimenti persa o segnalata su una connessione esterna. Ciò non dipende dal fatto che la registrazione più frequente è un problema grave in quanto tale, ma piuttosto perché una registrazione eccessiva significa semplicemente che il log consuma più spazio senza contenere più informazioni. Una volta che hai registrato l'eccezione, puoi segnalare un précis all'utente / cliente con una buona coscienza (purché includa anche il tempo di generazione - o altro identificatore di correlazione) in quel rapporto così che la versione abbreviata può essere abbinata ai dettagli se necessario).

L'opzione migliore è, ovviamente, per gestire completamente l'eccezione, occupandosi della situazione di errore nella sua interezza. Se riesci a farlo, fallo assolutamente! Potrebbe anche significare che puoi evitare di dover registrare l'eccezione.

Un modo per gestire un'eccezione consiste nel generare un'altra eccezione che fornisce una descrizione di livello superiore del problema (ad es. " failed to initialize " invece di " index out of bounds "). Questo è un buon modello fintanto che non si perdono le informazioni sulla causa dell'eccezione; usa l'eccezione dettagliata per inizializzare il cause dell'eccezione di livello superiore o registra il dettaglio (come discusso sopra). La registrazione è più appropriata quando si sta per attraversare un confine tra processi, come una chiamata IPC, perché non è garantito che la classe di eccezione di basso livello sia presente sull'altra estremità della connessione. Mantenere una causa allegata è più appropriato quando si attraversa un confine interno.

Un altro pattern che vedi è catch-and-release:

try {
    // ...
} catch (FooException e) {
    throw e;
}

Questo è un anti-pattern a meno che tu abbia dei vincoli di tipo da altre clausole catch che significano che non puoi lasciar passare l'eccezione da solo. Quindi è solo una brutta caratteristica di Java.

Non c'è alcuna differenza tra le eccezioni controllate e quelle non selezionate, a parte il fatto che deve dichiarare eccezioni controllate che superano i limiti del metodo. È comunque consigliabile documentare le eccezioni non controllate (con il commento di @throws javadoc) se si sa che vengono deliberatamente generate dal codice. Non gettare deliberatamente java.lang.Error o le sue sottoclassi (a meno che tu non stia scrivendo un'implementazione JVM).

Opinione: un caso di errore imprevisto rappresenta sempre un bug nel codice. Le eccezioni controllate sono un modo per gestire questa minaccia e, laddove gli sviluppatori utilizzano deliberatamente eccezioni non controllate come metodo per evitare il problema di gestire i casi di errore, si accumula un sacco di debito tecnico che dovrai pulire un po 'di tempo se vuoi un codice robusto. La gestione errata degli errori non è professionale (e considerare la gestione degli errori è un buon modo per determinare quanto è buono un programmatore).

    
risposta data 31.03.2013 - 21:57
fonte
0

Penso che dovresti lanciare SOLO l'eccezione controllata quando l'applicazione può recuperare. Quindi, gli utenti della tua libreria devono intercettare quelle eccezioni e fare ciò che è necessario per ripristinare. Qualsiasi altra cosa dovrebbe essere deselezionata.

Ad esempio,

Se la tua app carica i dati da un file o da un database. Poi, ..

try {
  File data = new File(...);
  // parse file here
} catch (Exception ex) {
  throw new MissingDataFileException("data file not found");
}

il chiamante potrebbe sempre intercettare MissingDataFileException e provare a caricare i dati dal database.

try {
  Connection con = DriverManager.getConnection( host, username, password );
  // query data here
} catch (Exception ex) {
  throw new RuntimeException("better call Saul!");
}
    
risposta data 31.03.2013 - 20:52
fonte

Leggi altre domande sui tag