Comments

How many times have you seen (or written) comments like these:

// This needs tests
// Needs testing
// Need to test this

Those comments are easy to write, but you only notice them when you’re looking at that bit of code.

Let’s say you have some time to pay off some tech debt and you want to add some tests. How are you going to find that code again? A project-wide search for “test” is going to turn up words like “fastest” or the @Test annotation, and a whole bunch of things like that.

Similarly, what if you wanted to track the incidence of these of comments in your codebase over time? You’re never going to do it because the cost of writing the regex (or whatever filtering script you want to write) is always going to outweigh any benefit, and it’s

Annotations

The dictionary defines annotations as follows:

an·no·ta·tion /noun/ a note of explanation or comment added to a text or diagram.

It’s right there in the definition. At heart, annotations are nothing more than comments about our code. We already have comments in Java though, so why not just use them? Well, because comments are code, they are highly structured and tools (like your IDE, or CI) can make use of them easily.

If I want to use IntelliJ find all the uses of @Deprecated in my codebase, I just find all the references to that annotation. Similarly, I could easily write an annotation processor to count the uses of that or any other annotation in my codebase, for use in a CI report.

Custom annotations to the rescue

So, how could we replace all those comments about missing tests with an annotation? Fortunately, custom annotations are easy to write in Java. Here’s a simple example:

public @interface NeedsTests {
}

We can probably do better than that though. This annotation is never going to be needed at runtime, and it wouldn’t make sense to put it on anything other than a method or a class, so let’s specify that:

@Retention(RetentionPolicy.SOURCE)
@Target(value = {ElementType.METHOD, ElementType.TYPE})
public @interface NeedsTests {
}

Better. But maybe we want to include some extra information, like an estimation of the effort it would take to write those tests. We can do that too:

@Retention(RetentionPolicy.SOURCE)
@Target(value = {ElementType.METHOD, ElementType.TYPE})
public @interface NeedsTests {
    int estimatedMinutes();
}

You can even specify defaults for optional default values if you want.

Other ideas

@NeedsTests is definitely my most used of these “comment annotations”, but here are some other ideas (I’ll leave their uses up to your imagination):

  • @NeedsRefactor
  • @TechDebt
  • @WTF
  • @ToDo
  • @LocaleSpecific
  • @NeedsLocalising

Really, your imagination is the limit here. If you have any other ideas, I’d love to hear them in the comments section.