It seems there are two schools of thought when it codes to documenting code. In one corner you’ve got those who feel that the “code should be expressive“; those that feel the “unit tests should document the code“; and there are those who argue that developers are lazy and the documentation gets out of date. These people will argue that there is no point documenting code. And in the other corner there’s me… well, me and the rest of my team, who have all seen sense after I’ve pointed out the error of their ways. 🙂
The rule for Javadoc in our team is “do it properly, or not at all“. I don’t mandate it because if you do you will just end up with rubbish. I do strongly encourage it though. The key word, however, is properly. I’m not just talking about ending the first sentence with a full stop, and making sure you have all the correct
throws tags; I mean well written, well thought out documentation.
I’ll handle the lazy developers argument first. The same argument can be made for not unit testing, and yet I doubt there are many people who would take the stance that not unit testing is OK. It’s part of development. Writing good Javadoc should also be a part of development.
“But it’ll get out of date!“, I hear you cry. So not only has a developer done a half arsed job when updating some code by not updating the documentation, everyone who peer reviewed it missed that too. Please, feel free to hide behind that excuse. You may also want to stop doing reviews because you’re not doing them correctly. Also, what else are you missing?
The unit tests should document the code. Let’s consider a hypothetical situation. I’ve got your object and I’m calling a getter. I want to know if you’ll return
null or not, because I may have some extra processing if to do if I do get a
null value. You expect me to stop, mid flow, go find the unit tests, locate the relevant tests and work out if
null is something that might come back? Really? If there are no tests dealing with
null return values can I safely assume that
null is never returned, or did you just forget to include that? I’ve never bought that argument.
As to the code being descriptive, well yes, it should. But it’s not always evident what’s going on. I can leap into our hypothetical
get method and have a poke about to see what’s happening, but what if we’re getting the value from a delegate? What if that talks to a cache and a DAO? How far do I need to delve into your code to work out what’s going on?
And then we come on to the best argument of all: “You only need to document API’s“. It’s all API.
But what is good documentation? To help with that we’ll expand our scenario. Our getter has the following interface:
public String getName(int id);
What would most people put?
/** * Gets the name for the given id. * * @param id the id * * @returns the name */ public String getName(int id);
It’s valid Javadoc, I’ll give you that, but it’s this kind of rubbish that has given the anti-documentation lot such great ammo. It’s told me nothing that the code hasn’t already told me. Worse still, it’s told me nothing I couldn’t have worked out from the autocomplete. I’d agree with you that having no Javadoc is better than that. This is why I say do it properly, or not at all.
The documentation needs to tell me things I can’t work out from the interface. The method takes an ID, you may want to be more explicit what the ID is. Are there lower or upper bounds for the ID? You return a
String, are there any assumptions I can make about this
String? Could the method return
/** * Returns the name of the user identified by the provided * user ID, or <code>null</code> if no user with the * specified ID exists. The user ID must be valid, that is * greater than 1. * * @param id a valid user ID * * @returns the name associated with the given ID, or * <code>null</code> if no user exists * * @throws IllegalArgumentException if the user ID is less * than 1 */ public String getName(int id);
This Javadoc does three things.
- It means I can easily get all the information I may need about the method from within the autocomplete dialog in my IDE, so I don’t need to leave my code.
- It defines a contract for the method so anyone implementing the code (or overriding it in the case of already implemented code) knows the basic assumptions that existing users already have.
- It provides me with a number of unit tests (or BDD scenarios) that I already know I have to write. While I may not be able to enforce the contract within the framework of the code (especially with interfaces), I can ensure the basic contract is followed by providing tests that check
idis greater than 1 and that some non-existent ID returns
Writing good documentation forces you to think about your code. If you can’t describe what the method is doing succinctly then that in itself is a code smell. It forces you to consider the edge cases and to think about how people are going to use your code. When updating a method it forces you to consider your actions. If you’re changing our
get method so that it will always return a default value rather than
null will that affect other peoples logic and flow? What about the other way round when you’ve got a method that states it doesn’t return
null – change that and you’re likely going to introduce NPEs in other code. Yes, the unit tests should pick that up, but lets work it out up front, before you’ve gone hacking about with the code.
Those of you familiar with BDD may spot that what you’re doing here is just performing deliberate self discovery with yourself. The conversation is between you, and you as a potential future developer. If, during that conversation, you can’t find anything to say that the interface doesn’t already tell you, then by all means leave out the Javadoc. To my mind that’s pretty much just the getters and setters on Javabeans where you know it’ll take and return anything. Everything else can and should benefit from good documentation.