Quando dovremmo creare le nostre classi di eccezioni java?

da un buon punto di vista di progettazione / pratica, quando dovremmo creare e utilizzare classi di eccezioni java personalizzate invece di quelle già predefinite in java?

In alcune applicazioni vedo quasi nessuna o nessuna class di eccezioni personalizzate create, si sforzano di utilizzare sempre le eccezioni java native. D’altra parte, ci sono alcune applicazioni che definiscono eccezioni personalizzate per tutto.

Qual è la migliore pratica?

Grazie!

Dalle migliori pratiche per la gestione delle eccezioni :

Cerca di non creare nuove eccezioni personalizzate se non hanno informazioni utili per il codice client.

Cosa c’è di sbagliato con il seguente codice?

public class DuplicateUsernameException extends Exception {} 

Non fornisce alcuna informazione utile al codice cliente, se non un nome di eccezione indicativo. Non dimenticare che le classi Java Exception sono come le altre classi, in cui puoi aggiungere metodi che ritieni che il codice client invocherà per ottenere maggiori informazioni.

Potremmo aggiungere metodi utili a DuplicateUsernameException , ad esempio:

 public class DuplicateUsernameException extends Exception { public DuplicateUsernameException (String username){....} public String requestedUsername(){...} public String[] availableNames(){...} } 

La nuova versione fornisce due metodi utili: requestedUsername() , che restituisce il nome richiesto e availableNames() , che restituisce una matrice di nomi utente disponibili simili a quella richiesta. Il client potrebbe utilizzare questi metodi per informare che il nome utente richiesto non è disponibile e che altri nomi utente sono disponibili. Ma se non hai intenzione di aggiungere ulteriori informazioni, allora basta lanciare un’eccezione standard:

 throw new IllegalArgumentException("Username already taken"); 

da un buon punto di vista di progettazione / pratica, quando dovremmo creare e utilizzare classi di eccezioni java personalizzate invece di quelle già predefinite in java?

Quando i nomi delle eccezioni esistenti non coprono le tue necessità.

Un’altra preoccupazione progettuale è estendere la “buona” class di eccezione; per esempio, se si alza un’eccezione relativa a I / O, si dovrebbe idealmente ereditare IOException ; se l’eccezione indica un errore del programmatore, è necessario ereditare RuntimeException (ad esempio, rendere l’eccezione non selezionata).

L’aumento delle eccezioni personalizzate consente anche di trattare le eccezioni in modo più preciso; per esempio, se hai definito FooException ereditando IOException , puoi avere un trattamento speciale per questo:

 try { ... } catch (FooException e) { ... } // Catch it _before_ IOException! catch (IOException e) { ... } 

Inoltre, le eccezioni sono classi come le altre, quindi puoi aggiungere metodi personalizzati ecc; per esempio, Jackson definisce JsonProcessingException che eredita IOException . Se si cattura, è ansible ottenere informazioni sulla posizione dell’errore di analisi utilizzando .getLocation() .

certamente quando si prevede di essere in grado di gestire in modo programmatico un’eccezione, ovvero è facile creare istruzioni catch separate per diversi tipi di eccezioni, ovvero:

 try{ buyWidgets(); } catch(AuthenticationException ex) { promptForLogin(); } catch(InsufficientFundsException ex) { promptToRefillAccount(); } //let other types of exceptions to propagate up the call stack 

Sulla questione se quanto sopra costituisce un uso inappropriato dell’eccezione per il controllo del stream

Sebbene le eccezioni siano più costose della CPU rispetto alle dichiarazioni if-else (principalmente a causa del costo di costruzione di una traccia dello stack), il costo è relativo e dovrebbe essere valutato nel contesto di casi d’uso particolari. Non tutti i pezzi di codice devono essere veloci via web e alcune persone trovano che leggere e testare le condizioni siano più complicati. Ad esempio, quasi tutti i gestori delle transazioni implementano gli idiomi di commit-rollback-retry utilizzando le eccezioni. (Provare a scrivere un aspetto di riprova della transazione senza rilevare un’eccezione)

Separatamente, si dovrebbe rispettare il principio della separazione delle preoccupazioni: non ogni parte del codice deve occuparsi di ogni ansible condizione. Se non si effettua l’accesso mentre si acquistano i widget, si tratta di un caso eccezionale che dipende in realtà dall’app e dal luogo particolare nel codice base dell’app. Ad esempio, potresti avere un servizio con le operazioni per gli utenti loggati. Non ha senso che i metodi in quel servizio gestiscano l’autenticazione – invece questi metodi si aspetterebbero codice prima nella catena di chiamate per garantire che l’utente sia autenticato, e quindi semplicemente lanciare eccezioni se non è così. Quindi, per quei metodi che non sono registrati è un caso eccezionale.

Spesso creo eccezioni personalizzate se ci sono più informazioni che devo trasmettere invece di un semplice messaggio di errore.

Ad esempio, codici di errore particolari o valori effettivi rispetto a quelli previsti. questi possono anche avere i propri getter in modo da poter recuperare questi campi in modo programmato senza dover analizzare il messaggio String che potrebbe interrompersi se si cambia il testo del messaggio. (O traducilo in un’altra lingua)

Se crei le tue eccezioni, ti consiglio di estendere il JDK comune integrato nelle eccezioni, in modo che l’API possa dire MycustomIOException throws IOException ma in realtà genera MycustomIOException . in questo modo gli utenti della tua API non devono conoscere le tue versioni personalizzate a meno che non lo desiderino.

È utile disporre di eccezioni personalizzate nell’applicazione, una può essere un’eccezione personalizzata di livello superiore per le applicazioni, altre ai livelli del modulo / pacchetto. Se si dispone di qualche funzione / operazione specifica nell’app e occorre che l’utente sappia se si è verificata un’eccezione durante l’operazione, è meglio aggiungere un’eccezione personalizzata per tale operazione. Sarà facile eseguire il debug / investigare i problemi.