We help IT Professionals succeed at work.

Avoiding code duplicacy

Rohit Bajaj
Rohit Bajaj asked
on
Hi,
I have the following functions in my code :

 public ListenableFuture<MessagesAroundSidResponse> messagesAroundSid(final MessagesAroundSidRequest request)
    {
        final SettableFuture<MessagesAroundSidResponse> settableFuture = SettableFuture.create();

        _httpClient.processRequest(new HttpRequest(request.getRequestBody(), request.getRequestSpecificPath(), request.getUrlParams(), request.isMethodPost(), request.getTenantVersion(), new IResponseCallback()
        {

            @Override
            public void onSuccess(String responseBody, int statusCode)
            {
                if (statusCode >= 200 && statusCode <= 299)
                {
                    System.out.println(responseBody);
                    settableFuture.set(request.consumeResponse(responseBody));
                }
                else
                {
                    settableFuture.setException(request.consumeError(statusCode, responseBody));
                }

            }

            @Override
            public void onFailure(Throwable throwable)
            {
                settableFuture.setException(throwable);
            }
        }));
        return settableFuture;
    }

    public ListenableFuture<PreviousFetchResponse> PreviousChats(final PreviousFetchRequest request)
    {

        final SettableFuture<PreviousFetchResponse> settableFuture = SettableFuture.create();
        _httpClient.processRequest(new HttpRequest(request.getRequestBody(), request.getRequestSpecificPath(), request.getUrlParams(), request.isMethodPost(), request.getTenantVersion(), new IResponseCallback()
        {
            @Override
            public void onSuccess(String responseBody, int statusCode)
            {
                if (statusCode >= 200 && statusCode <= 299)
                {
                    System.out.println("Iniside PreviousChat");
                    settableFuture.set(request.consumeResponse(responseBody));
                }
                else
                {
                    settableFuture.setException(request.consumeError(statusCode, responseBody));
                }
            }

            @Override
            public void onFailure(Throwable throwable)
            {
                settableFuture.setException(throwable);
            }
        }));

        return settableFuture;
    }

Open in new window


The following piece of code is duplicated in it :

 @Override
            public void onSuccess(String responseBody, int statusCode)
            {
                if (statusCode >= 200 && statusCode <= 299)
                {
                    System.out.println("Iniside PreviousChat");
                    settableFuture.set(request.consumeResponse(responseBody));
                }
                else
                {
                    settableFuture.setException(request.consumeError(statusCode, responseBody));
                }
            }

            @Override
            public void onFailure(Throwable throwable)
            {
                settableFuture.setException(throwable);
            }
        }));

        return settableFuture;

Open in new window


what way i can avoid this duplicacy ?

Thanks
Comment
Watch Question

You may be able to create one method like this:

private static void onSuccessHandler(String responseBody, int statusCode, SettableFuture<?> settableFuture) {
                 if (statusCode >= 200 && statusCode <= 299)
                {
                    System.out.println("Iniside PreviousChat");
                    settableFuture.set(request.consumeResponse(responseBody));
                }
                else
                {
                    settableFuture.setException(request.consumeError(statusCode, responseBody));
                }  
}

and then change the onSuccess() methods to call to this method:
         
public void onSuccess(String responseBody, int statusCode) {
      onSuccessHandler(responseBody, statusCode, settableFuture) ;
}

(You can do the same for the failure).

The only challenge here is that the type of SettableFuture isn't the same in the two cases, so you need to use a generic version of the future and that could cause problems - depending on the details of that class.

Anyway give it a shot.

Doug
IT Business Systems Analyst / Software Developer
Top Expert 2015
Commented:
Rather than use anonymous IResponseCallback subclasses, you can separate that out into it's own top level class. Create a separate java file...

SettableFutureResponseCallback.java
public class SettableFutureResponseCallback<T> implements IResponseCallback {

            private T request;
            private SettableFuture<T> settableFuture;

            public SettableFutureResponseCallback(T request, SettableFuture<T> settableFuture) {
                        this.request= request;
                        this.settableFuture = settableFuture;
            }

            @Override
            public void onSuccess(String responseBody, int statusCode)
            {
                if (statusCode >= 200 && statusCode <= 299)
                {
                    System.out.println(responseBody);
                    settableFuture.set(request.consumeResponse(responseBody));
                }
                else
                {
                    settableFuture.setException(request.consumeError(statusCode, responseBody));
                }

            }

            @Override
            public void onFailure(Throwable throwable)
            {
                settableFuture.setException(throwable);
            }
}

Open in new window



And then in each version of your code you would do something like this...
 public ListenableFuture<MessagesAroundSidResponse> messagesAroundSid(final MessagesAroundSidRequest request)
    {
        final SettableFuture<MessagesAroundSidResponse> settableFuture = SettableFuture.create();

        _httpClient.processRequest(new HttpRequest(request.getRequestBody(), request.getRequestSpecificPath(), request.getUrlParams(), request.isMethodPost(), request.getTenantVersion(), new SettableFutureResponseCallback(request, settableFuture)));
        return settableFuture;
    }

    public ListenableFuture<PreviousFetchResponse> PreviousChats(final PreviousFetchRequest request)
    {

        final SettableFuture<PreviousFetchResponse> settableFuture = SettableFuture.create();
        _httpClient.processRequest(new HttpRequest(request.getRequestBody(), request.getRequestSpecificPath(), request.getUrlParams(), request.isMethodPost(), request.getTenantVersion(), new SettableFutureResponseCallback(request, settableFuture)));

        return settableFuture;
    }

Open in new window


(Note: that this was done without the assistance of an IDE so there could be minor errors, but hopefully it will give you the idea)

Author

Commented:
HI,
Thanks
That removed code duplicacy to a great extent. But now i am left with the following piece of code which also seems like duplicacy
:

package to.talk.history.api;

import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;

import org.jetbrains.annotations.NotNull;
import to.talk.history.requests.*;
import to.talk.history.responses.*;

public class Client
{
    private final HttpClient _httpClient;

    public Client(@NotNull HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    public ListenableFuture<FetchMessagesResponse> messagesAroundSid(@NotNull final MessagesAroundSidRequest request)
    {
        final SettableFuture<FetchMessagesResponse> settableFuture = SettableFuture.create();
        _httpClient.processRequest(new HttpRequest(request.getRequestBody(), request.getRequestSpecificPath(), request.getUrlParams(), request.isMethodPost(), request.getTenantVersion(), new SettableFutureResponseCallback<>(request,settableFuture)));
        return settableFuture;
    }

    public ListenableFuture<FetchMessagesResponse> PreviousChats(@NotNull final PreviousFetchRequest request)
    {

        final SettableFuture<FetchMessagesResponse> settableFuture = SettableFuture.create();
        _httpClient.processRequest(new HttpRequest(request.getRequestBody(), request.getRequestSpecificPath(), request.getUrlParams(), request.isMethodPost(), request.getTenantVersion(), new SettableFutureResponseCallback<>(request,settableFuture)));
        return settableFuture;
    }

    public ListenableFuture<SyncChatsResponse> syncChats(@NotNull final SyncChatsRequest request)
    {
        final SettableFuture<SyncChatsResponse> settableFuture = SettableFuture.create();
        _httpClient.processRequest(new HttpRequest(request.getRequestBody(), request.getRequestSpecificPath(), request.getUrlParams(), request.isMethodPost(), request.getTenantVersion(), new SettableFutureResponseCallback<>(request,settableFuture)));
        return settableFuture;
    }

    public ListenableFuture<MagicContactsResponse> magicContacts(@NotNull final MagicContactsRequest request)
    {
        final SettableFuture<MagicContactsResponse> settableFuture = SettableFuture.create();
        _httpClient.processRequest(new HttpRequest(request.getRequestBody(), request.getRequestSpecificPath(), request.getUrlParams(), request.isMethodPost(), request.getTenantVersion(), new SettableFutureResponseCallback<>(request,settableFuture)));
        return settableFuture;
    }

    public ListenableFuture<HistorySearchResponse> historySearch(@NotNull final HistorySearchRequest request)
    {
        final SettableFuture<HistorySearchResponse> settableFuture = SettableFuture.create();
        _httpClient.processRequest(new HttpRequest(request.getRequestBody(), request.getRequestSpecificPath(), request.getUrlParams(), request.isMethodPost(), request.getTenantVersion(), new SettableFutureResponseCallback<>(request,settableFuture)));
        return settableFuture;
    }
    public ListenableFuture<FetchMessagesResponse> latestFetch(@NotNull final LatestFetchRequest request)
    {
        final SettableFuture<FetchMessagesResponse> settableFuture = SettableFuture.create();
        _httpClient.processRequest(new HttpRequest(request.getRequestBody(), request.getRequestSpecificPath(), request.getUrlParams(), request.isMethodPost(), request.getTenantVersion(), new SettableFutureResponseCallback<>(request,settableFuture)));
        return settableFuture;
    }

   

Open in new window



I tried reducing the above all code to the following function :

 public <K extends HistoryRequest,T> ListenableFuture<T> Fetch(final K request)
    {
        final SettableFuture<T> settableFuture = SettableFuture.create();
        _httpClient.processRequest(new HttpRequest(request.getRequestBody(), request.getRequestSpecificPath(), request.getUrlParams(), request.isMethodPost(), request.getTenantVersion(), new SettableFutureResponseCallback<>(request,settableFuture)));
        return settableFuture;
    }
}

Open in new window


Although the above code is running which is bit surprise to me as
how is the following line getting instantiated :
        final SettableFuture<T> settableFuture = SettableFuture.create();
As i dont provide the value of T in the parameters or anywhere.

I executed the code with the following line :

        ListenableFuture<FetchMessagesResponse> future = client.Fetch(latestFetchRequest);