A screenshot showing a README in a project folder

Documentation as a Bug-Finding Tool

Every developer should already know about many of the benefits of writing good documentation for the future developers of whatever it is that they’re working on.

The documentation helps these future developers gain a real understanding of how the code works, why it does what it does, and prevents them from introducing new bugs in the future. A good overview of the inner workings of a program could save a developer hours of work attempting to figure out just how all of the pieces fit together. And even if you don’t think that anyone other than you will ever be looking at the code ever again, a good overview could certainly serve as an excellent refresher for you in the future, if you ever have to refer to the code again.

However, there’s one key benefit of writing this developer-focused documentation that I feel is often underplayed. Writing this documentation will help you find little bugs that would have otherwise been missed.

When I refer to “documentation” here, I don’t really mean the little scattered comments throughout the codebase. Those are important, but I desperately hope that enough developers already know about their importance that it isn’t a huge issue. I’m instead referring to more general architecture or code structure documentation. The type of documentation that tells you how all of the different moving parts fit together, and just as importantly, why they fit together the way that they do. This is the type of stuff that can be almost impossible to figure out without good, proper documentation, and this documentation is what can best help you find bugs.

Take, for example, the method from ClassA below:

public int getSomething(String key, int num) {
ClassB obj = hashMap.get(key);

synchronized(obj) {
return obj.getB();

There is one fairly simple bug here that should be realized with or without documentation. What happens if obj is null? NullPointerException. Right.

I actually wrote code with a similar bug earlier this week, which certainly would have been caught with further testing, but I caught during this documentation phase. It saved me a bit of personal embarrassment to have caught this simple bug before it left my machine, so I count this as a point for documentation.

However, there’s one other little and evasive bug that I may not have caught without proper documentation. Let’s take a look at ClassB’s two methods to see if you can catch it:

public void doA(int num) {
for(int i = 0; i < array.length - 1; i++) {
array[i] = array[i+1];

array[array.length - 1] = num;

public float getB() {
float total = 0;
for(int num : array) {
total += num;

return total / array.length;

Both of these methods are pretty simple. doA(…) treats “array” as a buffer of sorts, and appends the number passed to the buffer. getB() returns the average of the values in the buffer.

These methods should only ever really be needed when called from ClassA as shown above. However, I didn’t put in any guarantees that they wouldn’t be called from elsewhere, and there’s no concurrency protection on the methods themselves. If you recall, above, the group in ClassA was surrounded with a synchronized block (because they do need to be called in succession with nothing in-between), but the methods themselves have no protection. This is an issue that I likely only caught because of the documentation I was writing:

ClassA contains the only object that should be accessed by multiple threads, and is thread-safe.

As soon as I typed that, I realized my error. “Yes, ClassA is the only one that should be accessed by multiple threads,” I thought, “but that doesn’t mean that it will be the only one accessed by multiple threads. Something has to be done.”

And yes, with the current code that I had written, there would have been no issue. Everything would have been perfectly thread-safe. But what happens in the future? What happens when some other programmer comes along a few months from now, and goes, “Oh boy! ClassB is just perfect for this application!” and uses it, assuming that it must be thread-safe since it’s used by ClassA, which, due to its purpose, must be thread-safe.

And this is just for a fairly simple program! With larger programs, finding small bugs like these before they become an issue becomes even more difficult, and you need to use every tool in your arsenal to prevent these bugs from becoming an issue. Combining this type of documentation with your other means of defense, such as code reviews, will not only make your team love you more, but will help you churn out the high-quality code you dream of.

Eric Jeney is a Java aficionado with a number of projects under his belt. He enjoys programming for the web, and writing about his experiences. He currently studies Computer Science at the University of Maryland.

View all posts by Eric →