Lanciare eccezioni personalizzate nella libreria: faccio a lanciare quelle concrete o la loro superclasse?

0

Sto progettando una libreria che astrae un tipico servizio http CRUD chiamato FooService.

In questa libreria sto lanciando diverse eccezioni come FooServiceClientException per errori relativi alla rete o FooServiceObjectNotFound quando provo a recuperare un oggetto con un ID non esistente. Ho anche un FooServiceException da cui tutto l'altro FooService*Exception eredita.

Quindi fondamentalmente la domanda è quale eccezione (i) dovrebbero usare i metodi pubblici di questa libreria?

// throwing the generic FooServiceException
public FooObject getById(int id) throws FooServiceException {...}

// throwing concrete ones
public FooObject getById(int id)
       throws FooServiceClientException, FooServiceObjectNotFoundException {...}

PS: in questo caso la libreria verrebbe scritta in Java, se la lingua potrebbe influenzare le risposte a causa di approcci diversi in lingue diverse.

    
posta Carlos Campderrós 04.04.2018 - 11:01
fonte

2 risposte

3

Lanciare un'eccezione generica come FooServiceException rende la firma del metodo facile da leggere, ma si presume anche che il chiamante probabilmente non vorrà differenziarsi. Se lo facesse, potrebbe ancora farlo, ma dovrà rubare il codice per scoprire quali implementazioni specifiche di FooServiceException vengono lanciate. Non fare il chiamante farlo! Ecco perché non possiamo avere cose carine!

D'altra parte, se il tuo metodo getById sta lanciando FooConnectionTimeoutException, FooConnectionPoolExhaustedException, FooTableNotFoundException, FooServiceObjectNotFoundException , chiaramente qualcosa non va bene in questo caso. Ma non temere più, mio buon OP! C'è una soluzione.

Puoi organizzare eccezioni per tipo, quindi lanciare un'eccezione ragionevolmente generica per ogni tipo possibile. In altre parole, avere FooConnectionTimeoutException, FooConnectionPoolExhaustedException, FooTableNotFoundException deriva da FooDatabaseException . La firma del metodo diventa quindi:

getById(int id) throws FooServiceObjectNotFoundException, FooDatabaseException;

Vedi com'è bello? I chiamanti che desiderano coprire tutte le eccezioni non andrebbero oltre la gestione di solo FooServiceObjectNotFoundException e FooDatabaseException . I chiamanti che desiderano eseguire un'azione diversa su FooServiceObjectNotFoundException non possono farne a meno.

Puoi organizzarti ulteriormente secondo necessità, se vuoi essere più dettagliato, ma il livello di dettaglio dipende interamente da te. Il punto chiave è che hai il pieno controllo su quanto specifici vuoi che siano le tue eccezioni. Come regola generale, prova a ridurre il numero di eccezioni generate a 3 o meno. Qualunque cosa al di là di questo è in qualche modo inutile, specialmente se molte delle eccezioni sono correlate allo stesso tipo di problema (problemi imprevisti, errori di business, input non validi, ecc.).

    
risposta data 04.04.2018 - 11:44
fonte
0

La specifica delle eccezioni è un addendum al valore di ritorno, quindi dovrebbe seguire linee guida simili.

Suggerirei di utilizzare il tipo meno specifico che soddisfi le esigenze del codice che consuma. Nel tuo caso potrebbe essere FooServiceException , ma è ugualmente plausibile che Exception o Throwable sia sufficiente. Non dettagli i membri di FooServiceException , quindi non posso dirlo.

    
risposta data 04.04.2018 - 11:07
fonte

Leggi altre domande sui tag