I have part of the system that looks like this:
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:
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.
2 Answers 2
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:
or
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);
}
}
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.
Explore related questions
See similar questions with these tags.
Process1()
method call depends onflagOn
being true, it makes sense that the client also knows it has to callApiCall1()
on the server.{ "responsetype","1" }