Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Don't recommend using addCallback as a function decorator #2523
Well, I think this is a useful style for writing inline anonymous(ish) callabacks, so I'll be inclined to keep this style.
@wallrj I don't want to forcefully close this PR as you may have more arguments against this practice.
Please let me know why you think this is a bad idea.
I've tried using this style before on https://github.com/ClusterHQ/flocker or https://github.com/twisted/twisted/ and it was rejected by @exarkun for the same reasons, I think (but I can't find the reference. )
Then a colleague of mine, @moshez used this style recently on a private repo and I grumbled about it.
I found a couple of examples, introduced by @glyph in the Twisted code:
This buildbot documentation is the only place I can find it discussed / documented so I decided to start a discussion :-)
I guess the main objection is that
Since we are adding other people, adding @djmitche who write the recommendation in the first place (the git blame says it came from our wiki)
I agree its a bit of a hack, but it imho adds readability compared to
Which is written backward imho.
It's true the trick does make the order more readable for some folks. However, the resulting code is still rather dense and can be difficult to read overall. A recommendation I would make is that functions should focus on doing one thing well. A function that starts an async operation and then is packed full of nested functions for operating on the result may be just as poorly factored as a synchronous function that does ten unrelated operations.
Instead of defining
which I think we should be able to agree is more readable than either of the other options presented here.
Personally I like this style very much. For a while I worried that this was a too-clever impulse (I do have those sometimes) and an abuse of syntax; however, recent teaching experiences have confirmed my suspicions that explaining the
Combined with another (unfortunately somewhat obscure) idiom, it can avoid redundant temporary naming as well as putting things in the right order.
For example, instead of:
d = foo() def bar(result): return doStuff(result) return d.addCallback(bar)
you can do
passthru = lambda x:x # (or 'from twisted.internet.defer import passthru') @passthru(foo()) def d(result): return doStuff(result) return d
However, I'd agree with @exarkun in that if you're inclined to have an intense discussion about the merits of this style, chances are that the real issue is that you've got too many callbacks, nested too deeply, and you should consider breaking things up into more top-level functions instead. Buildbot certainly has that problem regardless of its stylistic representation :-).
I think the problem of nested function, and callback hell is orthogonal to this debate.
With or without @d.addCallback, we all agree that more than 2 inline functions is to be avoid in python code (which btw is far from being the case in the example given twisted/twisted@e331b4e)
Buildbot used to suffer from callback hell, and I think we removed most of that technical debt from the core (we still have a lot of the source steps which is quite hard to follow)
We replaced lots of the callback hell code with inlineCallbacks logic.
If you're concerned about performance, the thing to introduce is benchmarks, not callbacks :-). PyPy might be the right option, or shifting back to callbacks, or perhaps the lower-overhead async/await trampoline in 3.5 instead of the yield-based trampoline (i.e. switch to
Actually I spotted a couple of other typos and bad references and there's a sphinx lint failure.
Answer or address those and merge when you get green builds.