commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ted Husted <hus...@apache.org>
Subject Re: [Chain] DTD, Design Considerations, etc. (was Re: [Chain] examples XML file available?)
Date Sat, 27 Sep 2003 03:56:48 GMT
Craig R. McClanahan wrote:
> The latter lets any Command lets any Context implementation be passed 
> in, but still provide generic access to the specialized properties 
> without casting.  For example, if your Command is passed in a 
> ServletWebContext you can try:
> 
>  Map map = (Map) context.getAttributes().get("requestScope");
> 
> without having to know what Context implementation was used.  The things 
> that are accessed through the typesafe property getters and setters are 
> *not* hidden; and you can program solely to the generic Context API if 
> you want to avoid creating dependencies on external Context 
> implementation classes that may or may not be present.

It still doesn't seem like we're answering the question of why does the 
context have-a-map instead of being-a-map. If Context extended Map, 
rather than specify a Map property, could not the BaseContext implement 
the ContextBaseAttributes code directly, instead of as a property? Why is it

context.getAttributes().get("attribute);

instead of

context.get("attribute");

As you've said, we already have a standard interface for a Context ... 
Map =:) Why are we creating another? (An object with a Map.) Are we just 
following the example set by ServletContext? That in itself is a 
fair-enough reason, but I wondered if there were another.

(Another reason might be that isEmpty could conflict with a client 
attribute (but, conceivably, so could getAttributes)).

Of course, it's not hard to have it both ways. I've been using a 
ContextMap class as a base, which I'll post as another experimental 
class. It just implements the Map interface by calling getAttributes. 
(Should we setup a "whiteboard" or "opt" package for these?)


> My problem with this is what it does to implementors of subclasses of 
> such a BaseContext2.
> 
> Lots of people can type the idiom for creating a new property on a 
> JavaBean without even thinking about it:
> 
>    private String foo;
>    public String getFoo() { return this.foo; }
>    public void setFoo(String foo) { this.foo = foo; }
> 
> and there are lots of IDEs that will do it for you too.  Unfortunately, 
> such code won't work in a BaseContext2 subclass; you'd have to change it 
> to:
> 
>    public String getFoo() { return ((String) getAttributes().get("foo")); }
>    public void setFoo(String foo) { getAttributes().put("foo", foo); }
> 
> I can guarantee you that this kind of code doesn't roll straight off 
> your fingertips :-).

Either approach works with Base2. You can mix and match member fields 
with Map entries. I definitely wouldn't suggest obviating member fields, 
since it's such a common strategy.

The code I use now to access the Map entries as property values looks 
like this:

     public String getApplicant() {
         return (String) getField(Tokens.PN_APPLICANT);
     }

     public void setApplicant(String property) {
         putField(Tokens.PN_APPLICANT, property);
     }

And I've the IDE programed to prompt me for the Property and Token names 
when I need to create one of these, so it's not so hard. (Though, just 
telling it to encapsulate a field is even easier.)

As it stands, I'm not declaring properties for simple String fields, but 
only for key fields that are often used in API class and those that need 
type-safety. So like 80% of the attributes don't need properties anyway.

What I don't like is that getField and putField bypass the reflection 
mechanism, and so become a backdoor that accesses the underlying 
attribute map directly. At the very least, this seems to bend 
encapsulation.

I do believe that it would be better if we didn't compel people to use 
member fields when there's a perfectly good Map sitting there, but I'm 
still not thrilled with my implementation.


> The other complication would be you can't do this for primitive 
> properties, since  you can't store them in the real Map.

I suppose the properties could store them in the wrapper classes and 
turn them back to primitives on the way back. Since most data access 
tools don't like primitives, I rarely use them as attributes myself.

-Ted.




Mime
View raw message