I need to develop an API, the functions of the API are requests that call the service exposed by a server.
Initially the API worked like this:
class Server: def firstRequest(self, arg1, arg2): # block of code A async = Async() async.callFirstRequest(arg1, arg2) # block of code B def secondRequest(self, argA, argB, argC): # block of code A (identical to that of firstRequest) async = Async() async.callSecondRequest(argA, argB, argC) # block of code B (identical to that of firstRequest) class Async: def callFirstRequest(self, arg1, arg2): doFirstRequest(arg1, arg2) # run the real request and wait for the answer def doFirstRequest(self, arg1, arg2): response = client.firstRequest(arg1, arg2) def callSecondRequest(self, argA, argB, argC): doSecondRequest(argA, argB, argC) # run the real request and wait for the answer def doSecondRequest(self, argA, argB, argC): response = client.secondRequest(argA, argB, argC) server = Server() server.firstRequest(arg1=1, arg2=2) server.secondRequest(argA='A', argB='B', argC='C')
There was a lot of duplicated code and I don't liked the way it passed the arguments for the request. Because there are a lot of arguments so I wanted to extract them from the request and make something more parametric.
So I refactored in this way:
# using a strategy pattern I was able to remove the duplication of code A and code B # now send() receive and invoke the request I wanna send class Server: def send(self, sendRequest): # block of code A asynch = Async() sendRequest(asynch) # block of code B # Request contains all the requests and a list of the arguments used (requestInfo) class Request: # number and name of the arguments are not the same for all the requests # this function take care of this and store the arguments in RequestInfo for later use def setRequestInfo(self, **kwargs): if kwargs is not None: for key, value in kwargs.iteritems(): self.requestInfo[key] = value def firstRequest(async) async.doFirstRequest(self.requestInfo) def secondRequest(async) async.doSecondRequest(self.requestInfo) # Async run the real request and wait for the answer class Async: def doFirstRequest(requestInfo): response = client.firstRequest(requestInfo['arg1'], requestInfo['arg2']) def doSecondRequest(requestInfo) response = client.secondRequest(requestInfo['argA'], requestInfo['argB'], requestInfo['argC']) server = Server() request = Request() request.setRequestInfo(arg1=1, arg2=2) # set of the arguments needed for the request server.send(request.firstRequest) request.setRequestInfo(argA='A', argB='B', argC='C') server.send(request.secondRequest)
The strategy pattern worked, the duplication is removed. Regardless this I'm afraid to have complicated things, especially on regards of the arguments, I don't like the way I handle them, because when I look at the code does not appear easy and clear.
So I wanted to know if there is a pattern or a better and clearer way to deal with this kind of client side API code.