Posted by tball
on October 19, 2004 at 11:48 AM PDT
Like custom classloaders, reflection, and bytecode instrumentation, annotations definitely have a place in a Java developer's toolkit. But will annotations be the cure for all programming problems, any more than those other technologies were?
I think all Java developers have at one time or another fallen in love with a new technology and wanted to use it to solve all problems; after all, when you have a "golden hammer ", every problem starts looking like a nail. Remember when Java Reflection was all the rage when it was first introduced? All of Java's perceived ills could be solved with it, provided one ignored how slow and unreadable the solution using it was. Now the "first love glow" has subsided, and reflection is now an important but specialized technology in our toolkits.
With the release of Tiger, annotations are rightly getting developers excited, but its companion tool, apt , is starting to look a little too golden in my view. Last week, it was suggested that apt should replace javac , and while I applaud that sort of "out of the box" thinking, others are taking a cool thought experiment too literally. Users have already complained on the NetBeans forums about how its upcoming release doesn't support this "feature", even though the apt Mirror API doesn't support code types that a compiler needs.
I think what bothers me about wild apt scenerios is that folks are forgetting (or ignoring) the problem annotations are trying to address: that much of the specification for a class is done outside of its source code in other files, or is done in repetitive boilerplate code that has little to do with the class's problem domain. Information about a class is called metadata, and annotations allow developers to define metadata without external files (other than new annotation type declarations), special naming patterns or other error-prone hacks.
Java developers have been creating ad-hoc solutions to this problem for years. If you look at the Swing sources, for example, you'll find undocumented "@beaninfo" Javadoc tags, which a custom doclet in its build uses to create its BeanInfo classes (XDoclet is an excellent tool that takes the grunt work out of such metadata file-generation doclets). Another tool that adds pre and post-condition checking via custom doclet tags is JContract . The problem with these approaches is that, like all comments, metadata stored in comments can drift away from the source if not carefully tracked by its developers. It's also fragile, in that this metadata isn't checked for typos; for example, try misspelling "@deprecated" in a doc-comment and notice how the compiler just ignores it as comment text, instead of either recognizing it or reporting it as an error.
The Java 1.5 annotation support doesn't fix all metadata problems, but it helps in several ways. First, annotations are true Java types whose definition and usage are verified by the compiler. This makes it much harder to break metadata with a typo, but more importantly it means that if you enhance the definition of an annotation type and forget to update a class that uses it, the compiler will catch that error. I'm very partial to letting the compiler do as much project validation as possible (followed by my unit test suite). It also allows metadata to be discoverable in a standard way in classfiles and at runtime, so that tools like deployment tools or introspectors don't have to use external files and classes.
What makes apt and annotations so exciting to me is that anyone can write an annotation processor as easily as an XDoclet module, writing metadata using a verifiable Java language facility instead of comment text. So instead of trying to see how apt can replace existing tools, look at all the metadata your project has and see how it can be better handled using annotations. If your classes take more than one file to define (such as a factory or "info" class), has boilerplate code in it or doc-comment tags that aren't documentation-specific, consider defining it using annotations. If you need a compiler, stick with javac or jikes .