Ted Husted wrote:

Craig R. McClanahan wrote:

Do you think we should make a Catalog an optional property of a Context? A lot of use cases would like to have a default spot to go find one, and you can always have private conventions about what other attribute keys might also point at other Catalogs.


If we are talking about the Context interface, it might be problematic, since it would seem that any property we define there would steal it from the application. So, they could not have a "context" attribute of their own, even if they were using context in, well, a different context =:)

Yep :-).



But if by optional we mean a property on a base implementation, then that would seem all right. Worst case, they implement their own base. I like the loosely knit relationships between the three interfaces, but at some point implementations do need to start to nail things down for people.

Agreed. We want the right balance of ease-of-use and flexibility.



Of course, once we do that, a question someone is going to ask sometime is "Why doesn't the Command just have a pointer to its Catalog?" I'm not convinced it would be a good idea, but it's something we should ask and answer.

Thinking out loud to get my initial answers down for posterity, I don't think we want to require the use of Catalogs at all. I *certainly* don't think we should constrain a Command (or Chain) instance to be associated with a single Catalog.



Another popular question will be, "Why isn't the Context itself a Map?"

Well, it is-a Map of sorts (or more precisely, it has-a Map as its data representation). But what it also offers is a couple of interesting things:


* Ability to have type-safe accessors like any JavaBean.

* Attribute-property transparency (at least if you implement the Javadoc
 contracts for Context, or use ContextBase to do the hard part for you).

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.


In my own base class, I needed to make it a Map (through composition - the Map methods just call back to getAttributes) so it could mesh with other parts of the application. It's going to be a FAQ, so we might want to deal with it now.

As pointed out in the discussion below, it's not necessarily trivial to do this.



I think the answer is going to be extensibility, but we might consider an optional implementation that provides a Map interface for people to use.


On a related subject, how do we feel about the BaseContext2 class that allows property fields to be stored in the attribute Map? I have mixed feelings about the implementation, since it bends encapsulation, but I *really* like the idea of keeping all my fields and attributes together.

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 :-).

A different approach to meet your desire might be to actually store the property names in the existing Map, with the values pointing back at the actual instance variables. We'd probably want to make remove() throw IllegalArgumentException on attempts to remove them. The other complication would be you can't do this for primitive properties, since you can't store them in the real Map.


-Ted.

Craig





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




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



Reply via email to