Hacker News new | past | comments | ask | show | jobs | submit login

Since they're compiled into the code, it means you can't change them without recompiling, so they're not actually configuration. But they're not actually code either, so they can't be subclassed or inherited, don't support generics, and have other quirks [1]. Furthermore, they are a sort of explicit notation to make you feel like you're getting 'convention' over 'configuration', but if it were truly convention you wouldn't need them in the first place.

For example, to teach my class how to serialize itself into JSON, I can compile com.fasterxml.jackson annotations into it, but by doing so I've made a particular JSON library a dependency of myproject-datatypes. I'd rather my myproject-controller or some other layer of my application take care of how the data looks over JSON. Luckily Jackson supports an entirely different way [2] of teaching it how to map a class, but not all libraries are so nice.

That is not to say annotations don't have their place. They're good declarative structures, but in my opinion they are used in places where they shouldn't be. This blog post [3] from 2009 accurately describes how I feel about annotations.

[1] http://www.cowtowncoder.com/blog/archives/2009/02/entry_216....

[2] https://github.com/FasterXML/jackson-docs/wiki/JacksonMixInA...

[2] http://naildrivin5.com/blog/2009/03/11/java-annotations-java...




Annotations are data about the code. The fact that you can't change them without recompiling the code is a feature, not a bug.

If you want that kind of flexibility, use external files (e.g. XML) but now the two can get out of sync, which is what is commonly referred to as XML hell.

The rule of thumb is simple: whenever you need to add information about something in your source (class, method, field, package), use an annotation. If you need to add information about something that is not source code (port, host, various sizes, etc...) then use an external file. In particular, if you specify a reference to Java code in your XML, you should use an annotation instead.


> to teach my class how to serialize itself into JSON, I can compile com.fasterxml.jackson annotations into it, but by doing so I've made a particular JSON library a dependency of myproject-datatypes

Right, because at the moment, there is no standard cross-library convention for that. One day, there will be, as there is for serializing to XML:

http://docs.oracle.com/javaee/7/api/javax/xml/bind/annotatio...


What about gson?


It's not a standard, just another implementation.


Thanks for taking time! My views below:

> Since they're compiled into the code, it means you can't change them without recompiling, so they're not actually configuration.

Neither xml was configuration. I cannot remember ever changing xml for deployment. Actually in many ways the whole build jar/war process feels a lot like compiling in Javaland and while I'll happily pick jars or wars apart for troubleshooting deploying the result in production would break multiple guidelines at most places I guess (hope).

> Furthermore, they are a sort of explicit notation to make you feel like you're getting 'convention' over 'configuration', but if it were truly convention you wouldn't need them in the first place.

Partially agree but then again every other framework I have seen demands you do something: put x classes in y folder, subclass another class or implement an interface or something.

Compared to magical directory layout annotations are less well, magic, more explicit.

Compared to subclassing it is more flexible (although I remember enjoying Propel with Symfony 1.)

Compared to marker interfaces? Not sure.

That said once you accept them there is plenty of things you don't have to specify but can override if you want/need to.

Edit: As for your third reference it is out of sync itself:

> The same goes for EJB. I have a class named FooStatelessBean. How about we assume it's a stateless session bean, and it's interface is defined by its public methods? It can then provide FooRemote and FooLocal for me, and I don't need to configure anything or keep three classes in sync

I only use three annotations on such ones: @Named at the class telling the DI framework to pick it up for injection using its name as the name (although I can override it right there and then if I need to.) @Stateless tells it to make a suitable bunch of them and that it is OK to give any of them out to anyone at runtime and @PersistenceContext (at an instance variable) tells me that I want a reference to the ORM layer.

I could easily create a combined annotation for @Named and @Stateless, even naming it @Stateless and just importing my @Stateless instead of the standard (across all Java EE implementations) one.

I guess I could also create a superclass that does all this and subclass it but some day I'll leave the project and another one will have to maintain it.

Could we have picked this out from the name? Yep. Would it be magical? Yep, more so than annotations. Would it tie my hands with regards to naming classes? Yep.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: