Uri and Arjen in their blog entries (listed below) already touched the subject of overuse of annotations.
Arjen posed the interesting statement recently that there’s a different between a primary key and the identity of an object. This might sound kind of obvious, but when using annotations to configure each one of them, it all of a sudden becomes a bit more vague.
When for example tagging an object’s field as the primary key using the JSR-220 @Id annotation, I tend to think that’s not so bad at all. When however one starts to customize the column in which the primary key is stored using the @Column annotation or specifying how the primary key should be generated using the @SequenceGenerator annotation I’m getting a bit uneasy and it’s not only about the readability of the code (as Uri showed to be getting worse and worse each time you put a new technology and its annotations to use in [1]).
A question of definition: Arjen tells us about an interesting discussion of whether or not an annotated POJO could still be called a POJO (see [2]). Keeping this in mind, we can start to think about about why we wanted to use POJOs in the first place. To keep our classes decoupled from the environment first of all. To escape the so-called technology cycle as my colleague Rod has presented on (see [3]). Our code should be able to survive environmental and infrastructural changes resulting from the different specifications published each year by various vendors and organizations. To insulate our core code from the way the core code will be used:
- as a web service,
- as a remote service,
- as part of a old-school web interface,
- as part of an AJAX web interface or
- as part of whatever we come up with in the coming years
Arjen and myself also discuss this shortly (see [4] and [5]).
I guess what it comes down to is that annotations internal to our systems–required to have our internal components and classes function–are okay. An example of such a usecase could be the checking of whether or not a required dependency has been injected (see [6]). If you’re in the position where you have to solve a problem dealing with rapidly changing infrastructural elements (see the examples above), I think it’s best to think twice before starting to use annotations.
Then for a concrete example, which shows us that it’s difficult to come up with a general rule. When I teach people on how to use Spring, we also touch base on the @Transactional annotation Spring provides. The @Transactional annotation is used to set transaction boundaries on a service class. It allows you to fully customize transaction semantics such as propagation behavior, isolation levels and transaction timeout values. I actually like this annotation although it does deal with infrastructural issues. Transaction management however is something that’s been there for quite some time already and I don’t think the basics of TX-management are going to change any time soon. Defining the annotation on your service class (and not on the interface) hides it from the user (be it a web service or remote client or Spring Web MVC Controller, JSF Managed Bean, et cetera) and the chance that you’ll ever be using the service class in a non-transactional context is pretty unlikely. In other words, using an annotation to define transaction semantics is quite attractive and not so bad at all. I still don’t use it that much though–don’t ask me why
.
So when do you use annotations?
[1] Uri Boness in Dude, where’s my class?
[2] Arjen Poutsma in Annotations/Attributes: How do they help us?
[3] Rod Johnson in Ecsaping the Technology Cycle
[4] Arjen Poutsma in Annotations vs. Interoperability
[5] myself in Re: Annotations vs. Interoperability
[6] Uri Boness in Verifying configuration in Spring
