Annotations for language features

Reinier Zwitserloot reinier at zwitserloot.com
Sun Aug 16 12:27:23 PDT 2009


On 2009/16/08, at 20:45, Adam Malter wrote:
> They have been universally fragile, difficult to test, difficult to
> code and difficult to debug.

Huh? We're talking about using annotations as language features. Tool  
support isn't relevant to this discussion at all - whether assert was  
done as 'assert (boolean);' or as "@Assert (expression);" (supposing  
that would be legal) is irrelevant to how well or badly eclipse and  
other tools would support it.

> The 'code' must be
> generated realtime in order to preserve 'as your type' error hints

Exactly, which is why lombok does what it does. the AST reflects what  
you typed, immediately.

> All those nice Eclipse/Idea/Netbeans features like dynamic method
> lookup, error highlighting, templating, etc, must run the annotation
> processors/plugins on the entire codebase as you go.

So? Lombok's performance impact on either javac or eclipse is not  
measurable. And yet the lombok transformation core is run by eclipse  
everytime you type a character.

>
> Also, the hurdle for building a Java IDE with these basic features  
> is raised.
>

No, it's lowered.

We're now speaking about two entirely different things, but either  
way, Java IDE authors will be happy with you.

If we're talking about hardcoding the meaning and result of  
annotations into the JLS (Such as @Override), then Java IDEs have it  
marginally easier compared to introducing a keyword, because they  
don't need to make changes to their grammar processor. A *LOT* of coin  
proposals involved syntactic formats which either didn't even fit the  
LL(1) model, or would have been non-trivial to implement for grammar  
parsers. If you for example look at the difference between the eclipse  
parser pre- and post- java1.5 additions, you'd barely recognize the  
parser codebase. Annotations can only be useful for a fraction of  
those issues (quick: Name a java 1.5 language feature that could have  
been done with annotations instead. I can't think of even one!) - but  
where annotations fit, the AST building process does not have to  
change at all - much easier for IDE developers.

If we're talking about a 'roll your own language features' framework,  
e.g. making AST rewriting a plugin architecture like lombok, then IDE  
developers will be *much* happier with you. They add support for this  
admittedly complex thing once, and then most further features are  
delivered either directly in the JDK via sunoracle, or they themselves  
write for this framework. Their IDEs would be compatible with feature  
java language features right off the bat.

> I believe that tools like Project Lombok are useful for illustrating
> new paths the language can take, but I'd be hesitant to integrate any
> library using it into any production project.

You can't tell. No, really - you cannot tell if a library uses lombok  
unless you inspect the source code. Lombok produces class files that  
are indistinguishable from the class files generated if you hadn't  
used lombok and instead wrote it out longhand.

>
> While the class files for the library may be 'JVM' compatible, without
> the exact version of the plugin, the source files might as well be
> Groovy or Scala (aka, opaque to the java developer)

That's just not true. If you see:

private @Getter int x;

you're not really going to argue here that you, or any other java  
programmer is going to be as utterly baffled by what's happening, as  
if you rewrote the whole thing in scala, right? Or, to be a bit more  
fair about it, isn't this true for *ANY* new language feature?  
Therefore your argument boils down to: Java should never change, ever,  
ever, ever, because people will get confused, and it'll be like a new  
language. We could argue that, at length, but then why are you even on  
coindev in the first place? As an argument it has some merit against  
adding a 'roll-your-own' framework to java itself, but I don't think  
that's what we're talking about, and such a framework would most  
definitely be off limits for coin anyway.

lombok-produced class files do not have a dependency on lombok.jar and  
are indistinguishable from class files generated by javac (or eclipse)  
sans lombok but written out.

> - I know this
> hyperbole, we are only talking about getters/setters, but the slippery
> slope argument is no fallacy

Slippery Slope is by definition a fallacy. You just cannot argue 'This  
is going to devolve into insanity' without showing a likely course of  
events for how that would happen. So far you've given me absolutely no  
indication. I'll get things started with a counter-proof: Between the  
various tricks as shown in the Java Puzzlers book, and abusing  
reflection, it seems clear that anybody could easily write utterly  
fragile, impossible to read or maintain code. And yet the java  
community writes code that is by and large readable. Therefore, your  
'giving the programmers tools that could possibly be used to shoot  
oneself in the foot is going to lead to severe problems' is just a  
falsehood. I'll prove it to you, even: In order for a language to be  
turning complete, something we generally want in our programming  
languages, you also give the programmer the ability to shoot  
themselves in the foot. That's the price you pay for allowing code to  
be sufficiently expressive to do anything. So far nobody's managed to  
build a language that is turing complete and yet prevents you from  
writing shoddy code.

So, -yet again-, I implore all to move away from these hyperbolic  
gestures of 'that way lies the madness', and actually show HOW the  
madness could happen, and discuss BOTH sides of the coin here: It'll  
make java code harder to follow mechanically (what -exactly- does this  
do), but it'll make code easier to read (you can express the same  
thing on a higher level, which is easier for a human brain to get the  
gist of). Generics has undoubtedly made understanding how java code  
actually works -MUCH- harder, but on the flipside, a lot of code has  
become much more readable, because you now know exactly what's in all  
those lists and maps. The discussion on whether the cost was worth the  
gain is of course a complex one, but it's nevertheless the one we  
should be having.

Personally, I'm of the conviction that generating getters and setters  
by annotating (with an annotation or a keyword) the field causes  
barely any confusion, and makes code -muuuch- easier to maintain and  
read. It's got a great value for a marginal cost. We should add things  
that offer good value for low costs.

> As an alternative, if what the @Property annotation did was both
> create the getters/setters in the original source, validated them if
> they were already present, and served as a hint to aware IDE's (which
> would then hide the boiler plate), I'd be on board 100%.
>

That's what lombok does (well, not with @Property, but with @Getter  
and @Setter). Unless you mean actually write the physical characters  
into the source file, but that's a rather preposterous maintainance  
nightmare - you'd be burdened with rather a lot of content to read  
just to go: "Oh, this entire 3-page thing was just generated by 7  
lines of code and 5 annotations!" - that's rather a spectacular waste  
of everyone's time. You'd also be incapable of editing things - unless  
you propose that the @Property annotation magically knows the name of  
its field before you edited that name, and removes those setters and  
getters while adding the new one.

A final note on the current state of the APT API: It's a great API. I  
recall Joe saying that the original sun.* API was always intended to  
be a testrun, so that the true API (javax.annotation.*) can be better.  
It paid off well - the javax.annotation.* API is easy to write  
against, and the code you end up with is quite readable. I know of  
many APIs that are part of the core java platform where this does not  
at all hold. Example: Getting type info via reflection including the  
generics. That API (.getGenericReturnType() and friends) is horrid. I  
wish they did the "testrun once - build it properly after that"  
approach for that one.




More information about the coin-dev mailing list