0

I am working on a project where I need to make calls to a REST API. The end points of the API are on three different servers with three different base addresses.

  • I am using the System.Net.Http.HttpClient class to model the HTTP clients.

  • I am planning to have three different HTTP clients, one for each server as the base addresses are different. Let's name them ServerClient1, ServerClient2 and ServerClient 3.

  • These three clients would be using the methods in the HttpClient class but would have to implement their own methods to process the HttpReponse from the servers.

For eg:

    private async Task<HttpResonseMessage> getPresenceAsync() {
          string url="/xxx/yyy/zzzz";
          HttpResponseMessage httpResponse=await httpClient.GetAsync(url);
          return httpResponse;
    }

Which would be a good design decision in this case: Have the ServerClients extend the HttpClient or have the HttpClient as a member of the ServerClients?

I was referring to the link below and I personally feel Aggregation would be a better choice as I would not be using all the methods in the HttpClient Class.

Inheritance vs. Aggregation

Any different perspective/help is appreciated.

Thanks!

Community
  • 1
  • 1
Krishnaveni B
  • 103
  • 1
  • 7
  • 1
    More importantly, when would you ever want to treat a `ServerClient` *as* an `HttpClient`? – Jon Skeet Oct 27 '16 at 15:35
  • 2
    Don't think in terms of how you are actually going to do the necessary calls - that's an implementation detail. Think in terms of what each service should expose, and write your interfaces based on that. At this point, it should be clear that inheriting from HttpClient is not correct, as there is nothing in your interfaces that relates to HTTP - they will be written in terms of the methods exposed by the apis, and the responses you will get back from those - none of which is to do with HTTP. – RB. Oct 27 '16 at 15:37

1 Answers1

1

I would suggest that you use Aggregation instead of Inheritance to follow the Single Responsibility Principle. Furthermore I would inject HttpClient in the constructor. That way your ServiceClient will only do one thing: compose and send relevant requests to HttpClient and not care and know about it's internal implementation.

I always follow this pattern myself and prefer Aggregation to Inheritance. It is also worth noting that this structure is much simpler to understand and work with.

Another benefit is that if you would want to decorate your service, you can easily do that with aggregation, but not so easy with inheritance.

P.S. Yet another benefit you get is testability. If you inherit from HttpClient it will be rather hard to write unit-test that don't perform real requests. On the other hand if you inject HttpClient, you will be able to mock it during unit testing, though in that case you'll need to either ensure HttpClient has some abstract base class or interface you can use. Otherwise you'll need to abstract HttpClient yourself, i.e. create MyHttpClient : IHttpClient and wrap all of the calls that you need to real HttpClient.

Ilya Chernomordik
  • 27,817
  • 27
  • 121
  • 207
  • When unit-testing HttpClient one neat trick is that you can actually add handlers to it that will return canned responses. This reinforces your point about supplying a HttpClient in the constructor - you can create one with the relevant handlers and supply it. – RB. Oct 27 '16 at 20:43