Java Generics usage
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
JQuantLib |
New
|
Medium
|
Unassigned |
Bug Description
Suggested readings:
http://
http://
http://
http://
http://
In jquantlib, we are using Super type token approach to mimic
some of the C++ templates usage quantlib. While i think its a good idea to
use the technique it can introduce a non-type safe programming
model resulting in runtime errors which can be annoying to the endusers.
Lets take an example:
We have binomial vanilla engine follows
public abstract class BinomialVanilla
extends VanillaOptionEn
}
Though class implementation is concrete we made the class abstract so that we can
force a extension and there by we can use super type token approach to determine
the BinomialTree type and create the instance of the tree class internally.
For end users to create JarrowRudd BVE, we expect them to create an extension class
with empty body as shown below
new BinomialVanilla
Using super type token approach we create the instance of JarrowRudd under the covers to drive the
engine. Lets go over the drawbacks of the approach:
a) We are forcing end users to create a concrete implementation which isn't desirable
when engine needs to be created dynamically using class by name approach by runtimes. While you
can argue that its just two parenthesis they need to write, but we shouldn't force
tools to write code.
b) Now lets say user trying out the api the first time and he does
new BinomialVanilla
which is prefectly legal thing to do. Above is just a compile warning. When user tries to
run the code, it will fail miserably with no useful message to a non-advanced programmer. You might
say we can document and assume users are going to read. Come on, how many times does anyone
reads 100% of the doc and do we think we will be able to organize docs in such a way that
users of the api will know the tricks, good luck.
I beleive in "out of box experience". If it gives me an impresssion that its too complicated and doesn't
allow language semantics, most likely i won't use it
Now lets see how we can address above..
a) We can create a concrete extensions for each type, for example
public class JarrowRuddBinom
BinomialVanil
This approach doesn't change any existing api, so advanced users can still continue to use original approach.
Other approach is make BinomialVanilla
b) Don't expect users of the api to specify generic type as it is perfectly legal thing not to. When generic type
is not specified, we should have default type to go with.
Comments are welcome.
Here is another reading i strongly recommend http://
=============
Relationships
=============
child of http://
My comments [more or less] 'inline':
a) We are forcing end users to create a concrete implementation which isn't desirable
when engine needs to be created dynamically using class by name approach by runtimes. While you
can argue that its just two parenthesis they need to write, but we shouldn't force
tools to write code.
-->
The reason for using...
PricingEngine engine = new BinomialVanilla Engine< Jarrod> (...) {};
... instead of ...
Tree tree = new Jarrod(...); Engine( tree, ...);
PricingEngine engine = new BinomialVanilla
... is that the 'responsibility' for creating a Tree is moved from end user code to library code. An end user only needs to tell which algorithm he/she desires and the library code will do all the magic and calculate all the correct parameters a Tree of such algorithm needs to work properly.
IMHO this is a very good design and object model.
On the other hand, the use of templates in C++ and the tricky counterpart Super Type Token in Java may lead to certain problems:
1. It's difficult to create wrappers when you have templates;
2. Super Type Tokens is an 'advanced' technique which could be easily replaced by something trivial like an enumeration, as Srini mentioned.
======
b) Now lets say user trying out the api the first time and he does
new BinomialVanilla Engine( ) {}
which is perfectly legal thing to do. Above is just a compile warning. ....
-->
I've improved error messages and documentation of BinomialVanilla Engine. You just need to hover the mouse over it to obtain the information you need, including an example of usage.
I'd love to see everything being verified at compile time too!
Oh well... this is how Generics works, for good or for bad.
=====
Now lets see how we can address above.. ialVanillaEngin e extends nillaEngine< JarrowRudd> { }
a) We can create a concrete extensions for each type, for example
public class JarrowRuddBinom
BinomialVa
-->
This is not convenient for MonteCarlo module. In MC there are classes with 3 (or maybe even 4?) generic parameters. In MC, the following approaches are acceptable:
1. Use Super Type Tokens
MC mc = new MC<MyNumberGene rator,MySampleS trategy, MyDistribution> (...) {};
2. Class as parameters
MC mc = new MC(MyNumberGene rator.class, MySampleStrateg y.class, MyDistribution. class, ...);
3. Enumerations
MC mc = new MC(enum1. MyNumberGenerat or, enum2.MySampleS trategy, enum3.MyDistrib ution, ...);
Note:
In particular, I'm against the use of enumerations because they restrict how the object model can be extended.
IMHO, we should keep the Super Type Token and add constructors which accept Classes as arguments. This change would satisfy 'advanced' users (typically C++ programmers translating their existing code blindly) and Java programmers used to pass Class as arguments without hurting any previous pre-conception.
====
b) Don't expect users of the api to specify generic type as it is perfectly legal thing not to. When generic type
is not specified, we should have default type to go with.
-->
Yes, you are correct. It would solve the problem you mentioned in (a).
This is not what the original C++ code does, but we are not running C++ a...