È una cattiva pratica lanciare più eccezioni personalizzate in Java? [duplicare]

5

Sto sviluppando un'applicazione web Java. È un'architettura a tre livelli:

web > servizio > repository.

Sto pensando di creare molte eccezioni, ciascuna specifica per ogni singolo errore e nel livello di servizio in cui risiede la mia logica aziendale. Voglio generare eccezioni specifiche legate all'errore aziendale.
E nel livello web (più in alto nella pila dove è più vicino al front-end) è dove lo sto prendendo e gestendo di conseguenza.

Qualcuno mi ha detto, non farlo in questo modo perché è una cattiva pratica e mi ha consigliato di lanciare una sola eccezione di business generico invece - ed è stato inflessibile che aveva ragione. Quando ho sentito questo, la mia reazione è stata che va contro tutte le cose che ho imparato all'università, le esperienze passate e le cose che ho letto nei libri di tecnologia comuni.

    
posta SoftwareDeveloper 06.11.2015 - 22:41
fonte

5 risposte

7

Is it bad practice to throw multiple custom exceptions in Java?

No. È una buona pratica.

L'unica situazione in cui più eccezioni potrebbero essere (leggermente) una cattiva idea è se non c'è assolutamente alcuna possibilità (mai!) di individuare le singole eccezioni; cioè le eccezioni a grana fine non servono a scopi funzionali. Tuttavia, la mia opinione è che se riesci a fare quella affermazione, allora probabilmente c'è qualcosa di sbagliato nel modo in cui tu / il tuo team state usando Java. E il contro-argomento è che l'uso ragionevole di più eccezioni personalizzate ti aiuterà a documentare le API ... anche se non farai mai più di catch-log-and-bail-out in fase di runtime.

Questo non vuol dire che molte eccezioni personalizzate saranno sempre buone:

  • Se esagerate e create un'eccezione separata per tutto, probabilmente aggiungerete complessità non necessaria. (In molti casi, sono sufficienti messaggi di eccezione diversi.)

  • Se non si dispone di una gerarchia di ereditarietà sensibile per le eccezioni personalizzate, si rischia di rimpiangerlo. (Una gerarchia ben progettata consente di catturare "classi" di eccezioni o dichiarare metodi come lanciarli. Può semplificare il codice.)

risposta data 07.11.2015 - 00:45
fonte
7

Is it bad practice to throw multiple custom exceptions in Java?

In generale: No. Perché dovrebbe?

Come tutto: l'astrazione è tua amica.

È necessario avere un'eccezione CustomerNotFound e un'eccezione ProductNotFound ? Oppure i tuoi requisiti sono solo un astratto NotFoundException ? Il contesto potrebbe aiutare a determinare, cosa mancava. Avere diverse eccezioni per il gusto di averle è una sciocchezza.

È necessario che ogni livello della tua applicazione abbia eccezioni personalizzate? Le eccezioni sono un modo per segnalare che un'azione intenzionale non è riuscita a causa di qualche motivo.

  • Supponiamo che tu abbia un controller che chiede al livello di servizio di recuperare i dati, che a sua volta chiede al layer DA di leggere i valori dal DB. resultset è vuoto . Il servizio ottiene il set di risultati vuoto e genera un NotFoundException che il servizio comunica, il fallimento dell'azione a causa di un risultato mancante.

  • Supponiamo che il controllore abbia bisogno del servizio per eseguire gli stipendi per i dipendenti. E al servizio viene chiesto di fare il libro paga per il dipendente con ID 123456 , e a sua volta chiede a un servizio di recuperare il dipendente - ma non è stato possibile trovare alcun dipendente.

Ci sono due modi per affrontarlo:

1) Lanciate un'eccezione NotFound nel layer DA, prendetela nel servizio payroll e rilanciate un PayrollServiceException avvolgendo NotFoundException con il messaggio Exmployee could not be found

2) Lanciate un'eccezione NotFound nel layer DA e non catturate il servizio di gestione stipendi e rilevate invece un livello sopra.

Vorrei andare per (2), dal momento che in (1) l'informazione, che l'azione fallita a causa di un impiegato mancante è ridondante.

    
risposta data 06.11.2015 - 23:42
fonte
4

Sto guardando l'applicazione Spring che ho qui seduto e ci sono alcune dozzine di eccezioni personalizzate. Gran parte di ciò è dovuto al fatto che con Spring, le eccezioni possono arrivare fino al livello framework e quindi essere ben tradotte dal framework nel corrispondente codice di stato HTTP.

  • Le righe mancanti sono la loro struttura di classe - MissingRowException è una classe astratta. C'è anche un posto per la SQLException avvolta corrispondente.
    • Riga non trovata? Questa è una FooMissingException che diventa 404.
    • Riga della barra non trovata nel database? Questa è una BarMissingException che diventa anche un 404.
  • Gli errori di convalida sono la loro propria struttura di classe di eccezione
  • Gli errori di sistema sono un'altra struttura di classe di eccezione (ce n'è una qui denominata DatabaseBorkedException - che è un errore 500)
  • E così via
  • Non voglio nemmeno pensare a quante piccole eccezioni sono prive di classi interne private ai controller perché vengono utilizzate solo all'interno di quel controller (salva, non c'è motivo di andare oltre, inviare una bella pagina personalizzata).

Noterai che ci sono alberi di eccezioni. Questi hanno una radice comune e posso semplicemente lanciare GenericBusinessException di livello superiore (che non è astratto). Nota che facendo che l'eccezione registra un messaggio informativo su chi lo ha fatto e ha anche un avviso pmd quando lo guardi con analisi statiche - ma a volte devi tagliare gli angoli e prendere un po 'di tecnica debito e basta lanciare la semplice eccezione ora per farlo uscire dalla porta piuttosto che tutti gli altri lavori per le altre eccezioni.

Se l'interezza della gestione dell'eccezione è sufficiente registrarla, si può considerare che scrivere tutte queste eccezioni è una perdita di tempo. E in alcune situazioni, sarei d'accordo. Tuttavia, se hai una gestione diversa per ogni eccezione a un certo livello, la tua alternativa è lanciare un enum in un campo dell'eccezione o digitare genericamente GenericBusinessException e non fare realmente nulla al riguardo.

Le eccezioni personalizzate aggiungono significato e consentono al codificatore di esprimere più chiaramente l'intento del codice. Permette a un manutentore di (se le eccezioni sono usate in un modo su cui si può ragionare) per seguire più rapidamente il flusso di un'applicazione. In questa misura, sono abbastanza buoni e utili.

    
risposta data 06.11.2015 - 22:54
fonte
1

Ricorda che un'eccezione è dopotutto solo una classe, che può avere campi di istanza e metodi propri mentre estendono alcuni aspetti di Exception o implementano Throwable.

Dico questo perché penso che avere un'eccezione definita per ogni singola condizione di errore possa essere un livello inappropriato di specificità per una classe, quando in realtà ciò che potrebbe servire meglio è avere una piccola manciata di eccezioni che coprono categorie distinte di tipi di errore e che ti consentono di includere dettagli che forniscono la specificità.

Generalmente, crei un tipo di eccezione per ogni diverso modo in cui gestirai le eccezioni generate.

    
risposta data 06.11.2015 - 23:34
fonte
1

Nella mia esperienza (sono uno sviluppatore Java da oltre 10 anni), è cattiva pratica. Non che sia un odore di codice, ma spesso ti ostacola nel tuo lavoro quotidiano.

Pensa a un'applicazione che tenta di leggere un file e probabilmente genera FileNotReadableException . Dopo un po 'ti rendi conto che il file potrebbe non essere leggibile a causa di diritti di accesso insufficienti. cosa fai? Cambia il nome dell'eccezione - no, potrebbe essere ancora in uso. Aggiungi un sottotipo FileNotReadableBecauseOfAccessRightsException ? Bene, questo è piuttosto 2 errori - non leggibili + diritti di accesso, ma la causa principale è la cosa dei diritti. Quindi aggiungi un InsufficientAccessRightsException da qualche altra parte nell'albero delle classi. Nel fare ciò, devi anche cambiare il codice in cui è stata rilevata l'eccezione originale dai suoi 2 diversi tipi ora (una violazione del principio "aperto-chiuso"). E così via ... E qual è il guadagno? ... a differenza di un'eccezione con un messaggio? Sicurezza statica. Nel contesto delle eccezioni è utile solo per evitare errori di battitura. Uno sviluppatore potrebbe comunque utilizzare un tipo di eccezione errato (ad esempio EntryNotFoundException anziché FileNotReadableException ).

Come detto da dwoz: un'eccezione è solo una classe.

La mia esperienza è che poche eccezioni sono sufficienti. Ciò che si desidera esprimere sono messaggi di errore: per diversi messaggi è necessaria solo un'eccezione (di runtime) con un campo String. Tutte le eccezioni dovrebbero essere catturate da un gestore di errori predefinito al livello più alto possibile (o prima se necessario).

Oltre al solito messaggio, a volte è necessario memorizzare più informazioni, come un percorso del filesystem, un nome utente, un id-dispositivo, un uuid per tracciare più facilmente l'errore in un sistema distribuito, ecc. per tali scopi suggerisco per creare classi di eccezioni personalizzate.

Come detto da Amon, una regola empirica dovrebbe essere: per librerie utilizzare (alcune) eccezioni, per (web-) applicazioni us il meno possibile

    
risposta data 07.11.2015 - 07:05
fonte

Leggi altre domande sui tag