avalon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Darrell DeBoer <darr...@apache.org>
Subject Re: [Avalon4:PROPOSAL] Context Consensus
Date Thu, 12 Dec 2002 12:03:37 GMT
G'day

On Wed, 11 Dec 2002 09:23, Leo Sutic wrote:
> NOTE REGARDING consensus: Darrell voiced opposition to this scheme.
> However, it seemed to me that the objection was based on the assumption
> that the container would have a dependency on T. Darrell, does your
> objection still stand?

I certainly don't plan to fight tooth and nail over it. However, I've yet to 
see any argument where the benefits of requiring a castable context outweigh 
the added complexity. So yep, I still feel the same way; I'd rather keep the 
context simple.

> There is consensus that a method of specifying a context interface is
> needed in order to specify the Phoenix BlockContext given its current usage
> pattern.

Only to make the current usage pattern concrete and required as part of the 
Avalon Framework contracts. There's no reason that we can't declare the 
current usage to be Phoenix-specific, keep it working in Phoenix, provide a 
better way, and *gently* encourage people to move over to it.

...

> THE CAST-ABILITY OF THE CONTEXT INSTANCE
.. snip ..

> I don't think it is productive to assume that all code written for Phoenix
> can be changed, no matter how small the change. Even if it would only take
> one line of code:
>
>      Change: BlockContext bc =  (BlockContext) context;
>          To: BlockContext bc =  (BlockContext) context.get
> (BlockContext.CONTEXT_KEY);
>
> Multiply that with the number of places, and consider that the project
> where this code exist not only depends on Phoenix, but on some 30-odd other
> APIs that may change slightly, and you have a bunch of developers that do
> nothing but continuously scan the code, making millions of "simple one-line
> change[s]".
>
> Therefore I think that if attainable, the proposal must formally make the
> Phoenix usage pattern valid. Not left as a container-specific extension,
> but formally accepted, meaning that it can't be taken away without changes
> in the stable Framework (as opposed to dropping support for a
> container-specific extension).

I understand your argument for not wanting to make what is common-usage into 
something that is container-specific. But I don't really agree.

In for this "context-meta" stuff to work, developers are going to have to 
write code to upgrade their components. Something to describe their expected 
context entries. Until they do so, if they are casting the context, or 
retrieving a key, they are going to be operating in a container-specific 
manner. That's OK.

But *when* they decide to upgrade to the *new* Context-Meta specification of 
the framework, wouldn't it be good to encourage them to take on a new, better 
usage pattern as well. 
* One that *can* automatically throw a ContextException if the requested entry 
isn't there. (casting can't)
* One that allows Containers to support their request in a simple way, without 
proxies and tricky code, so it'll be easier to support in a resource limited 
environment (J2ME).
* One that let's us add Context.has( String key ), so that "optional" entries 
can be easily tested for by the component author. (I guess "instanceof" would 
work for casting)
BUT MOST IMPORTANTLY:
*A usage pattern that allows us to have a single way of describing what's in 
the context, not 2 separate ways for entries and castable interfaces.

These developers are going to be writing code to support context-meta. One 
more line change won't hurt. And if they don't do it, that's OK. The 
components just may not run in every container.

> The purely practical aspect of this is best illustrated with a scenario:
> Phoenix CVS has burnt up, and all developers had just wiped the Phoenix
> source code from their drives (and of course no one has a backup). Thus,
> all the ex-Phoenix developers have to migrate their projects to some other
> container, and that *fast*.
>
> Say that they decide to move to Merlin.
.. snip ..
> The point of the above is that even if Merlin doesn't support Phoenix
> emulation, adding such code can be done in the knowledge that it isn't a
> hack, but has full support in Framework and can be done without introducing
> any coupling to Phoenix.

Why would "full support in Framework" be so important in such a (far-fetched) 
disaster scenario. Surely we'd just plug Merlin to work like Phoenix (like 
you suggested), but hopefully work out a way to give deprecation warnings.

>
> And that's why I'm pro-context-casting.

And that's why I'm not. And I'm particularly impressed by the arguments 
*against* context-casting in the next section... :)

>
> THE PROPOSAL ITSELF (AS IT IS NOW)
>
> A context is defined by two sets of parameters. The first is an interface
> or a class, called T below. If an interface, it is an interface that the
> supplied context interface must be cast-able to. If it is a class, it is
> expected that the class is instantiated with the T(Map,Context)
> constructor, and that the instance is passed to the component's
> contextualize method.

This makes me feel a bit icky. It *feels* like implementation details 
impacting on framework design. I'd need a good explanation as to why this was 
required before I was convinced. I'm guessing that this is the way Merlin 
populates Context entries from it's "context providers" or whatever they are. 
(Not dissing, just not familiar enough).  I've said before, I think this is 
probably a cool container design, but pluggable "context-providers" don't 
necessarily have to be container-portable, surely. 

Let's get clear, clean contracts that work for the bulk of components out 
there. You know, the one that the *users* of the framework are writing.  The 
ones that access databases and filesystems and maybe need to ask the 
container to shutdown. 

Maybe later we can come up with an infinitely flexible Framework that allows 
us to implement portable lifecycle extensions and context providers. But I'd 
vote to do the easy stuff first, see how it works, and then move on to the 
harder stuff.

> NOTE: In the case where T is an interface, the container must supply an
> implementation for all methods in the interface. This may be done via a
> dynamic proxy that routes calls to appropriate handlers or by any other
> method. The set of methods that a container must support is defined by the
> standard context interfaces in Framework (currently none).

Doesn't this sound very complex, for the simple declaration of "what I want in 
my context"? To me, it looks like the sort of thing that we'd look back on 
and say "what on earth were we thinking?!?". 

Maybe I'm misunderstanding:
You mean we let the Component author declare *any* interface (combination of 
different bits and pieces) as it's context requirements? So I need a 
getHomeDirectory() and a getShutdownRequestHandler() method, so I can just 
invent an interface with those 2? And the Container, if it wants to run my 
component, has to somehow come up with an implementation that can cast to 
that interface? Surely not?

>
> The second set of parameters are the entries accessible via the Context.get
> method and their types. The class/interface T above may have associated
> metadata that specifies entries. These entries must be supplied by the
> container in addition to any entries the component itself requires.
>
> Each entry requirement must specify the canonical key name, may specify a
> name that the canonical key should be remapped to, and must specify the
> expected type of the value:
>
> For an example, where the data is specified in XML:
>
>    <entry intent="avalon:work" type="java.io.File"/>
>
>    <entry key="work" intent="avalon:work" type="java.io.File"/>
>

Ahhh. Now this all feels more real. I want a java.io.File called "avalon:work" 
in my context. Yep, makes sense.

Let's say I expect a java.sql.DatabaseMetaData (interface) in my context. I'd 
ask for it to be an *entry* in my context. It would crazy for me to suggest 
that the container should provide me with a context that I can cast to 
java.sql.DatabaseMetaData.

So why should it be different for BlockContext? Putting aside the fact that 
that's how Phoenix works today. If that's the *only* argument for it, then 
let's be honest and say so; if most people then agree that it's valid, then 
fair enough.

Sorry to be difficult, but this is just my feelings on the matter. Then again, 
since no-one else seems to be objecting, maybe I'm the odd one out here?
-- 
cheers,
Darrell DeBoer

--
To unsubscribe, e-mail:   <mailto:avalon-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:avalon-dev-help@jakarta.apache.org>


Mime
View raw message