@Supported design issues
mark.reinhold at oracle.com
mark.reinhold at oracle.com
Fri Mar 15 21:12:49 UTC 2013
2013/3/4 2:58 -0800, joe.darcy at oracle.com:
> On 02/28/2013 11:31 AM, mark.reinhold at oracle.com wrote:
>> 2013/2/23 5:10 -0800, joe.darcy at oracle.com:
>>> Having Supported take a boolean value both allows the explicit statement
>>> that an item is not supported as well as providing a possible transition
>>> path from Supported(true) to Supported(false) to removed.
>>
>> Okay. In that scenario what's the role of the existing @Deprecated
>> annotation?
>
> @Deprecated generally applies to all clients of an API. I don't think
> people tend to associate potential removal of an API with deprecation
> because we haven't (yet) removed any deprecated Java SE APIs from the
> platform since to date we have placed a higher value on preserving
> binary compatibility.
I'm continually surprised by developers I meet at conferences who
(sometimes angrily) demand that deprecated APIs be removed, so I think
the reality is a mixed bag -- not that it matters a great deal either
way.
What I'm trying to understand is, for a JDK API that's @Supported(true)
in one or more releases, what's the recommended protocol for removing
it? Perhaps something like this?
@Supported(true)
@Supported(true) @Deprecated
@Supported(false)
<gone>
(Time flows downward.)
Or does @Supported(false) happen when @Deprecated is applied?
Or will usage vary?
> The deprecated-in-JDK-7 and JDK-specific apt API was removed in JDK 8,
> but that is the only removal of a deprecated API from the JDK I'm aware
> of offhand.
I suspect that's correct.
> The jdk.Supported annotation is mostly a statement to users outside of
> the JDK itself.
Understood.
>> ...
>>
>> I'm still wondering whether marking a package "@Supported(true)" means
>> that I can use "@Supported(false)" on some of its member types. That
>> would be convenient for cases such as the JMX OSMBeanFactory class that
>> Alan mentioned.
>
> If a package has a mixture of supported and non-supported types, I would
> say it should either *not* have a @jdk.Supported annotation itself, or
> if the types in the package were predominately one value or another,
> then the package annotation should match the prevailing value of the types.
>
> Since types have a more concrete existence then packages, I regard the
> jdk.Supported information on package-info files to have a higher mixture
> of informative versus normative sentiment compared to the annotation on
> types.
If we're going to go to the trouble of defining an annotation for this,
and then sprinkle that annotation throughout our code, shouldn't we give
it as precise a meaning as possible? It'd be a shame for @Supported (or
whatever it turns out to be) to have no more authoritative value than,
say, the @since javadoc tag.
>>> ...
>>
>> What I don't understand is how doing all this with an annotation would
>> be any harder to circumvent than what we have today. Are you proposing
>> to do something stronger than issue a compiler warning when people try
>> to use an unsupported API?
>
> The ct.sym mechanism we have today is compile-time only and the
> mechanism and all its warnings can be circumvented by adding a single
> option to javac; the option is described on stackoverflow, amongst other
> places. Therefore, it is fairly easy for someone to claim "but I didn't
> know" in regards to the status of a JDK-specific API.
Well, sure.
> Since any jdk.Supported annotations applied to types are more localized
> and more specific ("*this* type is or is not supported / stable / etc.")
> it is both easier for JDK developers to made incremental changes to the
> JDK code base and is it also easier for users of those types to see what
> is going on since any inspection of the types can reveal the annotation
> value.
Agreed, but I was trying to understand how the annotation-based system
would be harder to "cirvumvent", at either compile time or run time.
>> ...
>>
>> Even if we think we only need two explicit levels today, a design that
>> admits expansion is preferable to one that forever limits us to just two
>> values. An annotation that takes an enum, to which we can add values
>> over time, would be more future-proof.
>
> Technically, it would be possible to evolve a boolean-valued annotation
> to one that included a non-boolean value as well by adding a new method
> that had a default to the annotation type. For example
>
> // Version 1
> @interfaced Supported {
> boolean value() default true;
> }
>
> // Version 2
> @interface Supported {
> boolean value() default true;
> Stability stability() default STABLE;
> }
Yuck.
> However, if what we eventually want to capture is "stability level"
> rather than supported-ness than having a single stability value from the
> start would of course be preferable.
>
> That said, it terms of the exercise of going over the inventory of
> existing types, I think it can be helpful to at first be constrained to
> making a binary supported / not-supported determination to avoid the
> temptation to overuse a middle-of-the-road value like EVOLVING.
>
> Types that don't fit well into supported / not-supported classification
> can help drive what other distinctions are useful to make.
Agreed.
>>>> - The retention policy of the annotation is RUNTIME. Is that really
>>>> what we want? I'd have expected CLASS.
>>>
>>> CLASS is not very helpful (and certainly not a helpful default). A
>>> CLASS-retention annotation can be reliably used at the compile-time of
>>> other code. For the use case of Supported, I think it is more helpful to
>>> allow runtime querying of the property.
>>
>> What run-time use cases do you have in mind?
>
> Allowing class loaders and other run-time tools to query the annotation
> value and take some action, like log a warning or potentially refuse to
> link.
Okay, that sounds plausible.
> ...
>
> As an aside, going forward I think we should make greater use of the
> "jdk.*" namespace for JDK-specific types. The JDK codebase has outlasted
> Sun Microsystems (R.I.P.) and therefore the natural lifetime of
> "com.sun.*." APIs. The JDK has also outlasted both of Sun Microsystems'
> ticker symbols (SUNW, and JAVA); as I understand their conventions,
> ticker symbols are a preferred component of Solaris package names. The
> "jdk" name will be appropriate as long as the JDK is around.
I have long supported this position -- jdk.* is the place to be for new
non-Platform, non-proprietary APIs.
>> I did just notice that the annotation's source file is in the langtools
>> repo rather than the jdk repo. What's the rationale for that? I think
>> most JDK developers would expect to find it in the jdk repo.
>
> As covered in other responses, while the jdk repo is the natural home,
> langtools was for bootstrapping reasons.
Hmm. Okay.
- Mark
More information about the core-libs-dev
mailing list