Don't create multiple annotations with the same simple name

Nobody reads imports. Good IDEs do their best to pretend imports don't even exist - they'll hide 'em from you, and manage them for you. They'll even add imports on demand when you're writing new code.

Suppose you create your own, say @Inject or @RequestScoped annotation. In the code, it's practically impossible to differentiate between this and a Guice-supplied annotation:
package com.publicobject.pizza;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Injector;
import com.google.inject.Provider;
import com.publicobject.pizza.annotation.RequestScoped;
import com.publicobject.pizza.annotation.Inject;
import com.publicobject.pizza.geography.GeographyService;
import com.publicobject.pizza.hr.EmployeeRoster;

@RequestScoped
public class PizzaStore {
@Inject PizzaStore(GeographyService geography,
EmployeeRoster workers) { ... }
}

Your head will explode debugging problems if the wrong annotation is applied. Guice can detect some problems (blowing up on a mismatched scope annotation) but it's still risky business.

2 comments:

tzwoenn said...

Before writing tedious long annotation names like @PostConstructInterceptorInject usage of inner classes may another solution:

public class PostConstructInterceptor {
public static @interface Inject {}
}

So you can decide to import the annotation directly or its outer class like

public class PizzaStore {
@PostConstructInterceptor.Inject
public PizzaStore(...) {}
}

Cowan said...

This is one of the really irritating things about JPA and Hibernate Annotations -- e.g. the annotations javax.persistence.Entity and org.hibernate.annotations.Entity (which provides 'additional information' on top of what's in j.p.Entity). This kind of thing (there are a few examples) leads to confusion and a lot of forehead-slapping realizations after long debugging.