2

I have 2 method which performs 80% same work but differ in result processing. I am doing :

 private <T> T getResponse(final RestURI query, final Class<T> responseClass) throws IOException {
        T response = null;

        final RestResponse<Record> tempResponse = getResponseFromDataPath(query);

        if (isResponseOK(tempResponse, query)) {
            final CustomReader reader = createCustomReaderFromResponse(tempResponse);
            response = objectMapper.readValue(reader, responseClass);
                                                          ^
            // DIFFERENCE --------------------------------|
        }

        return response;
    }

    private <T> T getResponse(final RestURI query, final TypeReference valueTypeRef) throws IOException {
        T response = null;

        final RestResponse<Record> tempResponse = getResponseFromDataPath(query);

        if (isResponseOK(tempResponse, query)) {
            final CustomReader reader = createCustomReaderFromResponse(tempResponse);
            response = objectMapper.readValue(reader, valueTypeRef);
                                                          ^
            // DIFFERENCE --------------------------------|
        }

        return response;
    }

This looks like lot of duplicate. How do I make this such that I reduce the duplicates.

4
  • Pass all three parameters into a single constructor, and the simply pass null in the unused parameter. Check for null to distinguish inside the constructor. Commented Aug 23, 2018 at 7:38
  • @SusmitAgrawal that's horrible design. Commented Aug 23, 2018 at 7:38
  • 1
    extract the duplicate code in a shared method Commented Aug 23, 2018 at 7:40
  • 1
    Honestly, it would be helpful if you somehow marked or explicitly repeated the not common parts. I had to re-read the code 5 times to figure where they are different. Commented Aug 23, 2018 at 7:46

1 Answer 1

5

You can use a BiFunction parameter that calls objectMapper:

private <T> T getResponse(final RestURI query, 
    final BiFunction<CustomReader, ObjectMapper, T> mapper) throws IOException {
    T response = null;

    final RestResponse<Record> tempResponse = getResponseFromDataPath(query);

    if (isResponseOK(tempResponse, query)) {
        final CustomReader reader = createCustomReaderFromResponse(tempResponse);
        response = mapper.apply(reader, objectMapper); 
    }

    return response;
}

And callers can choose how to call objectMapper:

getResponse(query, 
   (reader, objectMapper) -> objectMapper.readValue(reader, <valueTypeRef>);

Or:

getResponse(query, 
    (reader, objectMapper) -> objectMapper.readValue(reader, <class>);
Sign up to request clarification or add additional context in comments.

3 Comments

The important thing to keep in mind: this is only a good idea when that method stays private. Would it be something that external code is using, then obviously do not want to expose such a level of detail. Nice answer though!
@GhostCat Agreed.
As getResponse() is a private method, the caller method can directly reference the objectMapper field in the lambda body : getResponse(query, reader -> objectMapper.readValue(reader, valueTypeRef));. So Function<CustomReader, T> is enough. Which simplifies things in both sides.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.