[PEAK] Dependency Injection Examples with PEAK?
Phillip J. Eby
pje at telecommunity.com
Sat Mar 6 12:39:49 EST 2004
At 02:35 PM 3/6/04 +0100, Tom Schwaller wrote:
>After reading Martin Fowlers Article about Dependecy Injection (aka
>Inversion of Control (IoC)
>
>http://www.martinfowler.com/articles/injection.html
>
>I wonder how to compare PEAK with picocontainer.org / nanocontainer.org,
>springframework.org and avalon.apache.org.
>
>Is it possible to write code with PEAK the way e.g. springframework.org
>(new kid on the Java block) does it? I mean: complete separation of
>Components and Configuration/Composition of Components. Looking at the
>PEAK examples in the Dev-Wiki I have the impression that by using PEAK I
>have to stick it deeply in my code and will never be able to get rid of
>it.
Why would you want to be rid of it? ;)
Seriously, the point of putting Obtain and Make bindings in your components
is to allow them to provide sensible defaults. There is nothing stopping
you from overriding those bindings via keyword arguments, subclassing, or
direct attribute assignment. And, if you use ZConfig, you can even
assemble your complete application from data.
A lot of the differences between the Java frameworks and PEAK have to do
with the differences between Python and Java. In Java, you get
type/interface metadata "for free", so just by creating a class with the
right signatures, you have a "bean", and can then do things with it.
In Python, attributes and method signatures do not have any type
information, so there is no way you can do something like any of the Java
lightweight containers without either adding something into the class to
provide metadata about required types or interfaces, or externally
specifying that metadata.
To me, externally specifying the metadata is infeasible as a primary
mechanism, because it means that you have to look in more than one place to
understand something that's pretty fundamental about the component. Thus,
PEAK uses descriptors to define a component's required parts directly
within the component class. You can still use ZConfig to define external
metadata, i.e. how to convert from strings or structured data in a ZConfig
file to that object type.
>Maybe someone has a PEAK example which "emulates" the
>Springframework approach (Setter Injection beeing the prefered IoC
>approach there)
Pretty much, if you want to do data-driven injection of that sort, ZConfig
is the way to go, and you don't necessarily even need to use PEAK.
For most applications, most of the time, however, I think you'll find that
automatic dependency resolution (using PEAK's equivalents to "autowiring")
is much more convenient and less error-prone than manually wiring
everything together. When I use ZConfig, I prefer to still use PEAK
components that can have their singleton and global configuration needs met
by PEAK configuration lookups. Then I get the best of both worlds: the
ability to override anything, but having sensible defaults if I don't need
or want to override them.
(And again, note that PEAK's autowiring requires only that you specify in
your component what interfaces you depend on -- exactly the same as Spring
does, only in Python you need a descriptor to say what interface that is,
while Java forces you to declare that anyway.)
I think you'll find if you delve into PEAK a bit more, that PEAK has a much
more comprehensive configuration architecture than either Spring or
PicoContainer. For example, in addition to constructor injection, setter
injection, and interface-based autowiring, we also support named
properties, plugins, absolute and relative path references, naming-system
based references (ala JNDI), and unlimited nesting of contexts (allowing
any component to offer services to its children, rather than having just a
single "application context").
More information about the PEAK
mailing list