On Dec 8, 2003, at 10:38 PM, Phil Steitz wrote:

I missed your earlier comments, unless you mean on the CompositeCollection submission.

* Please try to follow the [collections] style for braces.

No problem, I figured this was just an autoformat via tool of choice -- can do so if it needs it. I (maybe mistakenly) assumed that anyone reading it would autoformat it to their preferred format anyway, and as only a collections committer can check it in -- his or her autoformat will work fine.


Why does CompositeSet extend CompositeCollection? The setup looks a bit strained to me (e.g. the type checking in the addComposited method).

As the majority of the behavior is identical behavior inheritance make sense in this context. The only behavior that changes is the calculation of equals() and hashcode(), and the requirement that elements be unique. Really the composited elements don't NEED to even be sets, but it is convenient for avoiding the situation where modification of the underlieing data structure invalidates the internal state of the composite. An inheritance by delegation would allow the reuse of behavior at the expense of more code and would allow typesafe addComposited(...) if you mind this. It is more code in that you need delegating stubs, but is a minor point.


Looking carefully at what addComposited does in CompositeSet, I am not sure that I understand what CompositeSet and CompositeMap are trying to do.

They do the same things. Collision handling was added as a convenience -- the default behavior is to throw an IllegalArgumentException if there is nothing set to handle the collision. The collision handling came from a requirement in my original implementation. If you feel it muddies the implementation rather than add useful features remove it. In the original implementation it was separate from the concept of the strongly typed Mutator interface that Stephen introduced to the CompositeCollection which could be used separately from the mutators (which were specified per-method rather than via a strongly typed interface).


I understood CompositeCollection to be a convenient way to decorate a collection of Collections to provide a unified view. Once you try to control "collisions", as in the Set and Map impls, you seem to be headed for some kind of partition concept. Is that what you had in mind?

There is a degree of partitioning that needs to occur - hence having the mutators undefined by default, but allowing definitions. There are really two concepts at play here. The first is the composite concept, the second is mixing in implementations of the mutators -- it externalizes the mutation operations as on a composite they are pretty much always special case operations if they are supported. The easier solution is to make composites immutable -- but as I mentioned, when originally developed I needed them to be mutable.


Also, since add() and resolveCollisions() are separate methods in the mutator interface, one could presumably do inconsistent things -- i.e., allow "duplicates" to be added directly via add() but disallow them in addComposited() by having resolveCollisions prevent duplicates.

You are correct that people could break the class if they wanted to. The default behavior is to disallow mutators (OperationNotSupported), and to throw an IllegalArgument on collisions. If you accept responsibility for mixing in mutators you need to be willing to solve that problem I think. Disabling mutators completely by dropping the ability to specify mutators is an option, and prevents people from hurting themselves, but I personally prefer to allow them hurt themselves if they have to work to do it (separately define mutators), and keep the classes more flexible and powerful.



Can you explain a little more what the use cases for these things are?



A lot of the uses grow out of the limitations of O/R mapping. The typical case in which I have used them is in hierarchical aggregates mapped to objects from a relational database. This case has occurred several times in different projects I have worked on, here is a typical example where a Group has members but it needs to include its children's members in the ones it presents to clients (Group in this case decorates a single instance, itself, and additional child instances) :


class Group
{
        private Set members;
        /** Instances of Group */
        private Set children;

        public Set getMembers() {
                CompositeSet set = new CompositeSet(members);
                // Would add collision handling and mutators if real
                for (Iterator i = this.children.iterator(); i.hasNext();) {
                        set.addComposited( ((Group)i.next()).getMembers());
                }
                return set;
        }
}

Specific behavior designed for includes supporting lazy-loading of the composited collections (don't get more information than is absolutely needed for a given operation as the database hit is typically far worse than the extra calculation), degradation of behavior as circumstances get unusual (collisions) but not downright broken (exceptions) rather than breaking for special cases (ie, in the above example, a member appearing at multiple levels of the hierarchy), and the ability to change how mutations work based on a lot of different criteria (factory/builder for mutators). Basically really flexible collections that composite nicely.

An additional use case is in an SQL generator that functions via a query-by-criteria with automatic reordering of elements based on where they belong in the query. Composited collections of query elements (columns, tables, sub-selects (with the full panoply of elements), join criteria, where criteria, etc) allow for maintaining a flexible model of the query at any given time but still be able to access all parts for nice things like extracting token replacements for mapping prepared statement binding values to the correct place in the query when it is actually bound. (I cannot open up this particular library at the moment as it was done on company time and is the company's IP)

If there is violent opposition to adding these, by all means please don't. I'm just trying to make available resources that I thought would be helpful and to my mind fit in well with things already in [collections].

-Brian



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



Reply via email to