Hi Chris, you've made excellent points, which I'll address below:

---
1. The port appears to me to be a direct attempt to take the existing collections codebase and generify its API. It's an approach I initially took but abandoned after a while when I realised that much of the existing codebase was inappropriate for generifying. To clarify this, much of the current collections API is not typesafe, and raises problems when trying to generify it. For example, the ChainedTransformer class has a constructor that accepts a Collection. The javadoc indicates that this should be a collection of Transformer instances, and the resulting ChainedTransformer's transform method takes the input object and transforms it using each Transformer in the chain, returning the result. When generifying the class to ChainedTransformer<I, O>, it's not possible to use the following constructor

  public ChainedTransformer(List<Transformer<I, O>> transformers)

because it's generally not possible to take the output of each of the chained Transformers and pass it into the next Transformer in the chain. After much consideration, it was decided that to maintain compile-time type safety, the behaviour of ChainedTransformer had to fundamentally change. This e-mail is already long enough, so I don't want to elaborate any further. The point I wish to make is that the collections.sf.net project addresses such issues by compromising type safety - it's constructor to ChainedTransformer<I, O> is as follows

  public ChainedTransformer(Transformer[] transformers)

In this instance, the difficulties that generification raises have been skirted by sacrificing type-safety, and it's an approach that is taken throughout the collections.sf.net port of collections. I think this is an important point to consider, as probably the most important point of generics is to provide compile-time type-safety.
---

There are definitely some collections that don't take very well to generics. ChainedTransformer is one of the worst offenders, as it is not clear how it should be changed so as to make it support generics. Other collections that have problems are MultiMap and the TransforedXXX collections. However, there are some good solutions available for those, and we are working on them actively.

Our approach was to shoot for supporting generics in the majority of the classes. This was because we wanted to begin using the collections in 1.5 in our own projects immediately, and there was no existing solution for us. Those classes that did not lend themselves well to generics were either not converted or were only partially converted. This way, the software worked right away and was a clear improvement over the non-generic collections. We agree that it has some short-comings in the partially-/non-converted areas and we look forward to working with everybody to resolve those in the best way possible.

It is our philosophy to not be bogged down by the more obscure cases (such as ChainedTransformer). Those few classes that just don't make sense at all from a generics point of view should perhaps just be labelled as such in the documentation.

---
2. Whilst the public API of the collections.sf.net port has been generified, the internal implementation is largely untouched. It's still the non-generic code that is present in the current commons-collections codebase. From a black-box approach, this isn't especially important provided that the implementation honours the documented API. As I've mentioned earlier, this isn't the approach I've taken in collections15.sf.net, where all of the code has been fully generified, rather than just the API. This isn't a particular criticism of collections.sf.net - Sun's own implementation of ArrayList<E> takes the same pragmatic approach - but it's just a difference I wanted to point out. I must say, however, that in the process of generifying all of the code in collections15.sf.net, a number of subtle improvements to the generified API became apparent that would not have been so had I only generified the public API. That this level of attention hasn't been paid to the implementation code in collections.sf.net, leads me to worry that the generification of the API isn't optimal, though I admit that this may be because my first stab at generifying the interfaces was not the best and so had to be changed a lot as I generified the implementing classes and the problems in the API became more apparent.
---

Yes, we feel that the some of the internal implementations are well-converted, but not all. We look forward to improving the use of generics in those classes and throughout the source. These refactors are important, but will not change the experience for the users of the library.

---
3. Here's my biggest worry. The unit tests in collections.sf.net don't appear to have been modified to reflect the generification of the APIs. The 100% success rate of the unit tests is therefore misleading, as it's more of an indication that the original commons-collections code on which the collections.sf.net port was based doesn't fail any of its unit tests. What's missing in the unit tests is an attempt to exercise the generic modifications made to the APIs. Whilst updating the unit tests in collections15.sf.net, a fair number of minor errors where uncovered. They were typically problems whereby it became apparent when writing the unit tests that the generic arguments of various methods weren't sufficiently flexible. I'm worried that since the unit tests in collections.sf.net don't exercise the generic modification that have been made, the modifications may not have been exercised at all.
---

On this point, I don't entirely agree. The behavior of a class is the same at runtime regardless of whether the user used generics in the source code or not. Any errors in our addition of generics to the collections will manifest themselves at compile-time, not runtime. Now, such issues are important, and we should make sure that each method of each collection is defined consistently from a generics point of view. However, as the vast majority of collections implement the java.util collection interfaces, a lot of the parameterized types are already strictly enforced in the overriding methods at compile-time. This trickles down to the helper/private methods, and makes things pretty tight.

However, I agree that some test code should be written to ensure that generics are properly employed in those places where issues could have slipped between the cracks. Just having that code compile will ensure that the generics are properly employed.

Incidentally, there were classes that underwent fairly severe refactoring in order to support generics externally and internally. Probably the best example is AbstractReferenceMap. For such classes, the test suite was invaluable in ensuring that the proper behavior was retained.

---
4. The javadoc in collections.sf.net doesn't appear to have been updated to reflect the generification of the API.
---

True, the docs have only been updated to indicate those classes that support partial or no type safety under Java 1.5.

Chris, thanks for these points. We agree that there should not be duplicated effort on this project, and we look forward to open collaboration on this. More work is certainly required to bring those straggling non-generic collections in to the fold, but we emphasize an approach that retains the full, working funtionality of the collections during these early releases. That way, developers can use the package, get used to the generic versions of the collections, and provide us with valuable feedback.

John Watkinson

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

Reply via email to