Consideriamo la situazione in cui si dispone del codice fornito di:
public void delete() throws IOException, SQLException { // Non-Compliant
/* ... */
}
Il pericolo qui è che il codice che scrivi per chiamare delete()
sarà simile a:
try {
foo.delete()
} catch (Exception e) {
/* ... */
}
Anche questo è male. E verrà catturato con un'altra regola che contrassegna la cattura della classe Exception di base.
La chiave è non scrivere codice che ti fa venir voglia di scrivere codice errato altrove.
La regola che stai incontrando è piuttosto comune. Checkstyle lo ha nelle sue regole di progettazione:
ThrowsCount
Limita genera istruzioni per un conteggio specificato (1 per impostazione predefinita).
Razionale: le eccezioni fanno parte dell'interfaccia di un metodo. Dichiarare un metodo per generare troppe eccezioni con radici diverse rende onerosa la gestione delle eccezioni e porta a pratiche di programmazione scadenti come la scrittura di codice come catch (Exception ex). Questo controllo costringe gli sviluppatori a inserire le eccezioni in una gerarchia tale che, nel caso più semplice, un chiamante deve controllare solo un tipo di eccezione, ma eventuali sottoclassi possono essere individuate in modo specifico se necessario.
Questo descrive esattamente il problema e qual è il problema e perché non dovresti farlo. È uno standard ben accettato che molti strumenti di analisi statica identificheranno e contrassegneranno.
E mentre si può farlo secondo il disegno la lingua, e ci possono essere momenti in cui è la cosa giusta da fare, è qualcosa che si dovrebbe vedere e andare immediatamente "um, perché sto facendo questo?" Può essere accettabile per il codice interno in cui tutti sono abbastanza disciplinati da non farlo mai catch (Exception e) {}
, ma il più delle volte ho visto persone tagliare angoli soprattutto in situazioni interne.
Non indurre le persone che usano la tua classe a voler scrivere codice errato.
Vorrei sottolineare che l'importanza di questo è ridotta con Java SE 7 e versioni successive perché una singola istruzione catch può catturare più eccezioni ( Cattura di più tipi di eccezioni e Rrowrow Eccezioni con il controllo del tipo migliorato da Oracle).
Con Java 6 e precedenti, avresti un codice simile a:
public void delete() throws IOException, SQLException {
/* ... */
}
e
try {
foo.delete()
} catch (IOException ex) {
logger.log(ex);
throw ex;
} catch (SQLException ex) {
logger.log(ex);
throw ex;
}
o
try {
foo.delete()
} catch (Exception ex) {
logger.log(ex);
throw ex;
}
Nessuna di queste opzioni con Java 6 è l'ideale. Il primo approccio viola DRY . Più blocchi fanno la stessa cosa, ancora e ancora - una volta per ogni eccezione. Vuoi registrare l'eccezione e riproporla? Ok. Le stesse righe di codice per ogni eccezione.
La seconda opzione è peggiore per diversi motivi. Innanzitutto, significa che stai rilevando tutte le eccezioni. Il puntatore null viene catturato lì (e non dovrebbe). Inoltre, stai ricodificando un Exception
che significa che la firma del metodo sarebbe il deleteSomething() throws Exception
che crea un pasticcio più in alto nello stack come le persone che usano il tuo codice sono ora costrette a fare catch(Exception e)
.
Con Java 7, questo non è così importante perché puoi invece fare:
catch (IOException|SQLException ex) {
logger.log(ex);
throw ex;
}
Inoltre, il tipo di controllo, se si fa prendere il tipo di eccezioni essere gettato:
public void rethrowException(String exceptionName)
throws IOException, SQLException {
try {
foo.delete();
} catch (Exception e) {
throw e;
}
}
Il verificatore di tipi riconoscerà che e
possono essere solo di tipi IOException
o SQLException
. Non sono ancora troppo entusiasta dell'uso di questo stile, ma non sta causando un codice errato come lo era in Java 6 (dove ti costringerebbe ad avere la firma del metodo come la superclasse estesa dalle eccezioni).
Nonostante tutte queste modifiche, molti strumenti di analisi statica (Sonar, PMD, Checkstyle) stanno ancora applicando le guide di stile Java 6. Non è una brutta cosa. Tendo a concordare con un avvertimento che devono ancora essere applicati, ma potresti cambiare la priorità in maggiore o minore in base a come il tuo team ha la priorità.
Se le eccezioni devono essere controllati o incontrollato ... che è una questione di g r all'e una t dibattito che si può facilmente trovare innumerevoli post del blog che occupano ciascun lato della discussione. Tuttavia, se si lavora con eccezioni verificate, probabilmente si dovrebbe evitare di lanciare più tipi, almeno in Java 6.