Progettazione oggetto per il risultato REST, inclusa la gestione degli errori

3

Non sono sicuro di quale sia il miglior design per la restituzione di un oggetto che sia in grado di restituire un risultato per le chiamate REST di successo o per le chiamate REST non riuscite.

Attualmente sto pensando a qualcosa di simile (scritto in Java):

public class ResultDTO<T> {
    public enum Status {
        SUCCESS, FAILURE
    }

    private Status status;
    private String message;
    private T result;
}

Quindi può essere usato come:

return new ResultDTO<User>(Status.SUCCESS, "", new User("john doe")); // Correct usage of API
return new ResultDTO<User>(Status.FAILURE, "Invalid e-mail", null); // Incorrect usage of API

Ma non sono abbastanza sicuro di questo design. Qualcuno ha qualche esperienza con la progettazione di oggetti per API REST e può raccomandarmi qualcosa?

    
posta Jelle 01.12.2016 - 23:57
fonte

1 risposta

3

È difficile fornire una risposta definitiva a questo perché REST è uno "stile" di creazione di applicazioni e perché non si fornisce un contesto sufficiente su come funziona l'applicazione per produrre i risultati, ma cercherò comunque di offrire alcuni consigli.

È positivo che tu voglia utilizzare un modo omogeneo per presentare tutti i risultati, che siano di successo o di errore, ma non dovresti rappresentarli entrambi con la stessa classe. Prendi questo codice per esempio:

new ResultDTO<User>(Status.SUCCESS, "", new User("john doe"));
new ResultDTO<User>(Status.FAILURE, "Invalid e-mail", null);

Vedi qualcosa di sbagliato in questo? Le uniche informazioni utili qui sono new User("john doe") e "Invalid e-mail" . Il resto è rumore. Avere una stringa vuota per il messaggio nel caso di successo, e un risultato nullo nel caso di errore sono un omaggio che i risultati dovrebbero essere esclusivi, qualcosa del tipo:

new SuccesfulResult<User>(new User("john doe"));
new ErrorResult("Invalid e-mail");

Il tuo codice potrebbe trasformarsi in questo per riflettere la nuova semantica:

public abstract class AbstractResult {
    public enum Status {
        SUCCESS, FAILURE
    }

    private final Status status;

    protected AbstractResult(Status status) {
        this.status = status;
    }

    private final Status getStatus() {
        return this.status;
    }
}

public class SuccesfulResult<T> extends AbstractResult {
    private T result;

    public SuccesfulResult(T result) {
        super(AbstractResult.Status.SUCCESS);
        this.result = result;
    }

    // ...
}

public class ErrorResult extends AbstractResult {
    private final String message;

    public ErrorResult(String message) {
        super(AbstractResult.Status.FAILURE);
        this.message = message;
    }

    // ...
}

È molto più codice da scrivere, ma lo scrivi una volta. Lo chiamerai molte più volte nella tua applicazione e batte sempre digitando "" e null dappertutto.

Ora, riguardo al commento sulla tua domanda. Non fare questa parte del tuo dominio. Il T result fa parte del tuo dominio. Il resto sono solo metadati che accompagnano il risultato in modo che il client sappia se si tratta di una chiamata riuscita o fallita. La tua applicazione dovrebbe funzionare con T (qualunque cosa rappresenti) e aggiungere solo i metadati del risultato quando si effettua il marshalling della risposta per il client. I framework possono aiutarti, soprattutto per la gestione degli errori. Nel codice dell'applicazione potresti throw un'eccezione, quindi consenti al framework di acquisirlo e trasformarlo in new ErrorResult(...) in base a una mappatura fornita.

Qui sopra sono le mie osservazioni sul codice che hai postato. Per ulteriori informazioni, prova a cercare "buona progettazione dell'API REST" e / best practice per la gestione degli errori nelle API rest ". Troverai più informazioni là fuori che potresti non avere, e potrebbe essere più utile di qualsiasi soluzione che ricevi su questo post.

    
risposta data 02.12.2016 - 20:47
fonte

Leggi altre domande sui tag