[Twisted-Python] adapt from more than one interface

Esteve Fernandez esteve at sindominio.net
Sun Apr 12 03:08:23 MDT 2009


Hi

On Sunday 12 April 2009 02:31:29 glyph at divmod.com wrote:
> This is a long and terrible road you're about to start down.  It's hard
> for me to explain exactly why it's so painful, but trust me, it is.

No, I won't trust you :-) I hope you don't take what I'm going to say too 
seriously, but you couldn't sound more patronising.

Anyway, if it's so hard to explain, it's probably harder to understand, and 
thus, it's something that you cannot figure out by yourself. So, if you don't 
mind, why do you think it's so bad?

> What you're doing now, passing out-of-band arguments to the IFooFactory
> adapter, whose concrete type you are *not supposed to know* at that
> point in the control flow, is bad.  But trying to force adaptation to
> become full-fledged multimethods is worse.  If you want multimethods, I
> believe PEAK provides a package that implements them.

I know it's bad, because the resulting factory is incomplete, but that's why I 
wanted to adapt from two objects: the service itself and something that would 
make the factory complete (i.e. some configuration parameters required by 
protocols).

The main problem I see with the current adapter registry, is that adapters 
aren't configurable. In our case, we have a bunch of services, which are 
exposed to AMQP (adapted into a factory that builds instances of the AMQP 
protocol class), but since this is a client protocol that needs some extra 
arguments that can't be set beforehand in the adapter (username, password, 
vhost, encoding), they are passed after the service has been adapted into a 
factory.

So the problem is that the resulting factory is not complete, it doesn't have 
enough information to build protocols. The only workaround is to explicitly 
set those extra parameters after it has been instantiated.

> If you want to keep doing what you're doing, you should do this:
>
> factory = MyServiceFooFactory(myService)
> factory.configureBar("some value")
>
> i.e. don't ask for an adaptation which might give you an object without
> a "bar" attribute, just create the concrete type that does what you need
> based on the type of myService and configure it with explicitly
> documented methods.  Although if I misunderstand the spec of
> "IFooFactory" and it *does* include a bar attribute, nevermind.

The IFooFactory interface declares that attribute, but it's not immediately 
available when the service is adapted into a factory.

I fail to see what's the difference between bar= and configureBar() in this 
particular case. Interface attributes can be documented, so I don't see what 
makes configureBar better than bar (which can be turned into a property). 
Anyway, I think both solutions are flaky, so that's why I thought adapting 
two interfaces would be more elegant.

> If you want something more magical and adapter-ish, them maybe you want
> this:
>
> IFooFactory(ConfigurationObject(myService, bar="some value"))
>
> i.e. by the time you are getting around to the IFooFactory adaptation,
> you should have an object that fully provides enough information that
> the concrete FooFactory adapter type can be fully initialized when it is
> created.

I think that solution is even worse. That particular instance of 
ConfigurationObject is tied to myService: it can't be (de)serialized, reused 
with other adapters, ConfigurationObject and MyService are completely 
unrelated and I don't think the former should depend on the latter.

> >In order to implement this, registerAdapter would have to be able to
> >take a
> >tuple of interfaces, like this:
> >
> >components.registerAdapter(
> >    AdaptToFactory,
> >    (IFooService, IConfigurationDescriptor),
> >    IFooFactory)
> >
> >would that feature make sense? If so, I'll file an issue right now :-)
>
> Unfortunately, much as I've been encouraging people to file tickets
> lately, no :).  I don't think it makes sense.

I still think it does, but nobody wants to make the ticket count grow 
higher :-) Anyway, Zope already has this nifty thing called multi-adapters, 
which implement exactly what I described:

http://www.muthukadan.net/docs/zca.html#multi-adapter

but I always liked Twisted's adapter registry better and our application 
already uses it in quite a few places. I like being able to call IFoo(bar) 
and let the registry lookup an adapter automatically, instead of having to 
call getAdapter()/queryAdapter()

Cheers.




More information about the Twisted-Python mailing list