If you do enterprise systems, you probably know annotations all too well. For me they are one of the things that are wrong with enterprise.

If you’ve ever done enterprise systems there is very high probability you were using Spring framework. Well, at least you know (about) it. Spring is the standard in enterprise world and as a standard it introduces other standard.

In Spring, annotations are all the way. Make endpoint, inject objects, set up configuration. Also don’t forget about annotation-driven parsing and database storage.

Just take a look at some simplified examples from the most exemplary project - Spring’s minimal pet shop:

Owner model:

@Entity
@Table(name = "owners")
public class Owner extends Person {
    @Column(name = "address")
    @NotEmpty
    private String address;

    @Column(name = "city")
    @NotEmpty
    private String city;

    @Column(name = "telephone")
    @NotEmpty
    @Digits(fraction = 0, integer = 10)
    private String telephone;

CacheConfig:

@org.springframework.context.annotation.Configuration
@EnableCaching
@Profile("production")
class CacheConfig {

    @Bean
    public JCacheManagerCustomizer cacheManagerCustomizer() {
        return cm -> {
            Configuration<Object, Object> cacheConfiguration = createCacheConfiguration();
            cm.createCache("vets", cacheConfiguration);
        };
}

Sometimes it’s really cool. Just add annotation and PUFF - your objects are persistent. Another annotation and BAM - you can convert them to JSON.

MAGIC

But it always comes at a price. Magic is cool because it does magical things, but at the same time it’s mysterious - you don’t know how it works and you can manage it only partially.

First problem: what to do if something doesn’t work? Good luck. Especially if your project is big and magic is equally big - i.e. Spring. Sure, after some time you get to know Spring better and better, but it is constantly changing and there are many annotations in the world from other projects. Annotations is magic you don’t control. Sometimes you don’t need that control but when you do, you might be in trouble.

Second thing: control of the app flow. I find entering Spring project to be more troubling because of annotations. They do dependency injection, aspects and so on. Your class might look as unused but thanks to Spring’s sorcery it actually might be used. Following flow control is more complicated without one place composing classes. Also @Autowired may seem innocent but it makes adding dependent objects so easy, it is often abused.

My final issue with annotations is lack of compile-time safety. You don’t have method references, just strings. Fields references? No, still only strings. I think we can all agree that compile-time safety is pretty cool. Unfortunately, annotations sometimes take away that safety from us.

Am I against annotations? Not really, I use them. But I try not to use them if I can and if doesn’t complicate things too much.

There is always a tradeoff. You trade easier and faster development for less understanding. And that’s cool, sometimes you really don’t need that deep understanding. Another time you might trade easy and fast configuration for worse project navigation and steeper learning curve. That might be also cool if your modules are very simple. The most important thing is to be aware of the tradeoffs and accept them consciously.

Further reading:

Nice and definitely more comprehensive article about the subject by Adam Warski from SoftwareMill: https://blog.softwaremill.com/the-case-against-annotations-4b2fb170ed67

Interesting point of view from Yegor Bugayenko: https://www.yegor256.com/2016/04/12/java-annotations-are-evil.html