commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ola Berg <ola.b...@arkitema.se>
Subject Re: [all commons] Proposal: CommonsCommons package
Date Sat, 15 Jun 2002 22:42:57 GMT
Michael A Smith wrote:
>The transform stuff
>and predicate stuff that is in the collections project doesn\'t
>necessarily need to be \"restricted\" to collections.  That is, they
>probably should exist outside of collections and have collections
>depend on them.

Exactly, that\'s one strong argument. The strongest argument is however
that they

Michael A Smith wrote:
>Instead, it would probably be appropriate to move these into other
>commons projects.  For example, \"lang\" or \"codec\" (for transforms).

Well, \"lang\" maybe _is_ the commonscommons I seek.

Stephen Colebourne wrote:
>I know I might be a little controversial to separate out those 5, but
>they do often seem to be used as a group. (And this also affects the
>people working on them.) Something to tie the three groups together
>could be useful, but it could also be troublesome.

My argument is not that one should separate the common mechanisms just
because one could, but for the great architectural benefit that would
come from it if the different components used the same
implementations of common mechanisms (which is the rationale for
jakarta-commons in the first place I believe).

And in order to _not_ make the packages you mentioned interdependent,
one _has_ to single the common mechanisms out, _no matter how small
they are_! (In fact, size of a mechanism should not decide whether it
should go in a separate package or not, the key is if the classes are
tightly related or not).

In the Configuration thread I pointed out that the Avalon configurator
needs a set of \"transformers\" in order to transform the String values
in config files into real Objects. The converter somewhere in commons
does just this, so why does Avalon config have to implement its own
set of conversions? A developer with a certain new data type should be
able to provide just one converter/transformer for this (or in my
framework: just make sure that there is a String constructor so that
the default from-string-converter can do it\'s work).

>Even adding some extra interfaces
>doesn\'t really make the case. You suggest Named (or Nameable ;-)
>although I\'m not sure what advantage/use it gives. Earlier today in a
>betwixt discussion I suggested Identifiable.

1) Identifiable is better than Named. And 2) one single common
interface really can make all the difference, even if it is small and
very specialized (offering only one method). What would the SUN
JavaAPI be without Comparable? Imagine how much of the usability of
java.util that would be gone if there wasn\'t a generic Comparable
interface.

And what if the FileFilter in getFiles( FileFilter) in java.io.File
had been a generic ObjectFilter (or the more generic name Predicate)
instead of just a filter for File objects?

Identifying such similarities in roles and making a separate Interface
for it is PlainGoodOODesign. It makes the work so much easier, once
one gets hold of it.

>One possible solution is to resurect the lang sandbox package which
>seems to be asleep and add these things to it.

Hm, \"lang\" really _is_ the thing, isn\'t it?

>The real trouble is deciding what is truly absolutely
>unquestionably common however. If you\'ve seen a logging flame war,
>you\'ll know that the more common it is, the higher the tendency for
>problems.

:-) I know. Even when I did make such a set of packages alone I had
that flame war from time to time inside myself.

Moving from the specialized into the general case _is_ hard and hard
to do right. But hey, there are methods for it!

1) You spot the similarities once you already have the specialized
implementations in different packages. That means that it would be the
second time around, this time making it \"right\" (easy to say... ;-)

2) The maintainers of the different packages doesn\'t need to switch,
if they don\'t want to. When you create the general implementation of a
mechanism, you draw heavily upon what they have done, and collect
information on how they would have done it today. But the maintainers
only switch if they want to, at their architectural discretion. Like
Linuxdevelopers decide what lib to depend upon. The creator of the
general package shouldn\'t flame the users to use the package, but make
a good package that really helps the users so that the users picks it
at free will.

And when they switch, they have the
option to create a set of adapters that does the trick for them,
keeping down the number of dependencies between their code and
other\'s. Maintaining a stable public API for a package is the
preferred method of futureaware design on the producer\'s side, but you
cannot always do that. Futureaware design for the \"customer\" (ie other
developers) is to never trust an API maintained by someone else, but
create a level of indirection that adapts to the foreign API. Changes
in the API means changes in the adapters only.

3) When it comes to interfaces there is this trick:

you have the interface Identifiable{ public Object getId();}

you have the class Foo with the method public Object getId(), but that
class doesn\'t say that it in fact implements Identifiable.

So you create the class ClassUtil with the static boolean
hasInterface( Class interface, Object o) method that returns true if
Object o actually has the same public interface as Class
interface. With this method you can check if an object really is an
Identifiable, regardless of what it says:

ClassUtil.hasInterface( Identifiable.class, someObject);

Next you create a generic wrapper that does implement Identifiable,
and uses some utility method to adapt the object to Identifiable, all
using reflection and dynamic method invocation.

Identifiable i = new IdentifiableAdaopter( someObject);

I use this trick with java.util.Collection classes to verify that they
implements my own interface Traversable { public Iterator
iterator();}. Then I have a number of methods that acts upon
Traversable.

So I think the steps would be like

1) Creating this general package from what we have seen is general.
2) Offer patches to the other component groups, for the proof of
concept.
3) Modify according to the thoughts of the component groups
4) In the process: move at a slow pace, always discuss every change
etc. Regard it as a thing for the future, and don\'t hurry.
5) Discuss at a patterns level. Take the Exception handling
discussion: there is a need for patterns how to handle Exceptions in
different contexts. Once you agree on a pattern, a generic
implementation would easily follow, so don\'t make the generic
implementation until you have reached some kind of consensus on what
patterns catalogue the generic packages should support.

/O

--------------------
ola.berg@arkitema.se
0733 - 99 99 17

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


Mime
View raw message