long again.

Berin Loritsch wrote:
Leo has some good points, and as usual, he likes to explain himself
in code :).

code can be dense and is usually unambiguous. It has the disadvantage of people usually sprouting of in finding ways to improve the code without digesting the message an example is ment to give. When you are not exactly sure what you are saying, an example avoids overgeneralizing. Explain by example is easier for me than explain by philosophy :D

Another question is how to protect people's investments so far. We
all have had a certain amount of investment in Avalon, and we don't want to throw it away.

if KISS is the main point I raised, this is the main dilemma we face.
How much "refactor mercilessly" can we apply to our core art? How do we
manage not only changing contracts, but also changing ways for defining those contracts? It's difficult. Strong typing means that implicit contracts might be explicit in practice.


== More Bullet Points ==

1) Protect your current users.

+1


2) Evolve the framework--don't redesign it.

yes...the difficulty with this is that it is extremely difficult to cleanly support evolving coding patterns that go above and beyond language-level features. This is a big challenge.


Picocontainer involves a complete redesign of "the framework", in that most of avalon-framework is simply replaced with some simple coding conventions. But it is still potentially compatible.

3) Follow XP practices.

+1


4) Add features incrementally.

and figure out how to build for extensibility to support this. Current avalon-framework is not geared towards extensibility. The excalibur-extension package allows extension in one direction; other directions remain difficult. Like the extension of a Context interface being problematic. Look at the amount of work, energy and complex code it is taking to provide even basic framework extensions in merlin. Jason 'n co hit the same basic problem a few times with plexus.


IOW, it is currently easy to add features to an implementation, but it is not easy to add features to every implementation without constraining ways for building that implementation.

5) Have an idea of what you are doing.  While I agree with Paul that
"Big Design Up Front" is detrimental, I also believe that you have to
have a general direction or overarching concern for a system.

exactly.



== Contracts ==


The others I completely agree with, so let's move on.  From Chapter 1
 from my book (which may or may not get published BTW) has this to
say on contracts:

<snip/>

I advocate KISS, but there is a balance of writing/enforcing contracts. You want *enough* rigidity so that you can reliably predict the results, but no more than that. Having the contracts so binding that there can only be one real implementation is a tragedy in my oppinion.

good explanation. Yes.


Why are you describing an axis with KISS on one end and rigidity on the other end? I think they're orthogonal?

Another important, related point:

*you never get a contract right the first time*

In designing an avalon-based system, I usually find that the second go or so at decomposition achieves acceptable results, but from there on the actual shaving of the interface up to reasonable maturity can be hard. And contracts can be difficult to refactor. I think that XP practice and strong contracts are more difficult to combine than KISS & contract.

* asynced events, pipelining -> we have support for this,

disagree. We have a cool library that could be used to build support for this. However, we have not integrated event-style contracts into our framework or containers. The container-component contract is our core art, and we use a handful of always-in-order "pseudoevents" (namely, enableLogging(), contextualize(), configure(), ....). Essentially our callstack is predicatable, stale, and execute-once.


Remember talking about the Command pattern back when finalizing 4.0? Large-scale systems are now popping up everywhere with support for it, and stuff like SEDA has shown us how to apply it more generically. Which means now might be the time for figuring out how to apply it to the container-component contract.

* attributes -> :) We have a minimum, and we have some work that
needs to be done to finalize this.  Let's not get religious about it,
but work on a truly workable minimum and then how we can safely
augment it.  I think we need to standardize on the way we store and
retrieve the meta info (not necessarily on an object model for the
info).

agree.


* apects -> Containers take care of many aspects for its components.

well, yes. One of the points with AOP systems is not only that you use AOP, but also that you make it easy to add/remove/customize your aspects. If you call configuration an aspect, well, the container manages it for us. But it is nontrivial to plug in in a ConfigurationManager into a container, let alone write one that will work for multiple containers.


We can take better advantage of that.

another challenge :D


* scriptability -> This is not a requirement, but it helps in many
problem domains.  Scripts should be treated as commands in the
system.  Those commands are executed in response to certain events.

indeed. It seems to me that most actual activity or logic execution could be captured in scripts. The first step is allowing pluggable logic execution at any point (using a workflow-style tool, perhaps), once you have that, plug in a logic manager that uses some kind of resolver and parser to encapsulate command execution.


* pluggability -> If we can conquer this, then it will open the door
for all the other things we need to be better about like aspects and
scriptability.

the key is designing for pluggability. Merely relying on a COP-based container makes pluggability possible, but doesn't make it easy. Like the nontrivial step one needs to take to plug fortress into merlin.


For all its static nature, phoenix is the only container that currently comes close to actually making plugging in different implementations of "stuff" possible. It achieves to maintain predictable by clearly outlining the possible plugins, and often accepting only a single plugin to perform a specific role. This is similar to many other component systems (like JBoss allowing you to plug in either Jetty or Tomcat, but not both on a per-webapp-basis).

* strong typing -> This is a language feature of Java, C#, and
several other languages.  You can't force strong typing on systems
where there isn't strong typing to begin with.  Or perhaps you are
talking about something else.

everytime you do something like


        initialize( Map map )
        initialize( Tree tree )
        initialize( Context context )

or

service( ComponentManager manager )

what you do, in fact, is remove some strong typing in favour of utilizing methods. Avalon-Framework generalism is mostly implemented by sacrificing strong typing in favour of type casts.

Avalon 4 Doesn't Cut It:

Those that have been advocating an Avalon 5 caught this vision way
back when.

yep. The way I see it, most of us have been striving to find the "why" after that, and with growing experience now is the time to drag out those analyses. We need to analyze and agree on the why. When all our discussions marked '[A5]' took place for the first time, we did not succeed in finding a common analysis of limitations and needs. Just like I imagine happened with A2, A3, and A4.


We recognize that we need to simplify the contracts as
much as possible.  We also need to strike a balance between work that
the component writer has to do and work that the container has to do.
IMNSHO, the container should take care of more work than the
component writer.

indeed. With avalon, the component writer has to do too much work. We have started of with many strong and explicit contracts. This is good. Through experience, I think we're becoming able to figure out which contracts to make less strong, which contracts to merge, etc etc.


Otherwise the same issues will be present time and
time again.

very true again. The issue(s) to tackle for avalon remain exactly the same as they were 4 years ago. They still exist. We arrive at a better solution every iteration.


Smaller Is Better:

maybe it is mainly "simpler is better". While one has to do a lot of *work* to write an avalon component, what is imho more important is that one has to do a lot of *understanding* to write an avalon component.


Paul has talked to me about a more Bean-like component architecture
that he and other well respected folks have been working on in an XP
manner.  It seems to work.  There are some things that are great like
setXXX() methods for your components which makes the framework
strongly typed--but it also makes certain aspects of
container/component contracts more difficult to implement. That's not
a real blocker for me though.

He has also talked to me about using constructors for write once assignment of the components. This has a twofold advantage for
making the components read-only without resorting to proxies, and
making it easier for the component to obtain them.


There are some challenges to that approach that need to be resolved:

1) Managing changes in the constructor 2) Managing ordering of
dependencies esp. when more than one type is compatible.

These can be handled with a declarative method (i.e. attributes), and
can definitely be explored.

these things are mostly implementation issues. Some of the achievements here that are valueable:


- more strongly typed code, removal of most typecasts, removal of most container-component concern-related exception handling from the component code

- using language-level features to encode contracts to maximum extent. (The only real way to do write-once using language-level features in java is the use of the constructor)

the former is implemented cleanly and predicably in picocontainer. The latter as well, but many other limitations of the constructor quickly become apparent as well. It is difficult to manage change in the constructor, there must always be ordering, optional dependencies are difficult to set up (you need to test against null), and application of a declaritive method may be more difficult.

I think I like setXXX() better with the write-once contract encoded in some other way. Especially since the write-once contract is something you often only want to apply conditionally. Like setValidate( false ) might make perfect sense. I think we need to wire in the configurator pattern that exists in plexus (ServiceBroker.lookup( String role, Configuration conf ). Not sure how, though.

Macro Concerns:

It seems to me that packaging and component classloader architecture
are bigger issues than the fine component contracts for the time
being.

hmm. Issues for whom? Phoenix classloader architecture works for me. For embedded stuff, I have never found a need to bother with classloader architecture, as whatever I choose to embed things in (9 times out of 10, servlet engine) usually provides enough classloader architecture of its own.


Packaging, yes, that is a concern which needs addressing (assuming you're referring to the Bundle API idea). I think it is a concern much broader than avalon itself. I am still not so sure whether it is a good idea to develop a packaging standard within avalon.

To be more honest, I am getting the feeling that a usable packaging standard will arrive from within the depths of maven-new sometime soon. And maven is gaining so much mindshare so rapidly it might be best to just ride along with these guys, focussing on our core art.

Classloaders are an implementation issue (that should be addressed using Classworlds or a similar library imho), the packaging challenge is bigger than avalon.

Separate API/Impl:

The code snippet did not do this.

what snippet didn't?


 The container must be in charge of
this. Components should be able to stand on their own merits.

+1


back to work now :/

- LSD



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Reply via email to