January 15, 2004

Ioc types

I am a bit puzzled by Martin Fowler's description of the difference between IoC type 1 (interface injection):

class MovieLister implements InjectFinder...
  private MovieFinder finder;
  public void injectFinder(MovieFinder finder) {
    this.finder = finder;
  }

and IoC type 2 (setter injection):

class MovieLister...
private MovieFinder finder;
public void setFinder(MovieFinder finder) {
  this.finder = finder;
}

These two methods look exactly the same to me, except for the name of the method the initializes the component and the interface implemented by the first component (the second component could implement an interface as well).

Am I missing something?

 

Posted by cedric at January 15, 2004 04:14 PM
Comments

Type 1 relies on casting vs Type 2 relies on reflection. The difference is mostly in the container implementation.

Posted by: at January 15, 2004 05:46 PM

There is neither casting nor reflection in either of the two code snippets that I reproduced.

Glad to see I'm not the only one confused.

Posted by: Cedric at January 15, 2004 05:49 PM

When container injects dependency in the first case it will be "instanceof" followed by the cast, the second case will produce code looking for a Method" and its signature.

Posted by: Pinocio at January 15, 2004 08:00 PM

In the XWork implementation of IoC (very simple) instances are keyed off of the enabler Interface, as shown in what he's called Type 1, so I guess he'd call that Type 1. It basically just looks through the Interfaces implemented and looks for them in its registry.

What I had previously heard referred to as Type 1 was the Avalon type config which ended up needing a dependency resolver to basically do service locator stuff to fulfill the dependency.

Posted by: Jason Carreira at January 15, 2004 08:12 PM

It's actually fairly simple: with setters, you have no assurance that the setter will be called once and only once. Some idiot might come along and call the setter again.

Or, if you're not using the framework, some idiot may not call the setter in the first place.

By using the constructor, you _know_ that the object is correctly made, and that immutable properties won't change.

Posted by: Robert Watkins at January 15, 2004 08:47 PM

Unless, of course, someone calls the constructor with null values...

Posted by: Jason Carreira at January 16, 2004 06:01 AM

Cedric, I share your confusion with the description of IoC 1 in Martin's article.

According to the PicoContainer website, IoC type 1 (Contextualized Lookup, the new fancy schmancy name) pushes the dependency lookup and wiring down to the consumer service. (http://www.picocontainer.org/types-of-ioc.html)

But, Martin's definition really doesn't illustrate this at all. His example,

class MovieLister implements InjectFinder...
public void injectFinder(MovieFinder finder) {
this.finder = finder;
}

Should really be something along the lines of,

class MovieLister implements InjectFinder...
public void injectFinder(ServiceRegistry registry) {
this.finder = (MovieFinder)registry.lookup(MovieFinder.class);
}

Or, am I confused as well? :)

(As a side note, although IoC is very generic and perhaps a tad ambiguous from a descriptive standpoint, injecting - pun intended - new terminology consisting of big long words I think only serves to raise the barriers to entry and scare off the bulk of would-be adopters.)

Posted by: Joe Duffy at January 16, 2004 08:38 AM

Hmm, now that I think of it, "Inversion of Control" is pretty big, long, and scary as well...

Posted by: Joe Duffy at January 16, 2004 08:40 AM

"Type 1 relies on casting vs Type 2 relies on reflection. The difference is mostly in the container implementation."
I meant that in your example, the container would do this for Type 1:
((InjectFinder) service).injectFinder(finder);

compared with this for Type 2:

and the container would:
ServiceUtil.set(setterName, dependentService);

Posted by: at January 16, 2004 09:45 AM

correction for previous comment:

<service id="movielister" class="MovieLister">
<property name="finder" serviceRef="moviefinder" />
</service>

ServiceUtil.set(parentService, propName, dependentService);

Posted by: at January 16, 2004 09:48 AM

Cedric - I think that it is an over-categorization myself, but the main differences can be seen between SpringFramework and Avalon. The only concrete difference is the interface implementation, and more specifically, the existance of the interface itself. SpringFramework injects dependencies based on Javabeans specifications (and reflection), Avalon uses instanceof on the known interface types and casting. They are considered different because of this.

Are you missing something? No. I think it is really people trying to segregate and seperate themselves - uniqueness goes a long way. Avalon is a non-reflection implementation, that's all. The main advantage of Type-2 is you don't have to mitigate IOC concerns into the class file (by implementing interfaces for the container).

Posted by: R.J. at January 16, 2004 02:09 PM

Isn't IOC, or whatever we're calling it here, a prime candidate for a "separation of concern" type of AOP solution. Basically, all the talk is having a push type of model to produce auto-wiring, auto-dependency, etc...

Couldn't this whole problem be addressed through cross-cutting against the "new(..)" keyword. Let all the auto-wiring be triggered through this standard java keyword.

A simple example:

public aspect IOCAspect {

pointcut creationAspect():
call(MovieFinder.new(..));

Object around():creationAspect(){
// Implement the Actual concrete instance
Object newObject = ... whatevever factory
return newObject;
}

}

Then have a Container:

public class MovieLister {
MovieFinder object = new MovieFinder();

...
}

The container becomes "auto-wired" through the creationAspect advice without any restrictions on Setter or Constructor "Dependency Injections".

Posted by: Frank Bolander at January 16, 2004 03:08 PM

It's simple. If you don't name the method inject, it will be boring Inversion of Control and you couldn't talk about it it. It's not romantic at all.

Personally I would like weared Data Transfer Object to be renamed to Data Teleport Object. This alone will make RMI trasnfers instant.

Posted by: Slava Imeshev at January 16, 2004 03:20 PM

Cedric,

for me there is one big difference between IoC-2 (setter) and IoC-3 (constructor):

After the constructor is called, the object has all its properties and is ready to be called in IoC-3. In IoC-2 the constructor is called and the object is (maybe) not ready to be called, because some dependencies are missing.
So in IoC-2 you have to implement something like a state: CREATED->CONFIGURED->READY
In IoC-3 you don't need this state because after object creation the object has always the READY state.

Mirko

Posted by: Mirko Novakovic at January 19, 2004 01:10 AM

Cedric, I think you're right to be confused; I am too. The crucial
point is where Fowler says "For simplicity's sake, I'll do it in
code." If you "do it in code", then there's no interesting difference
between the "setter" and "interface" patterns, and so the entire point
is lost. The real question is whether the framework that uses
"interface injection" (Avalon or whatever) was told something special
about the InjectFinder interface, and, if so, what.

In fact, the only reason that the whole topic is interesting enough to
write about is because of the way these component framework
architectures work. However, having never seen any of these
frameworks, it's hard to compare and contrast the approaches; Fowler's
brief introduction to the frameworks is too brief, especially in the
case of Avalon.

His example of a Spring XML file is confusing because at first glance
it appears that the value of an "id" attribute of a "bean" element is
the name of a Java interface. Only when you notice the lack of the
package prefix do you realize that this is really a misleading
coincidence (I think!); he should have given them different names.

In the PicoContainer case, what am I supposed to assume that the
following line of code means:

pico.registerComponentImplementation(MovieFinder.class, ColonMovieFinder.class, finderParams);

Does this mean that whenever anybody asks for an instance of
MovieFinder interface, the framework will always use the
ColonMovieFinder implementation and always pass in "movies.txt" to the
constructor? Or does it mean that whenever anybody asks for an
instance of the ColonMovieFinder class, the framework will always pass
in "movies.txt" to the constructor? Or something else?

When he starts talking about "service locators" he completely loses
me. Why would a class with a broadly generic name like ServiceLocator
just happen to have a method specifically about movies? If
ServiceLocator is part of the movie world rather than part of the
framework, it should have some better name. And from then on he makes
the same "I'll do it in code" mistake.

Posted by: Dan Weinreb at January 22, 2004 07:56 PM
Post a comment






Remember personal info?