Refactorability proposal...

Bryan Atsatt bryan.atsatt at oracle.com
Tue Jun 10 18:27:28 PDT 2008


(FYI: I've discussed this with Stanley but wanted to ensure it was 
visible to everyone.)

Proposal

1. Eliminate runtime use of import-by-module in the JAM system:

    a. Support the (very convenient) import-by-module at the source level.
    b. jam tool transforms import-by-module to a list of 
import-by-package statements.

2. Add APIs to fully support import-by-package in the JAM system:

   a. Support Version annotation in package-info.java (or in 
module-info.java). If a
       package does not declare a version, it "inherits" that of the 
enclosing module.
   b. Add ImportPackage annotation with version constraints.

3. Add APIs to fully support import-by-package in the abstract framework:
 
    a. Add methods to Query to produce import-by-package nodes.
    b. Replace Query.getIndexableNames() with fully generic variants (I 
proposed
        a solution here previously which I will re-post).

Rationale

Module refactoring is inevitable, particularly during the transition 
from the current, effectively flat class space to a fine-grained space 
provided by module systems. We have significant experience with this 
issue at Oracle (with the transition to our own module system), and OSGi 
best-practices for conversion include starting with everything in one 
bundle and then separating out pieces as experience is gained.

A very common pattern, in our experience, is for developers to start 
with many extra jars in their initial module (a mini version of 
class-path hell). As that module is put into wider use, someone 
discovers that package X is also contained in their module, and that 
duplication either leads to runtime conflicts (very bad), or just plain 
footprint bloat. The obvious answer is to put package X in a separate 
module, and have everyone share it via imports.

But... not so fast. If there are consumers of that module who import it 
by module name alone, then pulling X out of it will cause those 
importers to break. And if it is possible for your module to have been 
imported by *anyone* by name alone, then you are stuck: either you break 
them or you live with the incorrect granularity (which just isn't an 
option in the conflict scenarios). Not a happy choice.

Originally, I had proposed to do away with import-by-module altogether, 
both to avoid this problem and to eliminate the conceptual disconnect. 
Your code does not today contain import statements that name *jars*, it 
names packages and/or specific classes in those packages. Why invent a 
new system that takes such a large step backwards?

The answer is simply convenience. Imagine a module that contains 100 
packages and it is obvious that writing a single import statement is far 
easier than discovering and explicitly writing all the package imports. 
Yes, IDEs will likely mostly eliminate this issue, but it still makes 
sense to be able to do this by hand.

This proposal is an attempt to maintain the convenience while adding the 
crucial ability to safely refactor: step 1b is the central idea.

// Bryan



More information about the jsr277-eg-observer mailing list