I'm writing an SDK for the European Space Agency's DISCOs API.
This has around 10 endpoints with different sets of query parameters, each of which returns a different payload type with different link parameters which will also need to be resolved. I explicitly don't want my user to have to construct query strings themselves, these will all be explicitly typed parameters on my client(s)' methods.
So, by the time I've handled all of this, my client class could actually be fairly hefty. As a consequence of this, I'm considering creating a client for each endpoint to handle the validation of query parameters and ensure everything is strongly typed. These can then use a basic, generic "God Mode" client internally to do the actual querying.
The god mode client would look something like this:
public class DiscosClient : IDiscosClient { private readonly HttpClient _client; public DiscosClient(HttpClient client) { _client = client; } public async Task<DiscosResponse<T>?> Get<T>(string endpoint, string query) where T: DiscosModelBase { return await _client.GetFromJsonAsync<DiscosResponse<T>>($"{endpoint}?{query}"); } } However, this then means I have a whole bunch of clients which could be a bit of a mess in and of itself.
For example, I'd need DiscosObject, Propellant, Orbit clients with interfaces like these (I've not added filter parameters to my interfaces yet):
public interface IDiscosObjectClient { public Task<List<DiscosObject>> GetObjects(); public Task<DiscosObject> GetObject(); public Task<List<ObjectClass>> GetObjectClasses(); public Task<ObjectClass> GetObjectClass(); } public interface IDiscosPropellantClient { public Task<List<Propellant>> GetPropellants(); public Task<Propellant> GetPropellant(); } public interface IDiscosOrbitClient { public Task<List<OrbitDetails>> GetInitialOrbits(); public Task<OrbitDetails> GetInitialOrbit(); public Task<List<OrbitDetails>> GetDestinationOrbits(); public Task<OrbitDetails> GetDestinationOrbit(); } What's the best way to approach this? Should I just have one super-client which handles all of these endpoints or should I deconstruct that into many smaller clients? Am I missing an obvious trick?