On Dec 15, 2009, at 1:11 PM, Jared Gisin wrote:

> I completely fail to see why zope.interface is even needed. It's not Pythonic 
> at all and it contributes to unnecessary code bloat.

Oh gosh!  You're absolutely right!  I never noticed it before!  I just got out 
my Pythonic-o-meter and measured Zope Interface!  Apparently it is only 0.44 
vRossums!  (For those you familiar only with the SI units, a vRossum is 
equivalent to one Microtim per cubic meter-second).  We should totally delete 
all the interfaces in Twisted!

Wait, oops.  I mean, did you even read 
<http://glyph.twistedmatrix.com/2009/02/explaining-why-interfaces-are-great.html>?
  There are lots of reasons to have interfaces.

> What's wrong with writing subclasses?

Lots of things in Twisted are subclasses.  twisted.internet.protocol.Protocol 
provides a helpful utility base-class for implementing 
twisted.internet.interfaces.IProtocol.  If you use them for what they're good 
for, there's nothing wrong with them.

But, as I said in my article, interfaces and classes are for different things.

As a very simple example of what's wrong with subclassing, there are times when 
having extra superclasses breaks things.  For example: let's say that you want 
to have an IProtocol implementation that uses __slots__ and doesn't have a 
__dict__.  Or, you want to do the equivalent thing in C to write a 
super-optimized IProtocol implementation.

If your documentation says "this parameter must be a Protocol", then you're 
stuck.  There's no way to enforce that or provide friendly debugging error 
messages when you *don't* provide a Protocol; you just have to invoke the 
appropriate methods and hope it works.  If you do actually subclass Protocol in 
your application, in the best case you get a class which accidentally inherits 
a __dict__, and in the worst case you get a base class layout conflict error 
and you can't even import your module.  There are also lots of ways that 
metaclasses can conflict, inheritance hierarchies can become awkward and 
confusing, etc.  This is even worse if the base class you want happens to do 
some unwanted work in its constructor.

Another use for interfaces is testing.  For example, you can use interfaces to 
write tests to make sure that your code is up-to-date with the most recent 
specifications.  Let's say that we have an interface, IFoo, that has a method, 
'bar'.  We want to add a method, 'baz', to it.  Now, applications may be 
claiming to implement IFoo already, so we need to be careful when we invoke 
'bar' as it may not be present, but the savvy implementor could use 
'verifyObject' to make sure that their MyFoo class properly implemented all the 
required methods, and IFoo.

There are some things you can kinda-sorta do with metaclasses or introspection 
to provide similar functionality, but they're highly susceptible to 
implementation details shifting around.  Metaclasses, in particular, tend to 
exacerbate the problems I mentioned above with inheritance conflicts and 
features like __slots__.

Yet another use for interfaces is adaptation.  This is very useful in 
integration systems like twisted.cred.  The interface object serves as a 
concise encapsulation of what the calling code wants to get out of cred, and 
realm implementations can return whatever.

> I've never had a case where that wasn't sufficient.

Your limited experience isn't necessarily a good argument for what Twisted 
should or shouldn't do.  There are many people for whom the 'urllib' or 
'socket' modules have always been sufficient, but that doesn't mean we're going 
to give up and go home either.

If you still don't think my reasoning is adequate, you should spend a few years 
contributing lots of really useful patches to Twisted, then bring this up again.


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

Reply via email to