È buona norma catturare un'eccezione controllata e lanciare una RuntimeException?


70

Ho letto un codice di un collega e ho scoperto che spesso intercetta varie eccezioni e poi genera sempre una "RuntimeException". Ho sempre pensato che fosse una brutta pratica. Ho sbagliato?


17
"Il prezzo delle eccezioni verificate è una violazione del principio aperto / chiuso. Se si genera un'eccezione controllata da un metodo nel codice e la cattura è di tre livelli sopra, è necessario dichiarare tale eccezione nella firma di ciascun metodo tra l'utente e la cattura Ciò significa che una modifica a un livello basso del software può imporre modifiche alla firma su molti livelli più elevati. " —Robert C. Martin, «Codice pulito», pagina 107
Songo,

6
È interessante notare che Jim Waldo si oppone a eccezioni non verificate in "Java: The Good Parts" shop.oreilly.com/product/9780596803742.do dicendo che i programmatori adulti dovrebbero solo lanciare eccezioni verificate. L'abbiamo letto nel nostro JUG solo 6 anni fa quando è uscito e sembrava un buon consiglio! Ora, con la programmazione funzionale, le eccezioni controllate sono completamente ingombranti. Lingue come Scala e Kotlin non le hanno nemmeno. Ho iniziato a eseguire il wrapping anche in eccezioni non selezionate.
GlenPeterson,

@GlenPeterson hai anche il consiglio in FP di evitare del tutto le esecuzioni e usare invece i tipi di somma
jk.

C'è anche il caso evidente di interfacce funzionali: le interfacce funzionali incorporate (vale a dire Function, Predicatee così via) non hanno parametrizzate getta clausole. Ciò significa che è necessario catturare, avvolgere e ricodificare qualsiasi eccezione verificata nel ciclo interno di qualsiasi metodo stream (). Di per sé ciò equivale a stabilire se le eccezioni verificate siano una cattiva idea.
Joel Cornett,

Non c'è niente di sbagliato nel creare sottoclassi personalizzate di RuntimeException per comunicare il significato attraverso la tua eccezione.
Joel Cornett,

Risposte:


55

Non conosco abbastanza contesto per sapere se il tuo collega sta facendo qualcosa di sbagliato o no, quindi discuterò di questo in senso generale.

Non penso che sia sempre una pratica errata trasformare le eccezioni verificate in qualche tipo di eccezione di runtime . Le eccezioni verificate sono spesso utilizzate in modo improprio e abusate dagli sviluppatori.

È molto facile usare le eccezioni verificate quando non sono pensate per essere utilizzate (condizioni irrecuperabili o persino flusso di controllo). Soprattutto se un'eccezione controllata viene utilizzata per le condizioni dalle quali il chiamante non può recuperare, penso che sia giustificato trasformare quell'eccezione in un'eccezione di runtime con un messaggio / stato utile. Sfortunatamente in molti casi quando uno si trova di fronte a una condizione irrecuperabile, tende ad avere un blocco di cattura vuoto che è una delle peggiori cose che puoi fare. Il debug di un tale problema è uno dei maggiori problemi che uno sviluppatore può incontrare.

Quindi, se ritieni di avere a che fare con una condizione recuperabile, dovrebbe essere gestita di conseguenza e l'eccezione non dovrebbe essere trasformata in un'eccezione di runtime. Se si utilizza un'eccezione controllata per condizioni irrecuperabili, è giustificata trasformarla in un'eccezione di runtime .


17
Nella maggior parte delle applicazioni della vita reale, ci sono pochissime condizioni irrecuperabili. C'è quasi sempre un certo livello al quale puoi e dovresti dire "OK, questa azione non è riuscita, quindi mostriamo / registriamo un bel messaggio di errore e continuiamo con / attendi il prossimo".
Michael Borgwardt,

6
È vero, @MichaelBorgwardt, ma il posto per quel tipo di gestione è spesso al livello più alto dell'applicazione, quindi ogni volta che vedo gli sviluppatori "gestire" le eccezioni ai livelli più bassi, di solito è facile rimuovere la loro gestione e semplicemente calcolare l'eccezione verso l'alto. Ad esempio, un framework Web come JSF rileva le eccezioni al livello più alto, stampa i messaggi di registro e continua l'elaborazione di altre richieste (senza dire che la gestione predefinita è adatta, solo un esempio).
DavidS

40

Si può essere buoni . Si prega di leggere:

http://onjava.com/pub/a/onjava/2003/11/19/exceptions.html

Il più delle volte, il codice client non può fare nulla riguardo alle SQLExceptions. Non esitate a convertirli in eccezioni non selezionate. Considera il seguente codice:

public void dataAccessCode(){
  try{
      ..some code that throws SQLException
  }catch(SQLException ex){
      ex.printStacktrace();
  }
} 

Questo blocco catch elimina solo l'eccezione e non fa nulla. La giustificazione è che non c'è nulla che il mio cliente possa fare su una SQLException. Che ne dici di affrontarlo nel modo seguente?

public void dataAccessCode(){
   try{
       ..some code that throws SQLException
   }catch(SQLException ex){
       throw new RuntimeException(ex);
   }
} 

Ciò converte SQLException in RuntimeException. Se si verifica SQLException, la clausola catch genera una nuova RuntimeException. Il thread di esecuzione viene sospeso e viene segnalata l'eccezione. Tuttavia, non sto corrompendo il livello del mio oggetto business con una gestione delle eccezioni non necessaria, soprattutto perché non può fare nulla per una SQLException. Se la mia cattura ha bisogno della causa dell'eccezione radice, posso utilizzare il metodo getCause () disponibile in tutte le classi di eccezione a partire da JDK1.4.

Generare eccezioni verificate e non poterne recuperare non aiuta.

Alcune persone pensano addirittura che le eccezioni controllate non debbano essere utilizzate affatto. Vedi http://www.ibm.com/developerworks/java/library/j-jtp05254/index.html

Di recente, diversi esperti ben noti, tra cui Bruce Eckel e Rod Johnson, hanno dichiarato pubblicamente che, sebbene inizialmente concordassero completamente con la posizione ortodossa sulle eccezioni verificate, hanno concluso che l'uso esclusivo delle eccezioni controllate non è una buona idea quanto è apparso inizialmente e le eccezioni verificate sono diventate una fonte significativa di problemi per molti grandi progetti. Eckel ha una visione più estrema, suggerendo che tutte le eccezioni dovrebbero essere deselezionate; L'opinione di Johnson è più conservatrice, ma suggerisce ancora che la preferenza ortodossa per le eccezioni verificate è eccessiva. (Vale la pena notare che gli architetti di C #, che quasi sicuramente hanno avuto molta esperienza nell'uso della tecnologia Java, hanno scelto di omettere le eccezioni verificate dal design del linguaggio, rendendo tutte le eccezioni non controllate.

Anche dallo stesso link:

La decisione di utilizzare eccezioni non controllate è complicata ed è chiaro che non esiste una risposta ovvia. Il consiglio di Sun è di usarli per niente, l'approccio C # (con cui Eckel e altri sono d'accordo) è di usarli per tutto. Altri dicono "c'è una via di mezzo".


13

No, non ti sbagli. La sua pratica è estremamente fuorviante. Dovresti generare un'eccezione che cattura il problema che l'ha causato. RunTimeException è ampia e irraggiungibile. Dovrebbe essere una NullPointerException, ArgumentException, ecc. Qualunque cosa descriva accuratamente ciò che è andato storto. Ciò offre la possibilità di differenziare i problemi che è necessario gestire e consentire al programma di sopravvivere rispetto agli errori che dovrebbero essere uno scenario "Non passare". Quello che sta facendo è solo leggermente migliore di "On Error Resume Next" a meno che non manchi qualcosa nelle informazioni fornite nella domanda.


1
Grazie per il suggerimento. E se lancia un'eccezione personalizzata che ha implementato che eredita direttamente da RuntimeException?
RoflcoptrException il

27
@Gary Buyn: Molte persone pensano che un'eccezione controllata sono un esperimento di progettazione lingua fallito e che sono quelli che devono essere utilizzati con parsimonia, non come una questione di abitudine.
Michael Borgwardt,

7
@Gary Buyn: ecco un articolo che delinea abbastanza bene il dibattito: ibm.com/developerworks/java/library/j-jtp05254/index.html Nota anche che oltre 15 anni dopo che Java ha introdotto questa funzione, nessun altro linguaggio l'ha adottato, e C ++ ha deprecato una funzionalità simile.
Michael Borgwardt,

7
@c_maker: In realtà, Bloch promuove principalmente la visione ortodossa e il tuo commento sembra riguardare principalmente l'uso di più eccezioni, punto. A mio avviso, l'unico motivo valido per utilizzare un'eccezione selezionata è una condizione che tutti i chiamanti devono gestire immediatamente.
Michael Borgwardt,

14
Eccezioni verificate di lancio non necessarie violano l'incapsulamento. Cosa fai se un metodo semplice come 'getAccounts ()' ti lancia un 'SQLException', 'NullPointerException' o 'FileNotFoundException'? Riesci a maneggiarlo? Probabilmente lo prenderai semplicemente (Eccezione e) {} '. Inoltre, quelle eccezioni - la sua implementazione specifica! Non dovrebbe far parte del contratto! Tutto quello che devi sapere è che si è verificato un errore . E se l'implementazione cambia? All'improvviso tutto deve cambiare, perché il metodo non genera più "SQLException", ma "ParseXMLException"!
KL

8

Dipende.

Questa pratica può essere persino saggia . Esistono molte situazioni (ad esempio nello sviluppo web), in cui se si verifica un'eccezione, non si è in grado di fare nulla (perché ad esempio non è possibile riparare DB inconsistenti dal proprio codice :-), solo lo sviluppatore può farlo). In queste situazioni, è consigliabile racchiudere l'eccezione generata in un'eccezione di runtime per ripeterla. Quindi puoi catturare tutte queste eccezioni in alcuni livelli di gestione delle eccezioni, registrare l'errore e visualizzare all'utente un bel codice di errore localizzato + messaggio.

D'altra parte , se l'eccezione non è di runtime (è selezionata), lo sviluppatore dell'API indica che questa eccezione è risolvibile e deve essere riparata. Se è possibile, allora dovresti assolutamente farlo.

L'altra soluzione potrebbe essere quella di riproporre questa eccezione verificata nel livello chiamante, ma se non si è riusciti a risolverla, dove si è verificata l'eccezione, probabilmente non sarà possibile risolverla anche qui ...


Speri che lo sviluppatore dell'API sappia cosa sta facendo e abbia usato bene le eccezioni verificate. Ho iniziato a vedere le API che favoriscono il lancio di eccezioni di runtime e allo stesso tempo la documentano in modo che il client abbia la possibilità di prenderlo se lo desidera.
c_maker,

Un metodo che genera un'eccezione non può in genere sapere se un chiamante potrebbe recuperare da esso. D'altra parte, suggerirei che un metodo dovrebbe lasciare scappare un'eccezione controllata lanciata da un metodo interno se sa perché il metodo interno ha generato l'eccezione e il motivo è coerente con l'API del metodo esterno. Se un metodo interno genera un'eccezione verificata in modo imprevisto, lasciarla apparire come un'eccezione verificata può lasciare il chiamante non informato su ciò che è accaduto.
supercat

2
Grazie per aver menzionato exception handling layer, ad esempio, una webapp, un filtro.
Jake Toronto,

5

Vorrei ricevere commenti su questo, ma trovo che ci sono momenti in cui questa non è necessariamente una cattiva pratica. (O terribilmente cattivo). Ma forse mi sbaglio.

Spesso un'API che stai utilizzando genera un'eccezione che non puoi immaginare di essere effettivamente lanciata nel tuo caso specifico. In questo caso, sembra perfettamente corretto lanciare una RuntimeException con l'eccezione rilevata come causa. Se viene generata questa eccezione, sarà probabilmente la causa dell'errore di programmazione e non rientra nei limiti per una specifica corretta.

Supponendo che RuntimeException non venga successivamente catturato e ignorato, non è vicino a un OnErrorResumeNext.

OnErrorResumeNext si verificherebbe quando qualcuno rileva un'eccezione e semplicemente la ignora o semplicemente la stampa. Questa è una cattiva pratica in quasi tutti i casi.


Questo potrebbe essere il caso vicino alla parte superiore dell'albero delle chiamate, dove l'unica cosa che puoi fare è provare a recuperare con garbo e sapere che l'errore specifico non sarà davvero d'aiuto. In tal caso, potrebbe essere necessario registrare l'errore e andare avanti (elaborare il record successivo, informare l'utente che si è verificato un errore, ecc.). Altrimenti no. Dovresti sempre gestire le eccezioni il più vicino possibile all'errore, non racchiuderle come un elefante bianco per il gestore successivo.
Michael K,

@MichaelK Il problema è "tanto vicino all'errore quanto pratico" nella pratica spesso significa "attraverso diversi strati intermedi che sono fuori dal tuo controllo diretto". Ad esempio, se la mia classe deve implementare una determinata interfaccia, le mie mani sono legate. Ciò può accadere arbitrariamente in profondità nell'albero delle chiamate. Anche quando le interfacce sono sotto il mio controllo, l'aggiunta di dichiarazioni di tiri può far perdere l'astrazione se ci sono solo un numero limitato di implementazioni concrete che possono plausibilmente lanciare. Far pagare ad ogni cliente il costo per i dettagli di implementazione di pochi non è un grande compromesso di progettazione IMO.
Tim Seguine,

4

TL; DR

Premessa

  • Le eccezioni di runtime devono essere generate quando l'errore è irrecuperabile: quando l'errore si trova nel codice e non dipende dallo stato esterno (quindi il ripristino correggerebbe il codice).
  • Le eccezioni verificate devono essere generate quando il codice è corretto, ma lo stato esterno non è come previsto: nessuna connettività di rete, file non trovato o corrotto, ecc.

Conclusione

È possibile riproporre un'eccezione verificata come eccezione di runtime se il codice di propagazione o di interfaccia presuppone che l'implementazione sottostante dipenda dallo stato esterno, quando chiaramente non lo è.


Questa sezione tratta l'argomento di quando deve essere generata una delle eccezioni. Puoi passare alla barra orizzontale successiva se desideri solo leggere una spiegazione più dettagliata per la conclusione.

Quando è appropriato generare un'eccezione di runtime? Si genera un'eccezione di runtime quando è chiaro che il codice non è corretto e che il recupero è appropriato modificando il codice.

Ad esempio, è opportuno generare un'eccezione di runtime per quanto segue:

float nan = 1/0;

Ciò genererà una divisione per zero eccezioni di runtime. Questo è appropriato perché il codice è difettoso.

O per esempio, ecco una parte del HashMapcostruttore di:

public HashMap(int initialCapacity, float loadFactor) {
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity);
    if (initialCapacity > MAXIMUM_CAPACITY)
        initialCapacity = MAXIMUM_CAPACITY;
    if (loadFactor <= 0 || Float.isNaN(loadFactor))
        throw new IllegalArgumentException("Illegal load factor: " +
                loadFactor);
    // more irrelevant code...
}

Al fine di correggere la capacità iniziale o il fattore di carico, è opportuno modificare il codice per assicurarsi che vengano passati i valori corretti. Non dipende dal fatto che un server remoto sia attivo, dallo stato corrente del disco, un file o un altro programma. Quel costruttore chiamato con argomenti non validi dipende dalla correttezza del codice chiamante, sia esso un calcolo errato che ha portato a parametri non validi o un flusso inappropriato che ha perso un errore.

Quando è appropriato lanciare un'eccezione controllata? Si genera un'eccezione controllata quando il problema è recuperabile senza modificare il codice. O per dirla in termini diversi, si genera un'eccezione controllata quando l'errore è correlato allo stato mentre il codice è corretto.

Ora la parola "recuperare" può essere complicata qui. Potrebbe significare che trovi un altro modo per raggiungere l'obiettivo: ad esempio, se il server non risponde, dovresti provare il server successivo. Se questo tipo di ripristino è possibile per il tuo caso, allora è fantastico, ma non è l'unica cosa che significa recupero: il ripristino potrebbe semplicemente mostrare all'utente una finestra di dialogo che spiega cosa è successo, o se si tratta di un'applicazione server, allora potrebbe essere inviando un'e-mail all'amministratore o semplicemente registrando l'errore in modo appropriato e conciso.

Facciamo l'esempio menzionato nella risposta di mrmuggles:

public void dataAccessCode(){
   try{
       ..some code that throws SQLException
   }catch(SQLException ex){
       throw new RuntimeException(ex);
   }
}

Questo non è il modo corretto di gestire l'eccezione selezionata. La semplice incapacità di gestire l'eccezione nell'ambito di questo metodo non significa che l'app debba essere arrestata in modo anomalo. Invece, è opportuno propagarlo in un ambito superiore in questo modo:

public Data dataAccessCode() throws SQLException {
    // some code that communicates with the database
}

Ciò consente la possibilità di recupero da parte del chiamante:

public void loadDataAndShowUi() {
    try {
        Data data = dataAccessCode();
        showUiForData(data);
    } catch(SQLException e) {
        // Recover by showing an error alert dialog
        showCantLoadDataErrorDialog();
    }
}

Le eccezioni verificate sono uno strumento di analisi statica, che chiariscono per un programmatore cosa potrebbe andare storto in una determinata chiamata senza richiedere loro di apprendere l'implementazione o passare attraverso un processo di prova ed errore. Ciò semplifica l'assicurazione che nessuna parte del flusso di errori venga ignorata. Il rilancio di un'eccezione controllata come un'eccezione di runtime funziona con questa funzionalità di analisi statica che fa risparmiare lavoro.

Vale anche la pena ricordare che il livello chiamante ha un migliore contesto dello schema più grande delle cose, come è stato dimostrato sopra. Potrebbero esserci molte cause che dataAccessCodepotrebbero essere chiamate, il motivo specifico della chiamata è visibile solo al chiamante, quindi è in grado di prendere una decisione migliore al corretto recupero in caso di fallimento.

Ora che abbiamo chiarito questa distinzione, potremmo procedere a dedurre quando è giusto ricodificare un'eccezione controllata come eccezione di runtime.


Considerato quanto sopra, quando è appropriato ricodificare un'eccezione verificata come RuntimeException? Quando il codice che stai utilizzando assume la dipendenza dallo stato esterno, ma puoi affermare chiaramente che non dipende dallo stato esterno.

Considera quanto segue:

StringReader sr = new StringReader("{\"test\":\"test\"}");
try {
    doesSomethingWithReader(sr); // calls #read, so propagates IOException
} catch (IOException e) {
    throw new IllegalStateException(e);
}

In questo esempio, il codice si sta propagando IOExceptionperché l'API di Readerè progettata per accedere allo stato esterno, tuttavia sappiamo che l' StringReaderimplementazione non accede allo stato esterno. In questo ambito, dove possiamo certamente affermare che le parti coinvolte nella chiamata non accedono a IO o a qualsiasi altro stato esterno, possiamo tranquillamente riproporre l'eccezione come eccezione di runtime senza stupire i colleghi che non sono consapevoli della nostra implementazione (e sono probabilmente supponendo che il codice di accesso IO genererà un IOException).


La ragione per mantenere strettamente statali esterno dipendenti eccezioni controllate è che sono non deterministici (a differenza di logica eccezioni dipendenti, che saranno prevedibilmente essere riprodotti ogni volta per una versione del codice). Ad esempio, se si tenta di dividere per 0, si produrrà sempre un'eccezione. Se non dividi per 0, non produrrai mai un'eccezione e non dovrai gestire quel caso di eccezione, perché non accadrà mai. Nel caso di accedere a un file, tuttavia, riuscire una volta non significa che ci riuscirai la prossima volta: l'utente potrebbe aver cambiato le autorizzazioni, un altro processo potrebbe averlo cancellato o modificato. Quindi devi sempre gestire quel caso eccezionale, o probabilmente hai un bug.


2

Per applicazioni autonome. Quando sai che la tua applicazione non può gestire l'eccezione che potresti, invece di lanciare la RuntimeException selezionata, lancia Error, lascia che l'applicazione si blocchi, speri in segnalazioni di bug e correggi la tua applicazione. (Vedi la risposta di mrmuggles per una discussione più approfondita di pro e contro di check-up rispetto a non-checked.)


2

Questa è una pratica comune in molti framework. Ad esempio Hibernatefa esattamente questo. L'idea è che le API non devono essere invadenti per il lato client e Exceptionsono invadenti poiché è necessario scrivere esplicitamente il codice per gestirle nel punto in cui si chiama l'API. Ma quel posto potrebbe non essere il posto giusto per gestire l'eccezione in primo luogo.
In realtà, questo è un argomento "caldo" e molte controversie, quindi non mi schierò dalla parte, ma dirò che ciò che il tuo amico fa / propone non è insolito o insolito.


1

L'intera cosa "eccezione verificata" è una cattiva idea.

La programmazione strutturata consente il passaggio di informazioni tra funzioni (o, in linguaggio Java, metodi) solo quando sono "vicine". Più precisamente, le informazioni possono spostarsi tra le funzioni solo in due modi:

  1. Da un chiamante a una persona chiamata, passando argomenti.

  2. Da una chiamata al suo chiamante, come valori di ritorno.

Questa è una cosa fondamentalmente buona. Questo è ciò che ti consente di ragionare sul tuo codice localmente: se hai bisogno di capire o modificare una parte del tuo programma, devi solo guardare quella parte e altre "vicine".

Tuttavia, in alcune circostanze, è necessario inviare informazioni a una funzione "distante", senza che nessuno nel mezzo "lo sappia". Questo è esattamente quando si devono usare le eccezioni. Un'eccezione è un messaggio segreto inviato da un raiser (qualunque parte del codice possa contenere throwun'istruzione) a un gestore (qualunque parte del codice potrebbe contenere un catchblocco compatibile con l'eccezione che era thrown).

Le eccezioni verificate distruggono la segretezza del meccanismo e, con esso, la vera ragione della sua esistenza. Se una funzione può permettersi di far conoscere al chiamante un pezzo di informazione, basta inviarlo direttamente come parte del valore di ritorno.


Potrebbe essere utile ricordare che questo tipo di problema può davvero provocare il caos nei casi in cui un metodo esegue una funzione fornita dal suo chiamante. L'autore del metodo che riceve la funzione in molti casi non ha motivo di sapere né preoccuparsi di ciò che il chiamante si aspetta che faccia, né quali eccezioni potrebbe aspettarsi il chiamante. Se il codice che riceve il metodo non si aspetta che generi un'eccezione controllata, è possibile che il metodo fornito debba racchiudere tutte le eccezioni verificate che genererebbe eccezioni non controllate che il suo fornitore potrebbe quindi rilevare.
supercat

0

Questo potrebbe dipendere da caso a caso. In alcuni scenari è saggio fare ciò che il tuo amico sta facendo, ad esempio quando stai esponendo un API per alcuni clienti e vuoi che il cliente sia meno consapevole dei dettagli dell'implementazione, dove sai che alcune eccezioni di implementazione potrebbero essere specifiche a dettagli di implementazione e non esposti al cliente.

Tenendo lontane le eccezioni verificate, è possibile esporre le API che consentirebbero al client di scrivere codice più pulito poiché il client stesso potrebbe pre-convalidare le condizioni eccezionali.

Ad esempio Integer.parseInt (String) accetta una stringa e ne restituisce l'equivalente intero e genera NumberFormatException nel caso in cui la stringa non sia numerica. Ora immagina che l'invio di un modulo con un campo agevenga convertito attraverso questo metodo ma il client avrebbe già garantito la convalida da parte sua, quindi non ha senso forzare il controllo dell'eccezione.


0

Ci sono davvero un paio di domande qui

  1. Dovresti trasformare le eccezioni controllate in non selezionate?

La regola generale è che dovrebbero essere verificate le eccezioni che il chiamante dovrebbe catturare e recuperare. Altre eccezioni (quelle in cui l'unico risultato ragionevole è l'interruzione dell'intera operazione o in cui le consideri abbastanza improbabili da non meritare la preoccupazione di gestirle in modo specifico).

A volte il tuo giudizio sul fatto che un'eccezione meriti di essere catturato e ripristinato è diverso da quello dell'API con cui stai lavorando. A volte il contesto è importante, un'eccezione che vale la pena gestire in una situazione potrebbe non valere la pena gestirla in un'altra. A volte la tua mano è forzata da interfacce esistenti. Quindi sì, ci sono motivi legittimi per trasformare un'eccezione controllata in un'eccezione non selezionata (o in un diverso tipo di eccezione controllata)

  1. Se hai intenzione di trasformare un'eccezione non selezionata in un'eccezione controllata, come dovresti farlo.

Innanzitutto e, soprattutto, assicurarsi di utilizzare la funzione di concatenamento delle eccezioni. In questo modo le informazioni dell'eccezione originale non vengono perse e possono essere utilizzate per il debug.

In secondo luogo, devi decidere quale tipo di eccezione utilizzare. L'uso di una semplice runtimeexception rende più difficile per il chiamante determinare cosa è andato storto, ma se il chiamante sta cercando di determinare cosa è andato storto, ciò potrebbe indicare che non avresti dovuto modificare l'eccezione per renderla non selezionata.


0

In una domanda booleana, è difficile rispondere in modo diverso dopo due risposte controverse, ma vorrei darti una prospettiva che, anche menzionata in alcuni punti, non è stata sottolineata abbastanza per l'importanza che ha.

Con gli anni ho scoperto che qualcuno è sempre confuso riguardo a un problema banale, a cui manca la comprensione di alcuni dei fondamenti.

Stratificazione. Un'applicazione software (almeno dovrebbe essere) una pila di strati uno sopra l'altro. Una aspettativa importante per una buona stratificazione è che i livelli inferiori forniscono funzionalità per componenti potenzialmente multipli dal livello superiore.

Supponiamo che la tua app abbia i seguenti livelli dal basso verso l'alto NET, TCP, HTTP, REST, DATA MODEL, BUSINESS.

Se il tuo livello aziendale desidera eseguire una chiamata di riposo ... attendi un secondo. Perché l'ho detto? Perché non ho detto richiesta HTTP o transazione TCP o inviato pacchetti di rete? Perché quelli sono irrilevanti per il mio livello aziendale. Non li gestirò, non li guarderò nei dettagli. Sto perfettamente bene se sono profonde le eccezioni che ricevo come causa e non voglio sapere che esistono.

Inoltre, è un male se conosco i dettagli, perché se domani vorrei cambiare i protocolli di trasporto di sottolineatura che trattano i dettagli specifici del protocollo TCP significa che la mia astrazione REST non ha fatto un buon lavoro per sottrarsi l'implementazione specifica.

Quando si passa un'eccezione da un livello all'altro è importante rivisitare ogni suo aspetto e che senso avrà per l'astrazione fornita dal livello attuale. Potrebbe essere di sostituire l'eccezione con altre, potrebbe combinare diverse eccezioni. Potrebbe anche trasferirli da controllato a non selezionato o viceversa.

Certo, è vero che i luoghi che hai citato hanno senso è una storia diversa, ma in generale - sì, potrebbe essere una buona cosa da fare.


-2

Secondo me,

A livello di framework, dovremmo essere eccezioni di runtime catch per ridurre più blocchi di try catch per l'invocatore nello stesso posto.

A livello di applicazione, raramente acquisiamo eccezioni di runtime e penso che questa pratica sia stata negativa.


1
E cosa farai con queste eccezioni a livello di framework?
Matthieu,

Se nel framework esiste un livello dell'interfaccia utente in grado di gestire le eccezioni, l'interfaccia utente presenterà un messaggio di errore di qualche tipo che qualcosa è andato storto. Nel caso di un'app javascript di una pagina, l'app potrebbe presentare un messaggio di errore. Concesso, il livello dell'interfaccia utente dovrebbe gestire l'errore solo se un livello più profondo non è in grado di ripristinare l'errore.
Jake Toronto,
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.