Thursday, November 3, 2011

Comments considered harmful

At school, I was taught to comment my programs well. Today, I wonder why I should.

Every comment relating to the code itself is redundant. Redundancy creates inconsistencies, and inconsistencies are a serious threat to code quality. So I prefer not to comment.

"Hey, come on! How do you expect anybody to understand your program if you don't comment it?" I hear being shouted at me. I will ask the opposite question: Why should I write such a lousy program that it needs comments to be understood?

I worked in a group where the coding guidelines said: Comment every class, comment every method. I refused. I mean, as an example, look at this getter, generated by the Refactor -> Encapsulate Fields... operation of NetBeans:

    private String name;
     * @return the name
    public String getName() {
        return name;

What does that comment add that I did not already learn from the method name? So rather than commenting a method, I prefer to use the comment,  kind of, as the method name. That guarantees consistency and also propagates the "commented" intent to every place the method name is referred to. Far superior to a localized comment!

Martin Fowler once said: "Any fool can write code that a computer can understand. Good programmers write code that humans can understand." I strive to be one of them.


Negröj Nossdravgis said...

I think there are two types of comment. One describes interfaces for external consumption (i.e. APIs). These should in most cases be self documenting. It's a different story if you are selling the API in binary form... Of course, you could document the API in a parallel Word document, but that's documentation one more step removed from the code, increasing the risk of inconsistencies.

The other describes "rough patches" in the code. By rough patches I mean code that does something complicated. For instance bit twiddling for ASN.1. You could of course put a reference to the standards document in a comment at the top of the source file, and be done with it. But I think you owe it to the maintainer of the code, to describe what the code is doing. I often find myself drawing cute ASCII pictures on how the bytes and bits are laid out in memory. Also, if you're doing some super duper optimization that isn't obvious at the first glance, I think it's a good idea to put a comment that outlines the optimization method.

It's a tricky balancing act...

Eivind Nordby said...

Yes, Negröj, I also find exceptions. But I like to think of them as just exceptions. I have been able to get rid of a lot of comments and make code simpler, clearer and easier to read following the main rule.

Most of the time, I think that tricky algorithms like ASN.1 do not belong to the exceptions, though. They are just a bit more challenging. I find the solution to be abstraction and implementation hiding. There exists an overall logic, (e.g. for each value, parse the value). Write that (the whats) at a high level of abstraction, and hide the implementation details (the hows). Repeat recursively. Blend in an ounce of polymorphism. At the lowest level, there may be some bit fiddling, but that will be in a small, isolated and easy to understand method with a meaningful name.

It might be an interesting challenge to write an expressive, readable ASN.1 implementation without comments. I am sure they already exist.

As for optimizations, that is a question of its own. If you have to to down that dangerous route (mind the three rules of optimization), they will be small, isolated islands requiring high attention. Optimization in itself introduces redundancies and complexities. Don't be surprised if you have to break some more guidelines as well along the road.