river-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Shay Hassidim <s...@gigaspaces.com>
Subject RE: correctness, generics, and spaces
Date Wed, 01 Jun 2011 02:51:41 GMT
James,
In case this helps - After similar debates over the years we at GigaSpaces end up with:
<T> T read(T template)  
<T> T take(T template)  
write(T entry) 

See more here:
http://www.gigaspaces.com/docs/JavaDoc8.0/org/openspaces/core/GigaSpace.html

Please note we support POJO as well with our implementation as space classes and not just
Classes implementing the Entry interface.
This works very well for us.

Shay Hassidim
Deputy CTO

-----Original Message-----
From: James Grahn [mailto:grahnian@gmail.com] 
Sent: Tuesday, May 31, 2011 7:05 PM
To: dev@river.apache.org
Subject: correctness, generics, and spaces

Hello all,
I've been doing some pondering on the question of generics in spaces again.

==Background==

To refresh those who've forgotten prior discussion, the proposal was to replace methods like
this:
Entry read(Entry)

With this:
<T extends Entry> T read(T)

This change was desired because:
1) it reduces boilerplate code (mandatory casting of objects returned from space)
2) it is a more precise statement of the contract by which these methods operate: i.e. the
return type _should be_ the same as the type of the template.

Some opposed this change because they felt any use of generics would be seen an implicit guarantee
that there are no corner cases with
generics.   Meanwhile, it was hoped, a lack of generics in the
interface would be seen as an implicit warning that no guarantees were
made about interactions with generics.   Regardless of the API, the
current specification does contain corner cases wherein the behavior is potentially surprising.

Specifically, this corner case was brought up: If an Entry implementation determines the type
of one of its members through a type variable, the returned generic type from a read/take
operation would not be guaranteed to be correct if that variable were wildcarded using "null"
in a javaspace template search.

Given:
class Box<A extends Serializable> implements Entry{
  public A member;
}

With the generic implementation of spaces:
Box<Integer> value = read(new Box<Integer>(5)); //correct Box<Integer> value2
= read(new Box<Integer>(null)); //potentially incorrect, inconsistent failures.
Box<Object> value3 = read(new Box<Object>(null)); //correct, but unhelpful.

With the non-generic implementation of spaces:
Box<Integer> value = (Box<Integer>) read(new Box<Integer>(5)); //correct
Box<Integer> value2 = (Box<Integer>) read(new Box<Integer>(null)); //potentially
incorrect, inconsistent failures.
Box<?> value3 = (Box<?>) read(new Box<Integer>(null)); //correct, but unhelpful.

Note that regardless of whether the implementation includes generic methods, both cases require
careful thought in the usage of generics to avoid errors. Because of this, a recommendation
was made that Entry objects should probably not have a parameterized types in general.

== Proposal ==

What I finally realized: we can actually require Entries to not contain any unassigned type
parameters.

Because it is a bad practice regardless, why not do that?

Costs:
1) People who are familiar with generics and would always properly handle corner cases will
not be able to do exactly as they please; they would need to provide a fully specified wrapper
class for what would otherwise be their Entry class.
2) An additional runtime check of an Entry's class would slow the execution time of Javaspace
methods (slightly).

Benefits:
1) If this clears the opposition for using generics in the Javaspace interface, see the above
mentioned benefits.
2) Prevents violation of the principle of least surprise in using generics with space (regardless
of implementation).

== Implementation Detail ==

At the interface level, we would need to add a line to the documentation of Entry, stating
that any class implementing Entry may not include type parameters. Entry implementations already
have several requirements which can't be enforced at compile time, so adding another is not
the worst thing in the world.

At the implementation level, we'd add enforcement in outrigger's EntryRep.ensureValidClass,
checking to confirm that the Entry that Outrigger is given has no type parameters via reflection.

Shouldn't take long to edit the existing generics branch to do this.

== Questions ==

So here are my questions:
1) Is there a problem transforming this from a bad practice to a forbidden practice?
2) Does this address concerns with the generics? Are there any corner cases this will not
cover?
3) Any other concerns? Anything I'm not seeing?

jamesG



Mime
View raw message