Stiamo creando un SDK Java per semplificare l'accesso a uno dei nostri servizi che forniscono un'API REST. Questo SDK deve essere utilizzato da sviluppatori di terze parti. Sto facendo fatica a trovare il modello migliore per implementare la gestione degli errori nell'SDK che si adatta meglio al linguaggio Java.Gestione degli errori su Java SDK per il servizio API REST
Diciamo che abbiamo il resto dell'endpoint: GET /photos/{photoId}
. Questo può restituire i seguenti codici di stato HTTP:
- 401: l'utente non è autenticato
- 403: L'utente non dispone dell'autorizzazione per accedere a questa foto
- 404: Non c'è foto con quella id
Il servizio simile a questa:
interface RestService {
public Photo getPhoto(String photoID);
}
I Nel codice sopra non sto ancora affrontando la gestione degli errori. Ovviamente voglio fornire un modo al client del sdk per sapere quale errore si è verificato, per poterci potenzialmente recuperare. La gestione degli errori in Java è fatta usando Eccezioni, quindi andiamo con quello. Tuttavia, qual è il modo migliore per farlo usando le eccezioni?
1. Avere un'unica eccezione con informazioni sull'errore.
public Photo getPhoto(String photoID) throws RestServiceException;
public class RestServiceException extends Exception {
int statusCode;
...
}
Il cliente del SDK potrebbe allora fare qualcosa del genere:
try {
Photo photo = getPhoto("photo1");
}
catch(RestServiceException e) {
swtich(e.getStatusCode()) {
case 401 : handleUnauthenticated(); break;
case 403 : handleUnauthorized(); break;
case 404 : handleNotFound(); break;
}
}
Comunque io non mi piace molto questa soluzione principalmente per 2 motivi:
- Osservando la firma del metodo lo sviluppatore non ha idea del tipo di situazioni di errore che potrebbe dover gestire.
- Lo sviluppatore deve gestire direttamente i codici di stato HTTP e sapere cosa significano nel contesto di questo metodo (ovviamente se vengono utilizzati correttamente, molte volte il significato è noto, tuttavia potrebbe non essere sempre il Astuccio).
2. Avere una gerarchia di classi di errori
La firma del metodo rimane:
public Photo getPhoto(String photoID) throws RestServiceException;
Ma ora creare eccezioni per ogni tipo di errore:
public class UnauthenticatedException extends RestServiceException;
public class UnauthorizedException extends RestServiceException;
public class NotFoundException extends RestServiceException;
Ora il client dell'SDK potrebbe quindi fare qualcosa del genere:
try {
Photo photo = getPhoto("photo1");
}
catch(UnauthenticatedException e) {
handleUnauthorized();
}
catch(UnauthorizedException e) {
handleUnauthenticated();
}
catch(NotFoundException e) {
handleNotFound();
}
Con questo approccio lo sviluppatore non ha bisogno di conoscere i codici di stato HTTP che hanno generato gli errori, deve solo gestire le eccezioni Java. Un altro vantaggio è che lo sviluppatore può solo rilevare le eccezioni che desidera gestire (a differenza della precedente situazione in cui avrebbe dovuto catturare la singola eccezione (RestServiceException
) e solo allora decidere se volerlo affrontare o meno).
Tuttavia, c'è ancora un problema. Osservando la firma del metodo, lo sviluppatore non ha ancora idea del tipo di errori che potrebbe dover gestire perché abbiamo solo la super-classe nella firma del metodo.
3. Avere una gerarchia di classi di errori + loro lista nella firma del metodo di
Ok, quindi quello che viene in mente ora è quello di cambiare la firma del metodo per:
public Photo getPhoto(String photoID) throws UnauthenticatedException, UnauthorizedException, NotFoundException;
Tuttavia, è possibile che in futuro nuove situazioni di errore possano essere aggiunte a questo punto finale di riposo. Ciò significherebbe aggiungere una nuova Eccezione alla firma del metodo e ciò rappresenterebbe una violazione della java api. Ci piacerebbe avere una soluzione più robusta che non comporterebbe la violazione delle modifiche all'API nella situazione descritta.
4. Avere una gerarchia di classi di errori (utilizzando eccezioni unchecked) + elencarli nella firma del metodo di
Quindi, per quanto riguarda le eccezioni non selezionati? Se cambiamo il RestServiceException di estendere la RuntimeException:
public class RestServiceException extends RuntimeException
E continuiamo la firma del metodo:
public Photo getPhoto(String photoID) throws UnauthenticatedException, UnauthorizedException, NotFoundException;
In questo modo posso aggiungere nuove eccezioni alla firma del metodo senza infrangere il codice esistente. Tuttavia, con questa soluzione lo sviluppatore non è costretto a rilevare alcuna eccezione e non si accorgerà che ci sono situazioni di errore che deve gestire finché non legge attentamente la documentazione (sì, giusto!) O ha notato le eccezioni presenti nel metodo firma.
Qual è la migliore pratica per la gestione degli errori in questo tipo di situazioni?
Ci sono altre (migliori) alternative a quelle che ho citato?
Stai facendo questo SDK per Android o per tutte le app java? – 4gus71n
La domanda è interessante ma soggettiva, no? Voglio sia votare e votare per chiudere, ma farò solo il primo. –
@MiserableVariable Penso che la SO sia stata specifica, "Ci sono altre (migliori) alternative a quelle che ho menzionato?" non ha detto qualcosa del tipo "Come posso gestire i codici di errore nella mia implementazione del client http?". Non so, è la mia opinione. Inoltre mostra segni di ricerche. – 4gus71n