On Nov 1, 2011, at 12:14 PM, Phil Mayers wrote:

> On 01/11/11 15:28, Christopher Armstrong wrote:
> 
>> I whole-heartedly agree with the sentiment, though. We need to get rid
>> of the global reactor.
> 
> Why?

Sometimes you want a different reactor.  The most common reason is unit 
testing, although if we could successfully eliminate the global reactor 
everywhere, there are other things that we might be able to do: slowing down or 
speeding up time from a protocol's perspective (by replacing IReactorTime), 
grouping related objects together in reactors that can be shut down together 
(so that reactor.stop() doesn't actually end the process); or, similarly, 
suspending a group of related objects (removeReader()/removeWriter() on 
everything) so that they can be inspected for debugging purposes, without 
suspending the thing doing the inspecting (a manhole python prompt).

> I find the "pass reactor as 1st argument to everything" API pattern 
> messy. I'm sure there's a good reason. What is it?

This pattern is a solution to the problem, but I agree that it is possibly not 
the optimal solution.  It sort of points in a direction where every possible 
module that might be imported becomes an argument to your function.  After all, 
there are plenty of other modules which have to be mocked for testing, why not 
just make everyone's __init__ method take sys.modules as an argument too, and 
never import anything?  In more complex systems this can definitely turn into a 
bit of a mess.

Nevertheless, "real reactor as default argument" is not a huge improvement 
either, because it typically breaks one level out.  If you have 
'a(reactor=defaultReactor)' and then 'b()' needs to call 'a', half the time 'b' 
will forget to supply a reactor argument and call 'a()' passing nothing, 
because that appears to be the suggested API.   Any code that calls 'b()' then 
needs to deal with the fact that the global reactor is going to get used, even 
if it has a cleanly encapsulated parameter of its own.  With sufficient 
discipline, of course, this approach is equivalent.

So despite its imperfections, I don't have a solution better than "pass the 
reactor to everything" yet.  It seems to be better than the alternatives in 
almost every case.  The one place it's not better is when writing brief example 
scripts, but I suspect this is only the case because examples have to expose 
the semantic conflict between the way you actually get the reactor (import the 
singleton) and the way that you want to deal with the reactor (as a parameter). 
 If we had a sensible top-level way of getting the reactor I think examples 
which didn't use the global would read much more cleanly.

If you can think of a better solution that addresses all of these concerns 
simultaneously somehow, please share, I'd love to hear it :-).

-glyph


_______________________________________________
Twisted-Python mailing list
Twisted-Python@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python

Reply via email to