Non è una buona pratica gestire le eccezioni di runtime nel codice?


11

Sto lavorando su un'applicazione Java e vedo che le eccezioni di runtime sono gestite in molti punti. Per esempio,

try {
    // do something
} catch(NullPointerException e) {
    return null;
}

La mia domanda è: quando è una buona pratica gestire le eccezioni di runtime? Quando dovrebbero essere gestite le eccezioni?


7
-1: Non esiste una risposta unica a una domanda così ampia e vaga. È impossibile fornire un'unica risposta a una domanda così sfocata come questa. Questa domanda è terribile. Fornisci esempi specifici di dubbi.
S.Lott

@ S. Lott In questo caso non sono d'accordo in quanto sembra che ci sia un sottoinsieme di programmatori che hanno in testa che questo è il caso senza razionalità "buona".
SoylentGray,

2
@Chad: "questo è il caso senza" buona "razionalità". Questo potrebbe essere vero. Ma l'unica risposta possibile deve essere "dipende". Pertanto, la domanda sembra difettosa.
S.Lott

Risposte:


18

Dipende.

Ad esempio, Integer#parseIntgenera NumberFormatException(che è un RTE) se la stringa fornita non può essere analizzata. Ma sicuramente non vuoi che la tua app vada in crash solo perché l'utente ha scritto "x" in un campo di testo che era per numeri interi? E come fai a sapere se la stringa può essere analizzata, a meno che non provi prima ad analizzarla? Quindi, in questo caso, l'RTE è solo un segnale di errore che dovrebbe causare qualche tipo di messaggio di errore. Si potrebbe sostenere che dovrebbe essere un'eccezione controllata, ma cosa si può fare - non lo è.


2
Sono d'accordo con "Dipende", ma il tuo esempio di analisi sembra essere piuttosto un caso di cattiva progettazione dell'API. Integer#parseIntdovrebbe Maybe<Integer>invece restituire un invece e non generare alcuna eccezione.
Jörg W Mittag,

3
@ Jörg W Mittag: concordo sul fatto che sia una cattiva progettazione API, ma è il mondo reale che dobbiamo affrontare. Come gestire correttamente i valori gettabili / restituibili dipende da come funziona effettivamente il mondo , non da come dovrebbe funzionare in modo ottimale :-)
Joonas Pulakka,

Il punto qui è che puoi fare qualcosa di significativo per una condizione anticipata (input dell'utente non intero). La deglutizione di NPE è un cattivo stile e coprirà solo gli errori di programmazione esistenti.
Jürgen Strobel,

7

NullPointerExceptions sono in genere il segno di un controllo null mancante. Quindi, invece di catturarlo in questo modo, è necessario aggiungere l'appropriato controllo null per essere sicuri di non generare l'eccezione.

Ma a volte, è opportuno gestire RunTimeExceptions. Ad esempio, quando non è possibile modificare il codice per aggiungere il controllo null nel punto appropriato o quando l'eccezione è diversa da NullPointerException.

Il tuo esempio di gestione delle eccezioni è terribile. In questo modo, perdi la traccia dello stack e le informazioni precise sul problema. E in realtà non lo stai risolvendo poiché probabilmente innescerai un'altra NullPointerException in un posto diverso e otterrai informazioni fuorvianti su ciò che è accaduto e su come risolverlo.


1
Vorrei aggiungere che un controllo nullo è una decisione migliore dal punto di vista delle prestazioni.
Mahmoud Hossam,

... tuttavia, se stai facendo dozzine di allocazioni che "non dovrebbero mai fallire" in un punto, l'aggiunta di controlli null per ognuno di essi potrebbe offuscare ridicolmente il codice. Un'eccezione generale (che gestirà la situazione con grazia, non solo return null;) sarà una soluzione migliore.
SF.

Probabilmente stai confondendo Java con qualcos'altro (C ++ per esempio). Quando un'allocazione fallisce, si ottiene un OutOfMemoryError o qualcosa di simile, mai un puntatore null. La richiesta di un ritorno null invece di un'eccezione significa nascondere l'errore in attesa che il codice esploda altrove.
deadalnix,

newgetta std::bad_allocin C ++.
R. Martinho Fernandes,

Supponendo che il nuovo operatore non sia sovraccarico, che è pratica comune. In C ++, può succedere di tutto;) OK, diciamo il malloc di C. Il punto importante è che non l'hai mai ottenuto a Java.
deadalnix,

4

Gestisco le eccezioni previste dove mi aspetto. (Come errori di lettura / scrittura DB). Eccezioni inaspettate Mi alzo. Da qualche altra parte potrebbe aspettarsi l'eccezione e avere la logica per essa.


2

Le eccezioni dovrebbero essere proprio queste ... eccezioni. La migliore pratica quando si usano le eccezioni è usarle per coprire la situazione in cui accade qualcosa di contrario a ciò che ci si aspetta che accada. L'esempio classico è FileNotFoundException che viene generato quando un file semplicemente non è presente. Se stai testando l'esistenza del file, allora usi File.exists () poiché stai semplicemente spingendo con un bastone da 10 piedi per vedere se colpisci qualcosa.

Potresti ottenere tecnicamente gli stessi risultati circondandolo in un tentativo di prova e usando il file come se esistesse, ma A) le eccezioni sono generalmente costose dal punto di vista delle risorse e B) i programmatori supporranno che intendevi che il file esistesse se lo fosse in una prova, che aggiunge alla confusione generale di un programma.

Ci sono molte situazioni in cui scriverò un metodo che recupera un valore da un database. Mille cose potrebbero andare storte e, visto che ho solo bisogno di una piccola informazione, è scomodo circondare la chiamata con un elenco di prova che contiene 5 diverse eccezioni. Quindi, prenderò delle eccezioni nel metodo di recupero. Se qualcosa va storto, intraprendo qualsiasi azione appropriata per chiudere la connessione al database o quant'altro nella clausola finally e restituire null. Questa è una buona pratica non solo perché semplifica il tuo codice ma anche perché "null" invia lo stesso messaggio che avresti potuto ottenere da un'eccezione ... che qualcosa non è andato come previsto. Gestisci le specifiche delle eccezioni nel metodo di recupero, ma gestisci cosa fare quando le cose non vanno

Per esempio:

Integer getUserCount() {
   Integer result = null;
   try {
      // Attempt to open database and retrieve data
   } catch (TimeoutException e) {
      logger.error("Got a watch?");
   } catch (MissingDatabaseException e) {
      logger.error("What are you smoking?");
   } catch (PermissionsToReadException e) {
      logger.error("Did you *really* think you were getting away with that?");
   } catch (PressedSendButtonToHardException e) {
      logger.error("Seriously.. just back away from the computer... slowly..");
   } catch (WTFException e) {
      logger.error("You're on your own with this one.. I don't even know what happened..");
   } finally {
      // Close connections and whatnot
   }
   return result;
}

void doStuff() {
   Integer result = getUserCount();
   if(result != null) {
       // Went as planned..
   }
}

6
Se si utilizza File.exists () e si fa affidamento sul risultato, potrebbe verificarsi una condizione di competizione se il file viene eliminato tra File.exists () e File.open (). Se questo innesca un bug critico per la sicurezza, un utente malintenzionato potrebbe causare questa condizione di proposito. Per questo motivo, a volte è meglio mantenere atomica l'operazione, ovvero provarla e catturare l'eccezione.
user281377

1
Inoltre, ci sono file che devono esistere per l'esecuzione dell'applicazione. Quelle sarebbero condizioni eccezionali. Se c'è un file che devi avere per far funzionare l'applicazione, allora non c'è motivo di non leggere da esso e quindi gestire l'eccezione per il caso eccezionale. Credo che renda più chiaro l'intento.
Thomas Owens

Questa è una cattiva decisione di restituire null. Si tradurrà in NullPointerException ad un certo punto e sarà davvero difficile eseguire il debug di ciò che è andato storto. Perché qualcuno a un certo punto dimenticherà il controllo null.
deadalnix,

@deadalnix: potrei dire che potresti dimenticare facilmente di circondarti con un try-catch altrimenti. La differenza è una questione di stile, non di funzionalità.
Neil,

@ammoQ: non sono d'accordo. Penso che dovresti usare File.exists () e nella rara circostanza che venga eliminato prima di usarlo, un'eccezione è più che appropriata. La differenza è dove tieni il pescato. È sufficiente disporre di un catcher di eccezione generale per errori imprevisti per registrarlo e segnalarlo.
Neil,

-5

sì, stai gestendo correttamente le eccezioni del tempo di esecuzione non è una buona pratica. Il motivo è che è considerato costoso / ad alta memoria.


5
Ciao amico, puoi approfondire la tua risposta? One-liner che non sono supportati da fatti, riferimenti o esperienze non sono molto utili.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.