Java Documentation Best Practices

Java documentation is important to do, but hard to love. In this post we discuss the reasons to document every piece of code you write, and the Javadoc best practices to make it easier, and more effective.

Java Documentation: A Love Story

I am pretty sure that as developers, we are all in love with technical documentation. We love reading docs, writing them, and don’t even start me on talking about maintaining docs: absolutely love it!

Also, I know that every time you create a class or a method you think about documenting it. And I am sure that you enjoy it as much as an occasional tasty burger. But sometimes, just sometimes, you have thoughts about having something lighter and maybe skip the docs just this one time. Unfortunately, this practice gets out of hand pretty quickly.

So in this post I want to talk about this crucial but often overlooked and forgotten part of a developer’s life. Hopefully, you’ll fall in love with documenting, come to a better understanding of why your code works, and ultimately help you, your team, and countless people who use your software.

Tips for Java Documentation

Usually developers never forget the code they wrote two weeks ago. Neither after two months or after even longer periods of time. Even if we take for granted that we’ll never forget any piece of code that we created there’s another much more important reason to document things.

1. Clarify Your Mind Before Coding

I will take my very own example: when I have an idea of developing my brand new exciting feature in SlideshowFX, I just would like to jump two feet into the code and implement it. But I know I am not the only passionate developer working on it. So my typical behavior goes something this:

  1. Write the following class body public class BurgersManager { }
  2. Think: “Well I should have some CRUD ops in that manager”
  3. Write some: public…
  4. Think “What should I return? Well void will be good for now”
  5. public void addBurger(Burger burger) { // TODO implement that later } public …
  6. Think: “Should I return the instance of the eaten burger or void will fit? Well, like #4 rules …”
  7. public void eat(Burger burger, boolean fast) { // TODO …
  8. Tell to myself: “Oh dang, coffee time. Where is my coffee …”
  9. Searching, drinking, talking to colleagues
  10. Then telling to myself: “Let’s get back to work. What was I doing?”

I know, you recognize yourself in this example, don’t you? At the beginning of creative work, our mind is a bit messy so if you start with the code it’ll be messy as well. Thinking documentation before code will help you clarify your mind and lay out clearly what you need to achieve with the code. So the first step could be writing the following code:

 * This class allows to manage burgers by providing CRUD operations using burgers and 
 * acts as a singleton. In order to get the instance of this manager, the method 
 * {@link #getInstance()} can be used. Then CRUD operations can be called like the following:

{@link #addBurger(Burger)} in order to add a burger that will be managed by the * singleton instance ;

* @author Thierry Wasylczenko * @version 0.1 * @since BurgerQueen 1.0 */ public class BurgersManager { }

Well this is a short example which:

  • forces you to think what is the purpose of the class you are creating
  • helps you identify your needs
  • reminds you what you are doing, even after taking your break
  • helps you estimate what is still to be done

2. You’re on a Team

You are probably not working alone, and you may have colleagues you respect and with whom you love drinking coffee and talking about things. Well the point is that, because you love them, an you want to help them participate in the development of your exciting BurgerQueen implementation. And for that, the very best practice is to make sure that when they read your code, they could refer to perfect documentation, even if they ask you questions two weeks after you wrote the code, you could answer them without any hesitation.

That is another reason why documentation matters: it avoids people going back to you multiple times with questions about how your complex algorithm works or why burgers added to the manager are not also added to the statistics of the employees manager. In a team documentation avoids:

  • people being interrupted in they work and then having difficulties to recover from the interruption
  • people looking for the right person who could answer a question and disturbing other teammates to know if they know who could answer
  • people waiting for teammates to be available to answer their questions

So doing documentation helps the team increase its productivity and focus on the development.

3. Take Java Documentation to the Next Level

This point is much more personal. Doing my Java document makes me proud because when I reuse my APIs, I have documentation while I’m coding that helps me ensure that I don’t forget any little details. Even if usually I forget nothing, knowing that I can and the docs are there to back my memory is great.

Seeing my IntelliJ IDEA displaying my doc makes me feel like “Hey, look, I’m like a pro, my stuff is awesome, I even have the documentation“. In some way it’s true, isn’t it? Because when you’re using a lib with a method log(String s, int i) without a description of these wonderfully well-named arguments and if you must be like me, telling to yourself “What on earth could be the possible values for i?

I don’t know about you but I find the new design of the Javadoc pretty sweet. And I think having my documentation neat like that is awesome. But as I said, this is very personal.

JavaDoc Best Practices (With Examples)

In Javadoc you have nine tags which are the following:

  • @author
  • @version
  • @param
  • @return
  • @exception/@throws
  • @see
  • @since
  • @serial/@serialField/@serialData
  • @deprecated

But the purpose of this article is not to explain all of them in detail, but instead, as a documentation writer as well as a developer, I want to share some tips I use when I write my Java document.

1. Use @link and @linkplain for Pointing to Some Code

In my Javadoc I like to refer to classes and methods if there is a dependency or if it is just useful for the documentation. In order to make it easier to navigate through methods and classes, you can use @link. It works like this:

  • {@link BurgersManager} to point to a class
  • {@link BurgersManager burgers manager} to point to a class with a given label
  • {@link #eat(Burger, boolean)} to point to a method inside the same class
  • {@link #eat(Burger, boolean) eat} to point to a method inside the same class with a given label
  • {@link BurgersManagers#eat(Burger, boolean)} to point to a method inside another class
  • {@link BurgersManagers#eat(Burger, boolean) burgers manager eat} to point to a method inside another class with a given label

The difference between @link and @linkplain is that the latter one doesn’t produce a monospaced code font.

2. Use @code for Code Snippets

Often you can find some code inside a Javadoc to illustrate how to use a method, class or to provide some other example. In order to display the code correctly and preventing some markup to be interpreted such as <String> and so on, you can use the @code.

List burgers = new ArrayList<>();
  for(int index = 0; index < 10; index++) {
    burgers.add(new Burger(“Burger #” + index)); 

The @code will generate the <pre> markup for you.

3. Use @value to Insert the Value of a Field in the Documentation

When you have a constant, you may want to display its value in the documentation. So you have two options:

  • Insert the value yourself. But if the value changes, you will have to update your documentation, and as you will not forget to do it, you can choose this option safely
  • Use @value which will insert the value for you, and you won’t need to worry about updating your documentation

Well I will discuss the second option which is for me the best way to take advantage of the Javadoc tool. Indeed using a single attribute is really helpful:

 * The default value for this field is {@value}.
public static final String BURGER_SHOP_NAME = "Thierry's shop";

But you can also refer to another constant, for example:

 * The default value for this field is {@value} when the value 
 * of {@link #OWNER} is {@value #OWNER}.
public static final String BURGER_SHOP_NAME = "Thierry's shop";

 * The default owner of this awesome burger shop.
public static final String OWNER = " Thierry";

4. Indicate when the Features Have Been Available With @since

It is often useful to indicate when a class or a method became available in your code. For this you use the @since tag followed by the version/year since the feature or class has been implemented:

 * This awesome class is for doing awesome things
 * @since burger-core-0.1
 * @version 0.2
public class BurgersManager {

   * Allows to eat burgers
   * @since burger-core-0.2
  public void eat(Burger burger, boolean fast) {
    // TODO

As you can see I use it on both methods and classes and not only with a version number. Indeed nowadays we have applications with multiple modules which can have different life cycle and so, versions. Saying that a class or a method are available since version 0.2 doesn’t have a particular meaning. Version 0.2 of what? This is why I always put a relevant @since for helping my teammates understand when something has been available at the first sight.

Moreover, I can identify an advantage of this tag which is helping you building release notes. Wait, what? No, really, go to your favorite IDE, IntelliJ IDEA for instance, and search for files containing “@since burger-core-0.2” and voila you can identify what has been added. This doesn’t tell you what have been updated of course, only what’s new. But you should agree, such a straightforward trick is useful.

5. Don’t Be Anonymous, Use @author

There is something I really dislike: people not owning their code and not indicating it is them, who have written this awful code for an awful reason. If you write code, own it, or go to being a manager. You have the @author tag you can use to identify you’re the author of a class or method. I think it is a good practice to put it on both classes and methods because the author of a class might not write all methods of it.

Another best practice is to put all authors for a class or method. Imagine you and your teammate have written an awesome method and you’re identified as the only author. And one day, when you are on vacation, someone is reading your wonderful method and doesn’t understand it very well and would like some details. But as you’re listed as the only author they don’t know that the information is easily accessible from your colleague who worked on this code with you. You see where I’m going, don’t you? Always document the code authorship with @author.

6. For Non-Void Methods, Always Use @return

Well this is one really hits home with me. Sometimes I read the code like on the example below and just cringe.

/** Get the address.
 * @return
public String getAddress() { /* … */ }

Why!? Really, why you don’t fill the @return? “It says just 1 line below, get the address”.

NO. NO. PLEASE NO. If you answer like that, it’s because your documentation is, well, how can I say that, subpar! Yes, because instead of having the poor documentation like you just saw above, you can easily have a better version, look:

 * Get the address of this burger shop. The address is of the following format:
 * {@code address line 1
 * address line 2
 * zipcode city}
 * @return the address of this burger shop or {@code null} if not filled.

Much better, right? Here your javadoc is useful. I always try to find a proper way of documenting the code because sometimes readers only read the @return, others the text above and you can easily avoid confusion by typing a couple more words.

6. Clarify What Parameters Mean With @param

What is more frustrating than seeing a method that takes a parameter named something unclear, like i with no documentation? Sometimes you can guess the purpose of that parameter thanks to the method’s name. Then again, sometimes you cannot. So in your documentation you should use @param in order to indicate what this parameter means and, potentially, indicate what the valid values are. In our case, i could be the level of the log and the values will be INFO, DEBUG or TRACE. Another case where this tag is particularly useful is when the value corresponds to an index. In some case indexes start at 0 and in other at 1. @param is the right tag to describe such differences.

JavaDoc Utility Options

It is very good to have documentation in the code, but now you have to generate it. So you can have to use the javadoc tool provided in the JDK to generate it. By executing something like:

javadoc {packages|source-files} [options]

You can specify the packages, space separated, or source files, also space separated, for which you want to generate the documentation.

Here’s a short description of some options javadoc utility accepts:

  • -author for generating the @author tag in the generated documentation
  • -d directory for generating the documentation elsewhere than in the current directory
  • -nodeprecated for avoiding the generation of documentation for code marked as @deprecated
  • -protected to include protected and public class and class members -private to include private class and class members
  • -public to only include public class and class members

Tools such as IDEs are also able to generate your documentation but also preview it to this if it is well formatted.

Dependency management tools like Maven and Gradle also include a phase or task to generate your documentation. And this is great! Because your documentation can always be produced with the release and so it will always be up to date.