1

I am using a third party HTTP client to make GET, POST calls. I don't want to tie my code to this library. So I've decided to create an interface called HttpClient and an implementation of it called HttpClientImpl.

One of the methods in the interface is:

Response get(String url);

The Response object being returned from the interface is the object from the third party library. So this technically does not decouple my code from the third party library.

What is the best approach to decouple myself? Should I create my own response object that can wrap the response of the third party library?

tattihead
  • 81
  • 2
  • 4

2 Answers2

1

This is a classic case of the Mediator design pattern: The class which uses the HTTP client shouldn't be exposed to neither the HTTP client implementation (which you've already encapsulated) nor its response object.

Using generics here will not prevent the using class from knowing the response class in this case.

As you suggested - have a wrapping response class / have a converter from the 3rd party response to one of your own.

user265732
  • 585
  • 4
  • 14
1

Instead of abstracting the http library, have you considered abstracting the repositories you are accessing through Http? Say for example, you have the restful endpoints for Tweets:

GET    https://someapi.com/Tweets
GET    https://someapi.com/Tweets/{id}
POST   https://someapi.com/Tweets
PUT    https://someapi.com/Tweets/{id}
DELETE https://someapi.com/Tweets/{id}

It would make sense to have a TweetRepository class, which can create, read, update and delete tweets. The interface for this class might look something like the following:

public interface TweetRepository {
    public List<Tweet> get();
    public int add(Tweet tweet);
    public void remove(int id);
    public Tweet get(int id);
    public void update(int id, Tweet tweet);
}

If your controllers use the interface, then you can make your implementation use whatever http library you want without introducing coupling.

Andrew Williamson
  • 8,299
  • 3
  • 34
  • 62
  • That works. But still the underlying implementation of the repository will be tightly coupled if the HTTP library is not abstracted. – tattihead Aug 06 '17 at 21:53
  • @tattihead life will be miserable if you want to isolate all your code from 3rdparty libraries. Andrew's suggestion is good. (except for the coding standards faux-pas of capital method names). – MeBigFatGuy Aug 06 '17 at 21:55
  • Sorry, I've been using a lot of C# lately. I had to resist calling it an `ITweetRepository`. @tattihead Yes, the http implementation will depend on _some_ http library, how could be implemented if it did not? When you place the implementation behind an interface, though, you prevent the code which uses the implementation from being coupled to the library. You could easily swap it out for a TweetRepository which connects to a database, and uses Sql instead. – Andrew Williamson Aug 06 '17 at 22:05
  • @MeBigFatGuy - consider that several modules in your service are using your HTTP client wrapper - in case you will return a response object which is coupled to the 3rd party HTTP client and you'll need to modify all of those modules... I'm talking more about the general case if having the most generic APIs as possible. – user265732 Aug 06 '17 at 22:21
  • Yes, you _could_ abstract the http implementation behind an interface. But unless you then use your http abstraction library behind a repository interface like the one above, you've coupled your code to the http protocol, which is (in my opinion) worse than the repository implementation being coupled to a specific http library. I could understand this being an issue if you have to merge two systems that use different http libraries, but in most other cases, I would say it's not worth it. – Andrew Williamson Aug 06 '17 at 22:39
  • I agree with what @user265732 said... that is what I was trying to get at – tattihead Aug 06 '17 at 23:16