On Tue, May 31, 2011 at 10:51 PM, Shay Hassidim <[email protected]> wrote:
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)
Quite interesting. This is exists presently in the experimental
generics branch, except the type is <T extends Entry>.
I take this to mean you did not address the corner case that worried
many on this list? Does it simply prove to not be an issue in your
experience?
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.
Entry, of course, is just a marker interface. When you say "POJO",
though you mean Java objects without any requirements upon them?
(e.g. no requirement of a public, no-arg constructor, no need for
public fields, etc.)
The inclusion of asynchronous calls using Futures is also quite
noteworthy, as is your treatment of "snapshot". I was about to start
poking the mailing list about snapshot myself, albeit with a different
proposal than yours.
I am now wondering: is the Gigaspaces code available? Under what
license? And is anyone there interested in contributing?
Shay Hassidim
Deputy CTO
By the way, welcome! If nothing else, your feedback in discussions
will prove valuable, I'm sure.
james
-----Original Message-----
From: James Grahn [mailto:[email protected]]
Sent: Tuesday, May 31, 2011 7:05 PM
To: [email protected]
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