[Twisted-Python] Re: [Twisted-commits] Updated defer.html so that the first 4 examples are runnable, split the 3rd

Andrew Bennetts andrew-twistedcommits at puzzling.org
Sat Mar 8 20:49:32 EST 2003

On Sat, Mar 08, 2003 at 04:44:56PM -0600, cce CVS wrote:
> Modified files:
> Twisted/doc/howto/defer.html 1.29 1.30

> @@ -19,14 +19,22 @@
>  methods where the common idiom is to block until a result is
>  gotten.</p>
>  <pre class="python">
> +
>  class Getter:
>      def getData(self, x):
> -        self.blockUntilResult(x)
> -        return result
> +        return self.someBlockingCall(x)
> +
> +    def someBlockingCall(self,x)
> +        print "blocking"
> +        import time
> +        time.sleep(4)
> +        return x * 3
>  g = Getter()
>  print g.getData(3)
> +print "blocking"
> +
>  </pre>

Why does this code snippet now do 'print "blocking"' twice?

>  <h3>Don't Call Us, We'll Call You</h3>
> @@ -39,29 +47,43 @@
>  understand the necessity for Deferreds.</p>
>  <pre class="python">
> +
>  class Getter:
>      def getData(self, x, callback):
> -        self.callback = callback
> -        # this call does not block, it ensure self.gotResult is called
> -        # when we have the result
> -        self.onResult(x, self.gotResult)
> -    
> -    def gotResult(self, result):
> -        self.callback(result)
> +        self.callback = callback; self.x = x

Why not two seperate lines here?

> +        self.nonBlockingOperation()
> +        #
> +        # Timer class happens to wrap the previous code in 
> +        # a thread; but this could be any asyncronous operation 
> +        # such as selecting from a socket, etc.
> +        #
> +        from threading import Timer
> +        t = Timer(4, self.gotResult)
> +        t.start()
> +
> +    def nonBlockingOperation(self): 
> +        print "non-blocking"
> +
> +    def gotResult(self):
> +        self.callback(3*self.x)
>  def gotData(d):
>      print d
>  g = Getter()
>  g.getData(3, gotData)
> +
>  </pre>

You've sacrificed clarity for runnability.  I'm not sure that's the right
thing to do; the point of this example is now obscured behind details like
how threading.Timer works, and spelling out a dummy "nonBlockingOperation"
method where before it was quite clear without it.  Not all example code
in the Howtos must be immediately executable standalone... I think perhaps
this example code would be better in the doc/examples directory, where it is
more appropriate for examples to be verbose like this.

Also, the way the example used to be reflected an idiomatic use in Twisted:
where there is some event handler, e.g. onResult, fired at an arbitrary time
by some external source.  Think of e.g. Protocol objects with dataReceived.
The example as it was emphasised that Deferreds can apply equally well when
you don't have control over when some event completes -- regardless of
whether it came from a thread, or the network, or anywhere.

> -<p>There are several things missing in this simple example.  There is no way to
> -know if the data never comes back; no mechanism for handling errors.  There is
> -no way to distinguish between different calls to gotData from different
> -sessions.  <code>Deferred</code> solves these problems, by creating a single,
> -unified way to defer execution of code that depends on blocking calls.</p>
> +<p>There are several things missing in this simple example.  There is no way
> +to know if the data never comes back; no mechanism for handling errors.  The
> +example does not handle a multiple callback functions, nor does it give a
> +method to merge arguments before and after execution.  Further, there is no
> +way to distinguish between different calls to gotData from different
> +producer objects. <code>Deferred</code> solves these problems, by creating 
> +a single, unified way to handle callbacks and errors from deferred
> +execution.</p>

What does "merge arguments before and after execution" mean to a Twisted
newbie?  Why would they want to do it?

>  <h2>Deferreds</h2>
> @@ -69,9 +91,45 @@
>  a function will at some point have a result.  We can attach callback functions
>  to a Deferred, and once it gets a result these callbacks will be called. In
>  addition Deferreds allow the developer to register a callback for an error,
> -with the default behavior of logging the error. This is an asynchronous
> -equivalent of the common idiom of blocking until a result is returned or an
> -exception it raised.</p>
> +with the default behavior of logging the error.  The deferred mechanism 
> +standardizes the application programmer's interface with all sorts of 
> +blocking or delayed operations.</p>

That probably should be "*D*eferred", not "deferred".  I think I'd also like
to add back the comment about "This is an asynchronous equivalent of ..." --
perhaps it's overly jargonistic, but it is the way I think about Deferreds;
they are the primary tool Twisted provides to abstract away blocking
operations into a fundamentally asynchronous framework.

> @@ -82,39 +140,48 @@
>  to return the result to the HTTP client.</p>
>  <pre class="python">
>  </pre>

Again, with the next two examples I think you've obscured the point in your
efforts to make everything explicit.  I'd rather have a 10 line example
that illustrates a concept, than a 20 line example that obscures the same
concept behind irrelevant method definitions, etc.  On the other hand, I
think long examples, say 50 lines or more, should be runnable, because
anything long enough to require that many lines to explain probably should
be ready for a newbie to play with.  

Informally, I'd say this is the different between <pre class="python"> and
<a href=... class="py-listing"> -- when you're listing a file, it *should*
be a complete, runnable example.  In fact, complete, runnable examples
probably should be a listing for the reader's convenience, i.e. put the code
in doc/listings somewhere, rather that in the .html file.

Please don't be discouraged from working on the docs!  They *do* need
work... I just happen to think that defer.html is probably the doc least in
need of improvement :)


More information about the Twisted-Python mailing list