[Twisted-Python] why deferred.setTimeout is not my favorite API method

Jonathan Simms slyphon at twistedmatrix.com
Sat Apr 17 16:22:50 MDT 2004


This is response to issue 178 on the twisted tracker:
http://www.twistedmatrix.com/users/roundup.twistd/twisted/issue178,
about the deferred method setTimeout.

The reason why I added a "DON'T USE THIS" to the docstring was that I
find that we are telling people this at least once a week. I think it
has more gravitas coming from the API documentation, as there is this
illusion that the people on IRC don't really know what they're talking
about, but if the author has marked something in the documentation, it
has a certain level of legitimacy.

I agree with spiv in the sense that it would be nice to have a minimal
interface that would provide this functionality. However, i think that
the level of control that is needed to pull this off properly is best
served by writing an explicit timeout method and accompanying call to
callLater. 

now, I'd like to present the idiom that we are try to encourage users to
follow every time we have to steer them away from setTimeout. 

------------------------------------------------------

d = iReturnADeferred()

def onTimeout():
    handleTimeoutCondition()

delayedCall = reactor.callLater(timeoutLen, onTimeout)

def success(value):
    handleSuccess()

def nonTimeoutFailure(reason):
    handleErrorCondition()

def cancelTimeout(val):
    if delayedCall.active():
        delayedCall.cancel()

d.addBoth(cancelTimeout)
d.addCallback(success)
d.addErrback(nonTimeoutFailure)

-------------------------------------------------------

Here you see that each step is very explicit. You can see what happens
on success and on timeout (failure). I think one problem with setTimeout
is the handling of the IDelayedCall is something that a new user could
miss.  

For instance, someone who hadn't /read/ the code of setTimeout, would
most likely miss the returned IDelayedCall, and wouldn't know to cancel
the pending timeout call in the event of success OR other failure. This
is _a crucial piece of the code path_, and setTimeout makes this easier
to miss.



As from the Zen of Python Programming:

- Explicit is better than implicit
    
    setTimeout hides a small piece of code that contains all of the
    important conceptual elements that a user is required to understand
    so that they may handle this side-exit condition properly.
    

- Special cases aren't special enough to break the rules

    Delayed calls are orthogonal to deferreds. 

    Deferreds are a _reactive_ tool, they fire in response to an event
    
    delayed calls are a _proactive_ tool, they cause events to fire

    Mixing the two together for the special case of dealing with a
    timeout is at best hairy and at worst ugly and confusing.

    Timeout conditions are _not necessarily_ something that a user needs
    to deal with 80% of the time they are working with deferreds. 


- Simple is better than complex

    The deferred api should contain absolutely necessary functionality. 

    Let's emulate the python language, not the python standard library


- There should be one, and preferrably only one way to do it

    It is better to have users of our API use a widely-understood and
    flexible idiom to accomplish this rather than a half-baked method
    that saves them 8 lines of easily written and conceptually crucial
    code

    I would like to recommend that we document a best-practice idiom
    in the deferred api documentation, and remove setTimeout.


- If an implementation is hard to explain it's a bad idea

    Explaining to users how to properly use setTimeout takes more effort
    than explaining to them how to use the tools that setTimeout employs
    to achieve its functionality.


spiv said: 

"In hindsight, I should've thought harder about the implications of
setTimeout before I committed it... but now it's there, I don't like the
idea of ripping it out unless we have a clearly better solution."

This is a less-than-optimal solution to an edge-case use of two
orthogonal parts of our API.

It makes no sense to leave a sharp, pointy thing lying around for users
to hurt themselves with, and to constantly tell them "DON'T USE THAT".


-Jonathan Simms 
slyphon AT twistedmatrix DOT com

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part
URL: </pipermail/twisted-python/attachments/20040417/88af04b4/attachment.sig>


More information about the Twisted-Python mailing list