0

I have part of the system that looks like this:

enter image description here

Basically, the client decides which API call to invoke on the server based on the flag that is previously provided. It knows in advance which type of response to expect as well. So the code would look something like this:

if (flagOn) {
   Response1 = ApiCall1();
   Process1(Response1);
} else {
   Response2 = ApiCall2();
   Process2(Response2);
}

I'm not quite happy with the way this works, first of all because the flag that decides which API to call doesn't belong in the client, but it should be part of the server. Client shouldn't know anything about which API's are called in the background, it should just forward the request to server which decides about those things. So, I have started drafting improved version and came up with this:

enter image description here

In this version, Client is only concerned with forwarding the request to the Server, where the flow is decided. However, with this design, there is a main issue that needs to be addressed: response type of ProcessRequest(). So because ProcessRequest() can call either API, and get from them two completely different responses, I'm not able to represent both kind of responses with the same datatype. I wouldn't know what kind of data structure to use on the client in order to represent the response from ProcessRequest(). Can anyone help me with this design problem, or maybe suggest an alternative design/solution ?

??? response = server.processRequest();
    1.
  • The client has to know which API call to make as that makes a difference in the returned result. Since Process1() method call depends on flagOn being true, it makes sense that the client also knows it has to call ApiCall1() on the server. – BobDalgleish Nov 5 '18 at 17:52
  • I get it, but it makes it really impractical to maintain the same config value in two different apps. – Zed Nov 5 '18 at 18:03
  • Potentially you can include some type information in your response, which the client can then switch on. i.e. { "responsetype","1" } – Robert Harvey Nov 5 '18 at 18:12
  • 6
    This feels a little like an XY problem. You have completely different outputs of 2 APIs but you want to treat them as interchangeable. I think the design issue is deeper than this particular problem. – JimmyJames Nov 5 '18 at 18:33
  • If the two API are completely different in output: why are you switching between them on a flag? – Winston Ewert Nov 5 '18 at 18:38
1

if client is a component (class, multiple classes) then IMO you should move decision out of the client and the server, and create two separate clients, or one client with two methods. Don't pass flag in to the client, just call specific client or specific method on client:

enter image description here

or

enter image description here

EDIT:

If I understund correctly you want to have one generic code to call any external api and to process its response. If that is the case, then you can use generics:

public class SomeService {

    public SommeService(ApiClient apiClient, ResponseProccessor responseProcessor) {
        _apiClient = apiClient;
        _responseProcessor = responseProcessor;
    }

    public TResponse CallApi<TRequest,TResponse>(TRequest request){
        var respose = _apiClient.Call<TRequest>(request);
        _responseProcessor.Process<TResponse>(response);        
    }
} 
0

One option is as Winston Ewert noted in the comments, just always use the asynchronous approach. With standard POST semantics, you POST to a URI which will create a sub-resource of that URI. The POST response contains the location of that URI.

You can still do this switch internally if it makes sense. The client API will be consistent and the client will always POST and then do a GET on the returned URI. The difference will be whether the resource will be there before the client is sent the response or if it will be there sometime later. In order for the client to be agnostic of the details, it should only know that it will be available at the sub-resource location at some point after the call is made, possibly right away.

It's not totally clear from your question that the client even needs the response. If it's only responsibility is to get the request to the server then this seems like a really good fit for what you want to do.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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