Comments on: Inversion of Control http://laurentszyster.be/blog/ioc/ Python on Peers Fri, 18 May 2012 14:31:15 +0000 http://wordpress.org/?v=1.5.1.3 by: Laurent Szyster http://laurentszyster.be/blog/ioc/#comment-1351 Fri, 30 Jun 2006 09:46:23 +0000 http://laurentszyster.be/blog/ioc/#comment-1351 Hi Danny, Yes, that's a Pythonic way to do DI! As for Zope and Twisted, I have no problem putting them both aside. For more than a minute ... Regards, Hi Danny,

Yes, that’s a Pythonic way to do DI! As for Zope and Twisted, I have no problem putting them both aside. For more than a minute …

Regards,

]]>
by: Danny Adair http://laurentszyster.be/blog/ioc/#comment-1338 Fri, 30 Jun 2006 02:33:15 +0000 http://laurentszyster.be/blog/ioc/#comment-1338 If you're alright with putting Zope and Twisted on the side for a minute, check out http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/413268 for a sample implementation and some good links If you’re alright with putting Zope and Twisted on the side for a minute, check out
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/413268
for a sample implementation and some good links

]]>
by: Florent Guillaume http://laurentszyster.be/blog/ioc/#comment-787 Sat, 27 May 2006 17:01:45 +0000 http://laurentszyster.be/blog/ioc/#comment-787 See http://svn.zope.org/*checkout*/Zope3/trunk/src/zope/interface/adapter.txt for example. See http://svn.zope.org/*checkout*/Zope3/trunk/src/zope/interface/adapter.txt for example.

]]>
by: Florent Guillaume http://laurentszyster.be/blog/ioc/#comment-786 Sat, 27 May 2006 13:36:46 +0000 http://laurentszyster.be/blog/ioc/#comment-786 > An interface framework is *already* built-in CPython, implemented in C There's more to interfaces than just naming. You want to group related things together. You want to provide something that makes testing if an object implements a 20-method interface a bit faster than checking for each method in turn. You want more metadata on the interface itself (and not just on every single thing that implements it). Basicaly you want to reify the interface. zope.interface provides all that, and it's based of course on the python features you mention. > That said, I don’t know much about adaptation in Zope component framework [...] But I doubt it would be of any use at the heart of a library. You are very wrong. You should read more about that topic. A library using a component model gives the opportunity to third-parties to interact with it at many levels. Interfaces are just a tool, and an component adaptation model is one thing that can give them real power, interfaces can be more than reimplementing existing functionality. (Oui je parle Français, mais pour le reste de nos lecteurs je préfère m'en tenir à l'Anglais.) > An interface framework is *already* built-in CPython, implemented in C

There’s more to interfaces than just naming. You want to group related things together. You want to provide something that makes testing if an object implements a 20-method interface a bit faster than checking for each method in turn. You want more metadata on the interface itself (and not just on every single thing that implements it). Basicaly you want to reify the interface. zope.interface provides all that, and it’s based of course on the python features you mention.

> That said, I don’t know much about adaptation in Zope component framework […] But I doubt it would be of any use at the heart of a library.

You are very wrong. You should read more about that topic. A library using a component model gives the opportunity to third-parties to interact with it at many levels.

Interfaces are just a tool, and an component adaptation model is one thing that can give them real power, interfaces can be more than reimplementing existing functionality.

(Oui je parle Français, mais pour le reste de nos lecteurs je préfère m’en tenir à l’Anglais.)

]]>
by: Glyph Lefkowitz http://laurentszyster.be/blog/ioc/#comment-772 Wed, 24 May 2006 05:44:12 +0000 http://laurentszyster.be/blog/ioc/#comment-772 >“Where is IProducer.stopProducing implemented?” http://twistedmatrix.com/trac/browser/trunk/twisted/internet/iocpreactor/abstract.py#L260 http://twistedmatrix.com/trac/browser/trunk/twisted/internet/abstract.py#L299 http://twistedmatrix.com/trac/browser/trunk/twisted/internet/_dumbwin32proc.py#L317 http://twistedmatrix.com/trac/browser/trunk/twisted/internet/_pollingfile.py#L143 http://twistedmatrix.com/trac/browser/trunk/twisted/internet/_posixstdio.py#L149 http://twistedmatrix.com/trac/browser/trunk/twisted/protocols/wire.py#L48 http://twistedmatrix.com/trac/browser/trunk/twisted/protocols/htb.py#L206 http://twistedmatrix.com/trac/browser/trunk/twisted/protocols/pcp.py#L65 http://divmod.org/trac/browser/trunk/Vertex/vertex/subproducer.py#L39 ... and so on, and so on, and so on. It is an interface, so it can be implemented anywhere. Applictions implement it, not just the framework. It is a particularly simple interface so you may notice many implementations are similar, but nevertheless there are many, many different things that 'stopProducing()' may do - but it always *means* the same thing: stop producing data. >“Where is IProducer.stopProducing implemented?”

http://twistedmatrix.com/trac/browser/trunk/twisted/internet/iocpreactor/abstract.py#L260
http://twistedmatrix.com/trac/browser/trunk/twisted/internet/abstract.py#L299
http://twistedmatrix.com/trac/browser/trunk/twisted/internet/_dumbwin32proc.py#L317
http://twistedmatrix.com/trac/browser/trunk/twisted/internet/_pollingfile.py#L143
http://twistedmatrix.com/trac/browser/trunk/twisted/internet/_posixstdio.py#L149
http://twistedmatrix.com/trac/browser/trunk/twisted/protocols/wire.py#L48
http://twistedmatrix.com/trac/browser/trunk/twisted/protocols/htb.py#L206
http://twistedmatrix.com/trac/browser/trunk/twisted/protocols/pcp.py#L65
http://divmod.org/trac/browser/trunk/Vertex/vertex/subproducer.py#L39

… and so on, and so on, and so on.

It is an interface, so it can be implemented anywhere. Applictions implement it, not just the framework. It is a particularly simple interface so you may notice many implementations are similar, but nevertheless there are many, many different things that ’stopProducing()’ may do - but it always *means* the same thing: stop producing data.

]]>
by: Laurent Szyster http://laurentszyster.be/blog/ioc/#comment-677 Sun, 21 May 2006 22:15:40 +0000 http://laurentszyster.be/blog/ioc/#comment-677 Hi Florent, >Why use a name convention when you can use an interface framework that gives you proper naming *and* introspectability *and* documentation at the same time, and can also be then used by a component framework that does adaptation between interfaces? Adaptation is the key point to decouple implementations. Hmm. Because it's CPython, not C/C++/Java. Introspection, documentation and dynamic namespaces are allready built-in CPython. You can allready ask: hasattr (instance, '') inspect instance.__dict__ or a class name, find out about a function defaults, print a docstring, etc. An interface framework is *allready* built-in CPython, implemented in C. I don't see the use of another one on top, implemented in Python. And it is possible to implement IOC in Python without additions. That said, I don't know much about adaptation in Zope component framework. It may be of application to compose the last layer of an applications or to quickly assemble parts that know how to work together. But I doubt it would be of any use at the heart of a library. En français dans le texte (but, but, you speak french?): l'utilisation de classes d'interfaces au lieu de conventions entraine les développeurs vers la réplication de certaines fonctionnalités déjà offertes par le language. Au point que certains - à l'esprit particulièrement tordu - finissent par croire que IProducer a un pouvoir magique qui fait disparaitre les dépendences fonctionnelles dans Twisted. Superstition is everywhere ... Thanks for reading, Hi Florent,

>Why use a name convention when you can use an interface framework that gives you proper naming *and* introspectability *and* documentation at the same time, and can also be then used by a component framework that does adaptation between interfaces? Adaptation is the key point to decouple implementations.

Hmm. Because it’s CPython, not C/C++/Java.

Introspection, documentation and dynamic namespaces are allready built-in CPython. You can allready ask:

hasattr (instance, ‘’)

inspect

instance.__dict__

or a class name, find out about a function defaults, print a docstring, etc.

An interface framework is *allready* built-in CPython, implemented in C. I don’t see the use of another one on top, implemented in Python. And it is possible to implement IOC in Python without additions.

That said, I don’t know much about adaptation in Zope component framework. It may be of application to compose the last layer of an applications or to quickly assemble parts that know how to work together.

But I doubt it would be of any use at the heart of a library.

En français dans le texte (but, but, you speak french?): l’utilisation de classes d’interfaces au lieu de conventions entraine les développeurs vers la réplication de certaines fonctionnalités déjà offertes par le language.

Au point que certains - à l’esprit particulièrement tordu - finissent par croire que IProducer a un pouvoir magique qui fait disparaitre les dépendences fonctionnelles dans Twisted.

Superstition is everywhere …

Thanks for reading,

]]>
by: Florent Guillaume http://laurentszyster.be/blog/ioc/#comment-659 Sun, 21 May 2006 14:39:19 +0000 http://laurentszyster.be/blog/ioc/#comment-659 > Why not use a name convention? Why use a name convention when you can use an interface framework that gives you proper naming *and* introspectability *and* documentation at the same time, and can also be then used by a component framework that does adaptation between interfaces? Adaptation is the key point to decouple implementations. > Why not use a name convention?

Why use a name convention when you can use an interface framework that gives you proper naming *and* introspectability *and* documentation at the same time, and can also be then used by a component framework that does adaptation between interfaces? Adaptation is the key point to decouple implementations.

]]>
by: Laurent Szyster http://laurentszyster.be/blog/ioc/#comment-615 Sat, 20 May 2006 16:43:13 +0000 http://laurentszyster.be/blog/ioc/#comment-615 >“By the way what do IProducer, IConsumer, ITransport, IProtocol implement?” As you point out, nothing. They define interfaces. Why not use a name convention? Twisted allready do. And it *is* telling. For instance in the new web2 protocol implementation there is what looks like another interface. What is: doStartReading so good for in http://twistedmatrix.com/trac/browser/trunk/twisted/web2/http.py?rev=16883 to litter the sources with its attribute *and* method implementation, the second depending on the first. >“Where is IProducer.stopProducing implemented?” This is an odd question. Yes, dissent is allways odd. I'm asking because if you follow the dependencies implemented, you'll find out that somehow through an obscure pile of code that does nothing more, you have actually got less. And that you are still tighly coupling transport and protocols to each other through a common dependency on the event loop. Regards, >“By the way what do IProducer, IConsumer, ITransport, IProtocol implement?” As you point out, nothing. They define interfaces.

Why not use a name convention?

Twisted allready do. And it *is* telling. For instance in the new web2 protocol implementation there is what looks like another interface. What is:

doStartReading

so good for in

http://twistedmatrix.com/trac/browser/trunk/twisted/web2/http.py?rev=16883

to litter the sources with its attribute *and* method implementation, the second depending on the first.

>“Where is IProducer.stopProducing implemented?” This is an odd question.

Yes, dissent is allways odd.

I’m asking because if you follow the dependencies implemented, you’ll find out that somehow through an obscure pile of code that does nothing more, you have actually got less. And that you are still tighly coupling transport and protocols to each other through a common dependency on the event loop.

Regards,

]]>
by: Andrew http://laurentszyster.be/blog/ioc/#comment-612 Sat, 20 May 2006 16:00:00 +0000 http://laurentszyster.be/blog/ioc/#comment-612 "By the way what do IProducer, IConsumer, ITransport, IProtocol implement?" As you point out, nothing. They define interfaces. Interfaces are documentation, and also support an explicit way to define adapters from one interface to another. If you wish to find implementations of these things, grep for "implements(IFoo)" in the code, or look at the API docs, which includes an automatically generated list of implementations: http://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.IProducer.html http://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.IConsumer.html http://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.ITransport.html http://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.IProtocol.html Mostly though you don't care what implementation you're dealing with; you just care that the object you're dealing with provides the right interface, e.g. that the object you get from reactor.listenTCP provides the IListeningPort interface. "Where is IProducer.stopProducing implemented?" This is an odd question. It's an interface, it's implemented by classes that implement that IProducer. I think you're trying to ask something else, but I don't know what. FileDescriptor, and most (if not all) transports implement IConsumer, which describes the behaviour of registerProducer. There is no coupling of protocols to FileDescriptor here; protocols that use self.transport.registerProducer depends on their transport attribute providing the IConsumer interface, not a specific implementation of that interface. Protocols certainly don't know or care about implementation details like stopReading, -- just like they care what bytecode python uses. “By the way what do IProducer, IConsumer, ITransport, IProtocol implement?”

As you point out, nothing. They define interfaces. Interfaces are documentation, and also support an explicit way to define adapters from one interface to another.

If you wish to find implementations of these things, grep for “implements(IFoo)” in the code, or look at the API docs, which includes an automatically generated list of implementations:

http://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.IProducer.html
http://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.IConsumer.html
http://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.ITransport.html
http://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.IProtocol.html

Mostly though you don’t care what implementation you’re dealing with; you just care that the object you’re dealing with provides the right interface, e.g. that the object you get from reactor.listenTCP provides the IListeningPort interface.

“Where is IProducer.stopProducing implemented?”

This is an odd question. It’s an interface, it’s implemented by classes that implement that IProducer. I think you’re trying to ask something else, but I don’t know what.

FileDescriptor, and most (if not all) transports implement IConsumer, which describes the behaviour of registerProducer. There is no coupling of protocols to FileDescriptor here; protocols that use self.transport.registerProducer depends on their transport attribute providing the IConsumer interface, not a specific implementation of that interface. Protocols certainly don’t know or care about implementation details like stopReading, — just like they care what bytecode python uses.

]]>
by: Laurent Szyster http://laurentszyster.be/blog/ioc/#comment-610 Sat, 20 May 2006 14:35:33 +0000 http://laurentszyster.be/blog/ioc/#comment-610 Hi Glyph, How do you concile: >IoC is a design pattern that really only applies to a statically-typechecked language. and >Twisted therefore more thoroughly engages in the only IoC possible in Python than allegra, because Twisted has explicit, independent interfaces (IProducer, IConsumer, ITransport, IProtocol) for each aspect of mainloop/application communication. Yet another Twisted paradox? By the way what do IProducer, IConsumer, ITransport, IProtocol implement? I mean, what does their code practically do? Excepted methods declaration: nothing, absolutely zilch. Is a naming convention not enough ... in Python? What is this interface module usefull for, besides making your code *look* more complex than it is. Where is IProducer.stopProducing implemented? How? And where is it called? In FileDescriptor it is called in registerProducer () *and* implemented as: 299 def stopProducing(self): 300 self.loseConnection() which makes it depend on 189 def loseConnection(self, _connDone=failure.Failure(main.CONNECTION_DONE)): ... 203 if self.connected and not self.disconnecting: 204 if self._writeDisconnected: 205 # doWrite won't trigger the connection close anymore 206 self.stopReading() 207 self.stopWriting() 208 self.connectionLost(_connDone) 209 else: 210 self.stopReading() 211 self.startWriting() 212 self.disconnecting = 1 three of those four Twisted interfaces that are coupling much of Twisted to its event loop. I'm sorry, but that *is* written in your own code. Regards, Hi Glyph,

How do you concile:

>IoC is a design pattern that really only applies to a statically-typechecked language.

and

>Twisted therefore more thoroughly engages in the only IoC possible in Python than allegra, because Twisted has explicit, independent interfaces (IProducer, IConsumer, ITransport, IProtocol) for each aspect of mainloop/application communication.

Yet another Twisted paradox?

By the way what do IProducer, IConsumer, ITransport, IProtocol implement? I mean, what does their code practically do? Excepted methods declaration: nothing, absolutely zilch.

Is a naming convention not enough … in Python? What is this interface module usefull for, besides making your code *look* more complex than it is.

Where is IProducer.stopProducing implemented?

How?

And where is it called?

In FileDescriptor it is called in

registerProducer ()

*and* implemented as:

299 def stopProducing(self):
300 self.loseConnection()

which makes it depend on

189 def loseConnection(self, _connDone=failure.Failure(main.CONNECTION_DONE)):

203 if self.connected and not self.disconnecting:
204 if self._writeDisconnected:
205 # doWrite won’t trigger the connection close anymore
206 self.stopReading()
207 self.stopWriting()
208 self.connectionLost(_connDone)
209 else:
210 self.stopReading()
211 self.startWriting()
212 self.disconnecting = 1

three of those four Twisted interfaces that are coupling much of Twisted to its event loop.

I’m sorry, but that *is* written in your own code.

Regards,

]]>
by: Florent Guillaume http://laurentszyster.be/blog/ioc/#comment-609 Sat, 20 May 2006 14:07:29 +0000 http://laurentszyster.be/blog/ioc/#comment-609 Laurent, An introduction to interfaces is here: http://zope-cookbook.org/cookbook/recipe17 While in the example the adapter is registered through zcml, it can also be registered in one line of python instead. Laurent,

An introduction to interfaces is here: http://zope-cookbook.org/cookbook/recipe17

While in the example the adapter is registered through zcml, it can also be registered in one line of python instead.

]]>
by: Glyph Lefkowitz http://laurentszyster.be/blog/ioc/#comment-591 Sat, 20 May 2006 06:39:41 +0000 http://laurentszyster.be/blog/ioc/#comment-591 Laurent, IoC is a design pattern that really only applies to a statically-typechecked language. For example, in Java it is possible to do this: class X { Y y; } class Y { Z z; void doStuff() { z.stuff(); } } That means X depends on Y and Z. To apply IoC to this class hierarchy: class X { IY y; } interface IY { void doStuff(); } class Y implements IY { /* same as before */ } In Python, you are simply calling methods on implicitly-defined interfaces. This is called "duck typing". It may be challenging to "mock" an object properly, but class-dependency is not possible in Python unless your class actually _instantiates_ the object it needs to depend on, and even then it is always possible to fake. The one thing that's harder than reasonable to fake reliably is including two functions in the same class; for example, transport and protocol logic ;-). Twisted therefore more thoroughly engages in the only IoC possible in Python than allegra, because Twisted has explicit, independent interfaces (IProducer, IConsumer, ITransport, IProtocol) for each aspect of mainloop/application communication. Laurent,

IoC is a design pattern that really only applies to a statically-typechecked language.

For example, in Java it is possible to do this:

class X {
Y y;
}

class Y {
Z z;
void doStuff() {
z.stuff();
}
}

That means X depends on Y and Z. To apply IoC to this class hierarchy:

class X {
IY y;
}

interface IY {
void doStuff();
}

class Y implements IY {
/* same as before */
}

In Python, you are simply calling methods on implicitly-defined interfaces. This is called “duck typing”. It may be challenging to “mock” an object properly, but class-dependency is not possible in Python unless your class actually _instantiates_ the object it needs to depend on, and even then it is always possible to fake.

The one thing that’s harder than reasonable to fake reliably is including two functions in the same class; for example, transport and protocol logic ;-).

Twisted therefore more thoroughly engages in the only IoC possible in Python than allegra, because Twisted has explicit, independent interfaces (IProducer, IConsumer, ITransport, IProtocol) for each aspect of mainloop/application communication.

]]>
by: Laurent Szyster http://laurentszyster.be/blog/ioc/#comment-561 Fri, 19 May 2006 22:13:30 +0000 http://laurentszyster.be/blog/ioc/#comment-561 Hi Florent, Do you have a "main" pointer to the sources of that Z3 component architecture. I kind of got lost into the volume of Zope documentation. Thanks for reading. Hi Florent,

Do you have a “main” pointer to the sources of that Z3 component architecture. I kind of got lost into the volume of Zope documentation.

Thanks for reading.

]]>
by: Florent Guillaume http://laurentszyster.be/blog/ioc/#comment-548 Fri, 19 May 2006 20:36:10 +0000 http://laurentszyster.be/blog/ioc/#comment-548 This "inversion of control" is the basis of zope 3's component architecture, where adapters between interfaces are used to do practically everything. You should look it up. This “inversion of control” is the basis of zope 3’s component architecture, where adapters between interfaces are used to do practically everything. You should look it up.

]]>