looking for a pattern to change function behaviour by context


Z

Zhang Weiwu

Problem:

library method request() requests data from external server. Sometimes, if a
request is failed, it should be ignored, like price inquiry - if we don't
get the price, then no decision could be made based on the price, then we
simply do nothing about it; Sometimes, if a request is failed, it should
retry, and if retry failed, it should throw an exception, like the case with
placing order.

The problem is how to write the retry/exception code once only, not
everywhere when needed.

Solution:

1. Inheritance. Add a new parameter 'critical' to the inherited method:

class New(requests.Session): # inherit a library class
def request(self, *args, critical = False, *kwargs):
if not critical:
return super().request(*args, *kwargs)
else:
result = super().request(*args, *kwargs)
if result.status_code != 200: # unsuccessful
result = super().request(*args, *kwargs)
if result.status_code != 200: # unsuccessful
raise SpecificException()
return result

class BusinessLogic:
....
def place_order(self, *args):
...
server.request(method, URL, critical = True)

Disadvantage: sometimes request is not called directly. The business logic
class may call other wrappers of request() (e.g. post() and get()), thus we
need repeat the above code to all the wrappers.

2. Use method 1, and also use decorator to add 'critical' paramter to all
wrappers of request()

class New(requests.Session): # inherit a library class
def AddCriticalParamter(func):
.... # add an optional parameter 'critical', which, if set,
.... # cause to retry and exception to func

@New.AddCriticalParameter
def get(self, *args, critical = False, *kwargs):
return super().request(*args, *kwargs)

@New.AddCriticalParameter
def post(self, *args, critical = False, *kwargs):
return super().request(*args, *kwargs)

class BusinessLogic:
....
def place_order(self, *args):
...
server.get(method, URL, critical = True)

3. Use a wrapper class in business logic

class New(requests.Session): # inherit a library class
def Critical(func):
.... # change behavior, add retry and exception to func

class BusinessLogic: ....
def place_order(self, *args):
...
critical(server.get)(method, URL)


4. Any other method?

Question is: 1) am I thinking along the right line? and 2) what method will
you use/recommend?
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top