1

I have an interface

public interface MovieDataFetcher {
    List<Movie> fetchAll(String query);
}

And these concrete classes

public class ImdbDataFetcher implements MovieDataFetcher {
    public List<Movie> fetchAll(String query) {
        OkHttpClient client = new OkHttpClient();
        // get the json data, deserialize it, return it as Movie objects
    }
}
public class TmdbDataFetcher implements MovieDataFetcher {
    public List<Movie> fetchAll(String query) {
        OkHttpClient client = new OkHttpClient();
        // get the json data, deserialize it, return it as Movie objects
    }
}

Now both of these implement the same interface so it should be easy to use them interchangeably. Adding new fetchers should also be trivial without having to change any of the existing fetchers.

My problem is, I am still using a concrete class in my fetchers, that is, OkHttp.

What if I don't want to use OkHttp anymore,but instead some other HttpClient? I can definitely refactor my fetcher classes and reuse some of the http functionality but I will still use a concrete class that might be an annoyance to change later.

My first idea was to wrap the OkHttpClient into a class that implements a new interface, IHttpClient

For any other HttpClient I might use, I'd write another wrapper class that implements IHttpClient and if I ever want to change the concrete class in my fetchers, I can do so with one line of code.

Is there a flaw in this approach that I am missing? Should I just use OkHttpClient without overthinking it?

2
  • 1
    Your idea on how to abstract the HTTP client is correct. BUT, as Ewan says, do you really want to do that? YAGNI (ya ain't gonna need it) applies. Jul 1, 2021 at 7:48
  • Regarding the question in the title alone: By only relying on the documented interface, instead of programming by trial and error. Jul 1, 2021 at 21:57

1 Answer 1

5

You should just use OkHttpClient without overthinking it.

But. If you needed to replace it more often, say you have lots of shared deserialisation code, but the actual data transfer wasn't always http, sometimes it was a database, sometimes WCF, sometimes a UDP stream etc You could then wrap each third party class in a simple interface

IDataGetter
{
    string GetData()
}

HttpWrapper : IDataGetter
{
    string GetData()
    {
        okhttpclient.get....
    }
}

DatabaseWrapper: IDataGetter
{
    string GetData()
    {
        connection.query....
    }
}

Now you can inject or use a factory to create 'DataGetters' and swap around as required.

The trick is to make the interface simple, don't try and include all the methods on httpclient, just find the one thing you want to do regardless of implementation

Your Answer

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

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