Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Running the same code for get(self) as post(self)

Its been mentioned in other answers about getting the same code running for both the def get(self) and the def post(self) for any given request. I was wondering what techniques people use, I was thinking of:

class ListSubs(webapp.RequestHandler):
    def get(self):
        self._run()

    def post(self):
        self._run()

    def _run(self):
        self.response.out.write("This works nicely!")
like image 304
Peter Farmer Avatar asked May 21 '10 14:05

Peter Farmer


3 Answers

I would suggest both theoretical and practical reasons why the approach you're using (refactoring out the common code to a separate method and calling it from both post and get methods) is superior to the apparently-simpler alternative of just having one of those two methods call the other.

From a theoretical viewpoint, "method A entirely delegates to method B" implies a notion of "primacy" or "asymmetry" -- a design decision that, going forwards, any change that may be applied to B will inevitably, intrinsically apply to A as well; that A may in the future be slightly customized with respect to B (adding some extra code before and/or after A's call to B) but never vice versa. When there's no reason to expect such primacy it's a bad coding decision to embed that notion in your code. By having both A and B call the common private method C, you avoid breaking symmetry.

Some people are not happy with theoretical arguments and prefer pragmatic ones: fortunately, in this case, the theoretical translates to the pragmatic pretty directly. Again, it's an issue of future evolution of the code: having both A and B call C leaves you all needed degrees of freedom to do small customizations (adding code before and/or after the call to C) to either, both, or neither of A and B. Since you don't know which parts of this flexibility you will need, and the cost of it in terms of simplicity is miniscule, taking the simple and flexible route is highly pragmatical and advisable.

One last pragmatical point (applying to either choice): any time you have a pattern like:

def amethod(self):
    return cmethod(self)

you're usually (modestly) better off rewording this as

amethod = cmethod

This avoids an unneeded level of call nesting (flat is better than nested). So, your class could usefully be coded:

class ListSubs(webapp.RequestHandler):

    def _run(self):
        self.response.out.write("This works even better!")

    get = post = _run

No big deal, and you'll have to refactor back to the original "nested" way if and when you do need to apply tweaks before or after the nested call (from get to _run, etc) or need other tweaks in debugging (e.g. set a breakpoint in your debugger on post but without having the breakpoint trigger on get, etc), but a nice little simplification for those times where it's feasible.

like image 88
Alex Martelli Avatar answered Sep 24 '22 20:09

Alex Martelli


Refactoring the code that does the work into its own function/method is the correct method.

like image 31
Ignacio Vazquez-Abrams Avatar answered Sep 25 '22 20:09

Ignacio Vazquez-Abrams


I've used this:

class ListSubs(webapp.RequestHandler):
    def post(self):
        self.response.out.write("This works nicely!")
    def get(self):
        self.post()
like image 33
Drew Sears Avatar answered Sep 26 '22 20:09

Drew Sears