DEV Community

Cover image for I love to document my code. Am I doing it wrong?
José Clovis Ramírez de la Rosa
José Clovis Ramírez de la Rosa

Posted on

I love to document my code. Am I doing it wrong?

I've been saved countless of times by people who document their code, and also doomed by people who doesn't. At some point I just started to love comments, even the most redundant ones. I strongly believe that a comment is never wrong, unless outdated or misleading.

Sadly not much people seems to like this stance. Instead of documenting our functions, we rely on the naming convention and writing expressive code to figure out the what and the why of any code. Sometimes we even have aesthetic troubles with it, as if the comments were distracting us from the code itself.

I like to write expressive code, but I don't see it as a replacement of proper documentation.

Am I doing it wrong?

Latest comments (34)

Collapse
 
mohamedboualleg profile image
Mohamed Bouallegue

Relying on comments will make it easier for developers to write bad code since they can always explain in comments how it works. With practices like this, developers will not even notice that their code is badly designed.
Avoiding comments will push the developer to rethink and improve his code rather than explaining why the code is complicated.

Collapse
 
maccappo profile image
maccappo

Amen to that. This thing that comments are supreme evil has gone too much beyond.

Collapse
 
dploeger profile image
Dennis Ploeger

I'm going a different way with my code in the last months: instead of commenting the code at the specific line, I'll wrap it in a debug-log call. This is a two birds with one stone thing for me.

Collapse
 
pedromagalhaes profile image
Pedro Magalhães

I think comments are important to explain business rules. These are not self explanatory. Eg: Why something needs to increment 10 instead of 2, why something needs to go left and not to the right, etc.

Collapse
 
scottishross profile image
Ross Henderson

I'm of the view that in large bodies of code, a little comment giving a brief explanation of what the code does can be very helpful. If my colleague writes a massive package that does something, I don't want to have to spend hours breaking it down so I can understand it. You can nearly always half that time by adding a little comment like this:

-- Working Day 01: 1st Email/Message
begin PKG_LOCK_CHASE.FIRE; end;
/

-- Working Day 02: 1st Email/Message + 1
update TBL_LOCK_CHASE set CREATED_ON = CREATED_ON - 1;
delete TBL_LOCK_SFTP where DEVICE_IMEI in (select DEVICE_IMEI from TBL_LOCK_SFTP where rownum <= 5);
begin PKG_LOCK_CHASE.FIRE; end;
/

I know exactly what those blocks are doing without having to go into each package and work it out.

Collapse
 
nateous profile image
Nate

They call them programming languages for a reason. You learn how to read and write in them. I'm in favor of less comments, more readable code.

Over time the code will change, and to my knowledge there aren't many tools that can ensure your comments match your code.

And if the code you're writing or reading needs to be commented so heavily, I'd question if it couldn't be rewritten.

Can you share with us an example method with comments?

Collapse
 
martinhaeusler profile image
Martin Häusler • Edited

Commenting code isn't "wrong" per se but (the following applies to per-line comments; API doc is a different matter entirely):

  • ... you may be better off spending your time in finding good variable and function names, and keeping your control flow and APIs clean. You will get a much better return on your time investment.

  • ... they go out of sync with the code extremely fast. Especially when multiple people work on the same code base. Comments rarely ever get updated.

  • ... they add a lot of visual noise, in particular if they just repeat in "natural language" what the code is doing and should be expressing on its own anyways. It's just like with tests: having a super-huge test suite won't add any value if the contents are useless. Having each line commented won't help if the comments don't add any info.

When I'm writing a particularly challenging piece of code, I find myself writing more line-by-line comments than usual. I try to put my reasoning in there for why I did things the way they are, such that I (or a coworker) can pick up this piece of code more easily in the future in case a modification needs to be made to it.

As stated earlier, API docs are a different matter entirely. I'm convinced that every public API member (method, class, constant...) should be documented rigorously and without exceptions. In practice, this corner is often cut due to time constraints - which makes proper naming and a clean API all the more important, because often times that is all you have to go by.

Collapse
 
michaelgv profile image
Mike

I've always done development like so, take this inherited code:

import { UserAction, ProfileValidator } from '@internal-package/ui-workflow/tools/UserAccount';

class IsAdministrator extends UserAction {
    /** @rt.inject "UserProfile" **/
    private _validator: ProfileValidator = null;
    public validate(): boolean {
        return this.getValidator().getPermissionLevel(7777))
    }
}

export default IsAdministrator;

This is pretty self explanatory, but then take this example:

import { Action, FormElement } from '@internal-package/ui-workflow/tools/Actionables/Elements';

export default class UxEnhancementAction extends Action {
    private _v: FormElement = new FormElement( this );
    public set( n: Action.Node ): void {
        this._set( n.build() ).write( this._v.__setter.write, { props: true, val: !this._v.__getter._wv } );
    }
}

Obviously, the second code block is confusing. If we break it down by documenting, it looks like this:

/**
 * This is legacy code, it should be removed in Version 0.3.1
 */
import { Action, FormElement } from '@internal-package/ui-workflow/tools/Actionables/Elements';

/**
 * This class was used to enhance the button actions, we wanted nested button actions, now these are not required
 */
export default class UxEnhancementAction extends Action {
    /** This is a form element **/
    private _v: FormElement = new FormElement( this );
    /** Set the node, build the node's DOM tree (n.build), write it by passing in the FormElement's write function, and inherit the properties (props: true), then set the success value of the FormElement's write value (wv). REFACTOR NOTE: This should be renamed for clarity if we need to keep this method alive. - DEVNAME **/
    public set( n: Action.Node ): void {
        this._set( n.build() ).write( this._v.__setter.write, { props: true, val: !this._v.__getter._wv } );
    }
}

My attitude: If your code is self explanatory, you don't need long documentation. If it's confusing, write some longer docs. but, don't write no documentation, always document even if it's minimal

Collapse
 
tomazfernandes profile image
Tomaz Lemos

First of all, thanks for bringing this subject up, as it’s a very nice opportunity for all of us to learn with each other.

I’ve encountered a fair share of times when I needed to reuse some legacy functionality only to find out that it had so many long methods it would be better to rewrite or copy the code than mess with it and risk breaking it.

I think OO and agile principles are tools made to handle the assumption that the requisites will always change in the most unpredictable way, so breaking the code in small, coherent, reusable methods/ classes pays of most of the times, even if you can’t see it when you first write the code.

On the other hand, there’s no better time to refactor your code than when you’re writing it, with everything fresh in mind.

As for the comments itself, I think if you have to explain the code most probably you haven’t written it clear enough... You can extract hard coded numbers and strings to well named constants, “if” conditions to methods, and so much more.

That being said, of course there’s no silver bullet and it always depends on common sense.

Collapse
 
codemouse92 profile image
Jason C. McDonald • Edited

First, don't let anyone discourage you: you're doing it right. My company follows the Commenting Showing Intent standard, which literally formalizes the idea of commenting "why" on every logical statement.

Some people would say that this is redundant, but code rarely expresses its own intent. If an obvious intent gets restated in a comment now and then, it's not really much of a loss, since things obvious to us might not be obvious to others. Most of the time, the intent isn't expressed by even the best code.

Yes, it may well mean you have a 1:1 comments-to-logic ratio, but this is actually more useful than some would have you believe. Good commenting will allow the entire program logic to be recreated in any language, using the comments alone! Implementation varies by language, but the intent and logic are generally the same (with some exceptions). In practice, this actually means the cognitive load is less - we're not sitting here trying to imagine what the programmer (or our past selves) meant. We read the comment, skim the code, grok the idea, and move on. It takes less time, not more, to understand 1:1 CSI'd code.

Others complain that "comments fall out of sync with the code," but that's only true if we let it. When incorporated into a review policy (which every 2+ person project should have), discrepancies between CSI comments and the code generally indicate mislogic, which should be fixed!

In practice, we've been using CSI for a few years, with fantastic return on investment: faster code learning times, less bugs, and better reviews.

This is, however, distinct from documentation, as you pointed out. Comments express "why" to the developers, documentation expresses "what" and "how" to the end-users. Anyhow, most API documentation is like teaching someone how to use a toaster by explaining the electrical specifications of the heating element.