2

It is generally agreed that overloading a method should not change its behavior, but how much of a method's behavior should be kept consistent?

Take for example a REST API client which is responsible for interacting with two different endpoints. Both consume a POST request, share the same base URL, and accept the same headers. The only difference is the payload (and of course the endpoints themselves). If one were to strictly follow the aforementioned rule of encapsulating a single behavior under the same method name, a client similar to the one below may be created:

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;
    }
}

This seems alright but also a little silly because of how similar the methods are. Why not use the same method name and just change the request and response type? Will this not imply the endpoint being called? should there be a separate client for each endpoint?

4
  • 1
    Are we talking about having the same URL for 2 different resources? Like apples and oranges from the same URL? While they are both fruit they don't behave or look the same. That sounds like confusion waiting to happen. Please help me understand what you are really after here. – Berin Loritsch Jan 16 '18 at 17:21
  • @BerinLoritsch I am talking about two different URLs which have the same behavior from the perspective of the client. The response payload is different, but the REST client does not read or modify it and just passes it up the stack. The only change in behavior between the two methods is the URL being called and the request/response being marshalled/unmarshalled. – HelloHello Jan 17 '18 at 15:55
  • So this is about assigning the same handler in code to multiple URLs to avoid a lot of boiler plate code? If so, that is likely very framework specific. Usually you would use some sort of routing mechanism to achieve this, but I don't even know what language you are using, much less framework. – Berin Loritsch Jan 17 '18 at 16:37
  • there is a very obvious solution using Generics for this. – user7519 Jan 17 '18 at 19:45
2

I would recommend keeping both methods, but delegating the actual logic to a private helper method:

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) {
    // ...
}

To the caller, those are two different requests. The fact that they have a similar implementation is an irrelevant detail.

Also, if in the future postA has to do something other than postB, it's only a local change. If you let the caller(s) access the common method directly, the changes may be spread all over the code base.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.