7
Swan
6y

Is it normal for a codebase to have almost no comments?

Comments
  • 7
    IMHO for a good codebase usually yes. A nicely organized code has well-named functions, variables, classes etc. so you don't need extra text describing what they do. Comments are only useful for explaining unusual/non-obvious decisions, but those should be avoided with only rare exceptions.
  • 1
    @gronostaj interesting. Stepping into industry from University where "Comment everything" was the norm I just find it strange. Doesn't make it the easiest to wrap my head around as an intern but I guess I just gotta get good.
  • 8
    Yepp... As Robert C. Martin has said, if you need to write a comment, you are admitting you have failed to do your job well. You're a failure.

    Code must be written in a way that it would be obvious what it does. Then it wouldn't need any comments.
  • 1
    When I can read my code like a book everything is fine. When I need a comment it is to complicated.
  • 4
    @Swan One clever thing they didn't teach me at university is that names of various code structures are great for describing your intentions. For example you can extract some code into a function and give it a name that describes what this code is supposed to do in context of the problem you're solving. Reading code tells you what it's doing, step by step, but it won't tell you why it's doing it or what purpose it serves - that's what names are great for.
  • 2
    @netikras I read Clean Code as well and I agree with that statement, but it's hard to find software that follows that principle. Maybe it's impossible.

    I have never seen anything even close.
  • 2
    @ddephor it's hard, because noone tries to write clean code. And when you say it like you've just did it sounds like it's not wprth bothering to write clean code. Maybe not even worth looking it up to find wtf is that..

    As a result noone will be writing it. And the souls that truly want to deal with clean code will be forced to maintain code written by people who didn't bother writing it properly.

    My point is, you will never work with clean code unless you start from yourself and write your code well. And teach others to do that too.
  • 0
    More comments means less code per line. Stay efficient 👍
  • 1
    Depends.

    Hacked together for personal use? I don't write comments.
    Very simple code? No comments.
    Big codebase? Well, I'd comment the parts that are a bit more complicated, or, if supported, make use of something like a
    #region preprocessor directive in C# to "comment" what a part of code does. If it's wildly unreadable code that just performs better than readable code, I comment more readable code that SHOULD be functionally equivalent. I made a rant on that as well: https://devrant.com/rants/2056266
  • 2
    @netikras i saw the video conference with him doing some 8 hours presentations over a couple days. not only is he dead center on what needs to be done, but damn if i'm not intrigued by TDD now, too...
  • 2
    Comment everything strategy results in comments that are less readable then the code they're describing
  • 1
    @alexThunder not quite. You always write code for others to read. Always. And if you fail to write it clearly, so that any newbie would understand what is happening and why, and you need to add comments to clarify it - you have failed.

    The code itself is an explanation of what is being done.

    There are a few exceptions where usage of comments is justifiable. EXCEPTIONS.
  • 1
    A well written one, or a terrible one...
  • 2
    Comments should explain why something is done. The code itself explains what is being done.

    Some documentation of the big picture about what is done where is more helpful when new to the project.
  • 1
    @electrineer you're right. Altho most of WHYs can also be described by code...
  • 3
    I don't think that the "why" can be described in code unless the code is trivial. As soon as the "why" results from something that is not part of the code itself, the code will never be able to describe it.

    Or if some function relies on certain preconditions, that needs to be commented right at the function header. Otherwise, refactoring becomes a debugging hell, especially if it isn't the original programmer.

    Also, great naming doesn't help when the problem isn't solved directly in the problem domain, but in a transformed domain, e.g. for performance reasons.
  • 0
    @Fast-Nop
    Preconditions:

    public void doStuff(String param1, String param2) {
    assertCanDoStuff(param1, param2);
    // do stuff here
    }

    private void assertCanDoStuff(String param1, String param2) throws AssertionError {
    assertHasPermissions(param1, param2);
    assertWizardDisabled(param1);
    assertResourceAvailable(param2);
    }

    The WHYs -- give me a case
  • 1
    Runtime asserts cost performance and are redundant code. Also, the actual function for asserting that data have some property would basically be the same function that had already been used to transform them, only rewritten as verification.

    Writing a lot of code just to avoid comments (just because some SW pope says so) strikes me as not helpful.

    Example for the why, that's always when external constrains limit your design and coding options. Just about everytime when you interface another system that either has limitations or even bugs. And sometimes, you even have to work around bugs in the silicon itself.

    Sure, you can try to name everything properly so that the code tells the story. That will be unreadable because then you mix two different categories together, namely why and how, and that's the opposite of clarity. It's a bunch of categorial errors.
  • 1
    @netikras Or, something I encountered this week. Suppose you start a bunch of processes via CreateProcessA(). Actually, you could assemble the command line string once and then just change the last word of it.

    So why do I instead assemble it once, and then before every call, I copy over that thing into yet another buffer, then change the last parameter, then call CreateProcessA()? Doesn't make sense?

    It does if you know that CreateProcessA() may change the command line string that you handed over so that you can't rely on what its content is when you call that function several times.

    This is stuff where I just don't expect future readers of the code to know the underlying issue and therefore have a comment in place.
  • 0
    @Fast-Nop Branch prediction should reduce runtime assertions' overhead. Since the main flow is more likely, performance hit should be the worst only when the exception occurs. Also, APIs should never trust user knows how to use the API and should assert proper values have been passed. Otherwise -- hello buggies! Hello all-night debuggings!

    Explicit assertions will point the finger right at the precondition that has not been met. Make a chain of such assertions and at any point in time you will know what/why has caused the unexpected behaviour.

    If you are abstracting some service, in the impl/adapter layer include those asserts as well. They will act two fold: as an explanation WHY you need THIS and THAT and as a safeguard for bad inputs, that will fail your flow fast AND will log the exact assert that has failed. Write assert methods as short as possible to make debugging as easy as a stroll in a park.

    At least that's how I do it. And it really works amazingly well.
  • 0
    @netikras APIs have associated documentation, and APIs are not meant for users. They are meant for developers. Sanitising external or user data is another matter.

    Btw, branch prediction isn't the whole picture - blowing up the code size also is a caching issue, and if something that could be small doesn't fit the cache anymore, it's going to be orders of magnitude slower. If the device in question even has branch prediction.

    Also, I usually organise my software in some layered fashion, and of course the middle layers rely on the lower layers having done their work. That's how I avoid having a big ball of mud that does everything at once.

    What you're doing seems like disguising code as comments, and I think that's nasty to read. My editor has comments in green so that I can easily skip them when I want to see the pure program flow. Bloated naming and code would not allow this.
  • 0
    @Fast-Nop this example of WHYs is not a good one. You should not care why is the function is acting as it is. It's something only implementation should know, not the API (user of the function).

    Either way, I'd do it that way. I don't think that mysterious inner workings should be used to bother impl users.

    CommandBuilder commandLs = CommandBuilder.getInstance("ls -ltrh");
    commandLs.runWithParam("/home/fastnop/Downloads");

    Impl:

    public class CommandBuilder {
    private final String cmdLine;

    private CommandBuilder(String commandLine) {
    this.cmdLine = commandLine;
    }

    public static void getInstance(String commandLine) {
    return new CommandBuilder(commandLine);
    }
    public void runWithParam(String lastParams) {
    run(cmdLine + " " + lastParams);
    }

    private void run(String fullCommand) {
    // exec stuff
    }
    }
  • 0
    @Fast-Nop developers are also API users :)

    Look, I really don't feel like arguing today. Let's agree to disagree. I've been doing my best to write as clean and descriptive code as possible, and I've seen it to ease my work tremendously. You have other thoughts about clean code paradigms (I had them at first too). I'm not telling you (or anyone, unless that _one_ is someone I'm mentoring) what to think or how to do your job. I'm only suggesting things that have been proven to work for most of people who have tried them.
  • 1
    @netikras I want a comment there so that it's clear why I chose an extra copy step. And CreateProcessA() isn't my function, that's a Windows function that I don't have under my control.

    Even in your example, I still would require an explanation of the extra copy step. If it isn't necessary, it shouldn't be there. So why is it there? Do you really want to call a buffer like "ThisBufferBecauseCreateProcessAMayScrewUpTheBufferContent" or so?
  • 0
    @Fast-Nop if this is something you do often, why not create a method that handles it and call that when you need to CreateProcessA()? you overload the method, hand the parameter to your overload and it takes care to instantiate a second string with the same content and hand _that_ string to CreateProcessA() while also returning whatever value the actual method returns back to where you may need that.

    i'm pretty far from an expert, but it sounds like you have a problem of recurring code.

    Also, using comments doesn't mean YOU have failed, it means SOMEONE has failed, and a method that is allowed to change an input from outside its' scope is pretty bad. i'd say that warrants a comment, but inside the method that handles just that part.
  • 1
    @ArcaneEye What would make you think that this has anything to do with repeating code?
Add Comment