comportamento del client REST determinato dal tipo di parametro

2

È generalmente riconosciuto che sovraccaricare un metodo non dovrebbe cambiare il suo comportamento, ma quanto del comportamento di un metodo dovrebbe essere mantenuto coerente?

Prendi ad esempio un client API REST che è responsabile dell'interazione con due diversi endpoint. Entrambi utilizzano una richiesta POST, condividono lo stesso URL di base e accettano le stesse intestazioni. L'unica differenza è il carico utile (e ovviamente gli endpoint stessi). Se si dovesse seguire rigorosamente la suddetta regola di incapsulare un singolo comportamento sotto lo stesso nome del metodo, si potrebbe creare un client simile a quello sottostante:

public class RestClient {

    private final String API_A = "http://api.somecompany.com/a";
    private final String API_B = "http://api.somecompany.com/b";

    RestTemplate restTemplate;

    public ResponseA postA(RequestA request) {
        HttpHeaders headers = getHeaders();
        HttpEntity<RequestA> request = new HttpEntity<>(request, headers);
        return postForObject(API_A, request, ResponseA.class);
    }

    public ResponseB postB(RequestB request) {
        HttpHeaders headers = getHeaders();
        HttpEntity<RequestB> request = new HttpEntity<>(request, headers);
        return postForObject(API_B, request, ResponseB.class);
    }

    private HttpHeaders getHeaders() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
        return headers;
    }
}

Questo sembra giusto ma anche un po 'sciocco a causa di quanto simili siano i metodi. Perché non utilizzare lo stesso nome del metodo e modificare semplicemente il tipo di richiesta e risposta? Questo non implica che venga chiamato l'endpoint? dovrebbe esserci un client separato per ciascun endpoint?

    
posta Dan Banks 16.01.2018 - 18:15
fonte

1 risposta

2

Raccomando di mantenere entrambi i metodi, ma delegando la logica effettiva a un metodo di helper privato:

public ResponseA postA(RequestA request) {
    return executeRequest<ResponseA, RequestA>(API_A, request);
}

public ResponseB postB(RequestB request) {
    return executeRequest<ResponseB, RequestB>(API_B, request);
}

private TResponse executeRequest<TResponse, TRequest>(string api, TRequest request) {
    // ...
}

Per il chiamante, quelle sono due richieste diverse. Il fatto che abbiano un'implementazione simile è un dettaglio irrilevante.

Inoltre, se in futuro postA deve fare qualcosa di diverso da postB , è solo una modifica locale. Se lasci che i chiamanti accedano direttamente al metodo comune, le modifiche potrebbero essere distribuite su tutto il codice base.

    
risposta data 17.01.2018 - 20:27
fonte

Leggi altre domande sui tag