Carsten Ziegeler wrote:
Aren't you tired of implementing a service/dispose combo for each of
your components over and over again? Now, actually, I am. Big time.

If you look at several of our components, they do something like this:

class MyComponent implements SOMETHING, ThreadSafe, Disposable,
Serviceable {
protected ClassA compA;
protected ClassB compB;
protected ServiceManager m;

public void service(ServiceManager m) {
  this.m = m;
  compA = (ClassA)m.lookup(ClassA.ROLE);
  compB = (ClassB)m.lookup(ClassB.ROLE);
}
public void dispose() {
  if ( m != null ) {
    m.release(compA);
    m.release(compB);
  }
}

The test "m != null" is useless, as dispose should never be called twice. Removes 2 lines :-)

Way too much code me thinks. So what about:

class MyComponent implements SOMETHING, ThreadSafe {
  protected final ClassA compA;
  protected final ClassB compB;

  public MyComponent(ClassA a, ClassB b) {
    compA = a;
    compB = b;
  }
}

We could simply add constructor injection: if the implementation does
not provide a default constructor, the available constructor is called
using reflection and the components are injected on construction of the
object - no need to configure something in any xml configuration file.
Implementing this is easy - I did this already years ago for Fortress.

But I think it can even get easier:
1. Let's just assume that every component is ThreadSafe - unless
otherwise stated - no need to declare the interface anymore. I think
apart from the interpreter most components are threadsafe or poolable
anyway.

This is a huge change compared to the current behaviour, where no interface means not threadsafe and not reusable. IMO, this change can only happen if we completely move away from Avalon.

2. Let's remove support for pooled components - yes, seriously. Fiddling
with the pool sizes is really annoying. We have a working factory
approach for sitemap components, so why not simply use it overall? And
rewriting the remaining pooled components shouldn't be that hard. (I now
that we are proxying pooled components to simplify the lookup, but you
still have to configure pool sizes).

+1 for generalizing the factory pattern. Cocoon spends way too much time in checking Avalon's lifecycle interfaces and parsing configuration objects.

My final idea is to use even more magic (but it might be too much magic?):

class MyComponent implements SOMETHING {
  protected final ClassA component_A;
  protected final ClassB component_B;
}
When the component is instantiated all instance variables prefixed with
"component_" are setup using some injection mechanism - or perhaps using
annotations?

Hmm...
- how do you unit test Cocoon without the container? By subclassing to access the protected fields? - we can't strongly enforce the contract of subclasses by making some fields private. - the naming convention weakens the strong typing of Java. What if you write "conponent_A"? Chasing the NPE won't be easy...

Now, in the end I really want to write less code :)

Use Ruby :-P

Seriously, I agree that writing less code is good, but not at the price of too black magic implying weaker contracts.

Sylvain

--
Sylvain Wallez                        Anyware Technologies
http://bluxte.net                     http://www.anyware-tech.com
Apache Software Foundation Member     Research & Technology Director