On Feb 25, 7:59 pm, Reinier Zwitserloot <[email protected]> wrote:
> Alex, you haven't explained how we can migrate list safely, then.
>
> If lots and lots of legacy code cannot accept new-style lists, then
> trying to integrate with the older code is going to be a very
> frustrating exercise.

In general, legacy code CANNOT use new-style lists. If JDK8 makes
binary-incompatible changes to List, e.g. drops size(), then only 8-
aware clients must get it. If JDK8 makes source-incompatible changes
to List, e.g. adds filter(), then only 8-aware extenders must get it.

There is no middle ground here; if incompatible changes are made in
version n (an enormous decision!), then some legacy code is stuck
forever in the pre-n world. Legacy code is implicitly bound to 7.*
classes on a 7 VM, an 8 VM, a 9 VM, etc.

For generics, there was a middle ground: legacy code was permitted to
use generic types with warnings where type correctness was
compromised. Those warnings were necessary even if the program is
ultimately type-safe. At least for modules, there is no such ambiguity
because it's clear which features are used by legacy code that are not
provided by a new List.

> Which brings us back to my original point:
>
> Modularization is very cool, and we really need it, but without some
> serious wrapping/view/translation tricks, modularization is not going
> to allow us to fix bad core API. Some work on the fringe might be
> possible if sun is okay with losing backwards compatibility in very
> rare circumstances.

Let's think about wrappers. Suppose JDK8 wants to drop a class. To
offer migration to a legacy client, the only possible option is to
leave the class in place but to annotate all its methods with
@CarefulThisMethodIsREALLYDeprecatedAsOf("8") and make the bodies
throw RuntimeException. We could imagine strategies like "javac: give
warnings in version n and errors in n+1" but ultimately the client is
going to have change their code. The provider wants that change to
happen ASAP. The easiest change for the client is to modularize itself
- this doesn't have to mean much more than declaring a dependency on
JDK 7.*. (And javac + a module system can assume this dependency
automatically, as I said.)

But look: if the client can be recoded to not use the dropped class,
then the "skeleton" class was unnecessary in the first place, since
it'll be obvious that a formerly usable class has become unusable. If
the client cannot be recoded to avoided the dropped class, then 7.* is
its dependency forever and the skeleton class adds nothing.

Other changes are harder. Suppose JDK8 changes a class from public to
module-private. Classes in the same module can still use it so the
method bodies need to stay intact. The trick of having a method check
who calls it at runtime (as proposed in 
http://wiki.apidesign.org/wiki/AlternativeBehaviour)
won't work since access control applies at compile-time.

Once the provider has made the choice to break binary compatibility,
the only option seems to be to let multiple versions (old "unbroken"
and new "broken") coexist.

Alex
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "The 
Java Posse" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/javaposse?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to