Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

After the recent discussion about code-comments, that sort of code is exactly the sort that requires an explanatory comment.

Then all of a sudden, you don't need to waste time on careful and deliberate analysis, and hunting down people who might know about it, and making assumptions, because the 2 minutes it would take to write a few lines of explanation would save you all of that.

At which point, the real question is: why did they choose not to document this non-obvious solution, and the edge case that required it?



At which point, the real question is: why did they choose not to document this non-obvious solution, and the edge case that required it?

From my personal experience with "corporate programming", the usual suspects are:

1) corporate culture that dictates that you need to get the code out ASAP and let someone else worry about maintenance

2) original author's assumption that he/she will be the only one to touch that code

I've been guilty of #2 before I learned that even if I am the only one to touch the code, if I wait long enough before I come back to it, I'll still have the same problem as a newcomer would.

As for #1, this is a typical corporate culture for any company whose business isn't producing code (and for quite a few whose business is precisely that).


3) The code was indeed obvious for the people who had worked on the project for a while.

When you get familiar with a domain it is very easy to get blind to what people without exposure to it will consider obvious or not.


3) A culture that thinks/mandates that "unnecessary comments" "clutter" the code.

4) Documentation that is held separate / made in different systems. That diverge over time. Or, one failure in training of the new guy is to not provide them a good overview of the documentation system(s). And/Or, the documentation organization and systems are cumbersome to the point of being unuseful, unless you already have a pretty good idea of where stuff is (and isn't -- all those empty forms that end up being ignored).


#4 has made my life miserable in the past, and will probably do so again. ISO certification requirements seem to exacerbate it, interestingly (frustratingly) enough.


1) corporate culture that dictates that you need to get the code out ASAP and let someone else worry about maintenance

Unfortunately, three months from now, "someone else" is you, and "getting the code out ASAP" means figuring out the spaghetti code you wrote but no longer understand.

In the long run, doing it right the first time helps us go faster. Therefore, it's part of the programmer's job to resist pressure to do it wrong.


Comments, and, one would hope, some tests showing how the obscure edge case interacts with everything else.


Sometimes you don't know what the edge cases are because you don't know what the everything else is. If you return something sorted, somebody will write a consumer that depends on the sorting. If you change backends and return things in a different order, you've broken their code. Sure, their code was broken from the start, but it used to work, now it doesn't, and you're the guy who changed something. The only way to prevent this, randomly sorting every unsorted collection you export, isn't feasible to reliably maintain.


> The only way to prevent this, randomly sorting every unsorted collection you export, isn't feasible to reliably maintain.

It's feasible to maintain. But people might rely on it, too. As a random example (and easily avoidable example), quicksort works with random input, but 'breaks' for pre-sorted input.


That depends on the pivot chosen. If your quicksort implementation actually hits n^2 behavior with sorted input, it's probably not the best implementation.

Any implementation can hit n^2 with random input. It's just highly unlikely.


Yes, I know. That's what the "easily avoidable" was for. I couldn't think of a better example in a few minutes, but if something can go wrong, I am sure it will eventually go wrong.


Agreed, with one caveat: even better than explanatory comments are explanatory method and variable names, when possible.

For example, you could have one 10-line method, interspersed with comments, or you could have a hierarchy of method calls, each with a name so clear that it needs no comments. The second method is less likely to get out of sync with what the code actually does, and it's more testable.

This the lesson that stuck with me most from Clean Code, which I highly recommend.


Even better is naming things as intuitively as possible, and to use explanatory comments where they would be helpful.

Not trying to pick on you, but every time I see someone implying that "naming things better" is a panacea, I want to throw it out there that sometimes, nothing beats a good comment to explain (in natural language) what's going on here.


We're on the same page. Generally, I find that naming things better helps explain what the program is doing, and comments help explain why. And comments will stand out best if they are only used when needed to answer the question "why didn't they just..." :)


I've come across a lot of code where the code itself was the clearest way to communicate the subtlety inherent in it. I think you have an inflated expectation of what human languages can document in a reasonable space. Many times it will take months to understand the edge case even if you have a human trying to describe it to you directly, let alone by reading a non-interactive comment.


The code may well be the clearest way to communicate the subtlety. That doesn't mean a comment isn't helpful to communicate that there's subtlety there and give some idea of what sort of case it's meant to be about.

  // It may look as if you could just say p->adjust() here,
  // but that doesn't work because of a subtlety involving
  // cancelled credit cards belonging to purchasers in Uganda.
  // Please tread carefully!
... And then, if talking to another human being is the only real way to grasp what's going on, you use your version control system to find out who added that comment and go talk to them.


You'll run into problems as soon as it's not the code that's left which explains the subtlely, but the code that you had to remove. In such cases, a comment explaining (for example) why the obvious choice of library FooBar was abandoned for a more direct-metal approach would provide the answer to the code which isn't there.


In these cases a simple, "Function is required to handle multiple edge cases", comment would at least alert other developers to a reason for ostensibly odd or overly complex code. This along with well commented test cases solves most issues.


But you might not even need to understand the edge case, you just need to know that it's there, and it means the code is more complex than it really should be. The code itself cannot reasonably communicate the developer's true intent, and so a short comment can remove any ambiguity even if it doesn't explain the issue in full. The GP assumed incompetence, when it was really pragmatism.


After the recent discussion about code-comments, that sort of code is exactly the sort that requires an explanatory comment.

If the code isn't the clearest comment you have, you're doing it wrong.

Comments are a crutch for people who write poor code. Comments have zero authority or guarantee of accuracy, and more often than not have little correlation with the actual code.

Code is canonical. Comments are noise.


I think you're wrong for one simple reason: business logic.

Business logic is complicated and rarely defined by a developer but by a product manager. Often you can understand what's being done in the code, but the WHY is necessary to understand why it's there and what it is trying to do. I believe giving a brief synopsis of the business logic in a method comment and, if it's not super straightforward, a brief overview of the steps or algorithm, is incredibly useful.

I guarantee you won't be able to figure out what your program is doing by looking through years old wikis left by product managers no longer at your company.


Just to be clear, the person I responded said, in effect, that the code did X. They made code that did Y, and then realized it didn't do X. That is the story of a million ill conceived code rewrites.

That the code did X is clear by the code: No amount of words can refute or change that the code does X. The danger is replacing code is always in the behavior of the code, and never simplified descriptions of its actions.

To business logic, as someone who has worked heavily with business code for years (laughable commentary from imbeciles to the contrary), business logic in comments is one of the worst choices a team can make because it is an escape hatch. It negates the need for verbose, traceable code. It negates the need for vastly superior external proof.


Mathematicians have much more convenient symbols and powerful notation than programmers. Yet they use text, too. Even wondered why?

Donald Knuth, who gives money to people who spot bugs in his code, even invented literate programming to mix prose explanation and code better. Is he an idiot?


I'll happily be "so brave" and reiterate a simple truism of software development -- comments are the battle cry of terrible developers.

They are the crutch of people who can't read code: "Add more comments because otherwise I can't make sense of what the statements are doing." It is the English speaker demanding that every French passage have an English translation, rather than simply learning French.

They are the crutch of people who can't write code. "My code is a gigantic, illiterate mess, so instead read the comment at the top that has no guarantee of being robust or accurate."

Bringing up mathematicians and Knuth are both irrelevant distractions. Software development in the modern world is a very structure, self-describing affair, or at least it should be. Comments are the short-circuit from having to figure out how to do that.


I'm not meaning to insult you, but you sounds like a programmer who's experience consists solely of personal projects and academic assignments.

As has been said, comments explain why you are doing something in a certain way. That why is often related to a business process, several business process, and/or 25 different outside cases.

The code can be amazingly clean and organized, but you comment to indicate why you did something one way and not another.


I'm not meaning to insult you

Sure you are. And that's okay.


I'd like you to offer some examples of code that successfully documents its own raison d'être - in a way that a comment couldn't do better - instead of repeating this 'crutch of poor developers' rhetoric.

I mean, I can write self documenting code without any comments, and it's perfectly understandable.

    before_create :auto_increment

    def auto_increment
      self.count + 1
    end
That code fails to tell the programmer why it's in the application logic and not defined in the database schema. What should I do instead, so I can code without crutches?

    def auto_increment_natural_key
        self.count + 1
    end
That's not a great deal better, it's still just saying what it does, not why it's there in the first place.

    def auto_increment_natural_key_because_another_app_relies_on_it
        self.count + 1
    end
Is that it?


Your code doesn't actually seem to do anything, so a comment would either be contradictory to the code, which is confusing, or explain why your code does nothing, which is silly.

I would argue that in this case, it is far better to just understand the code and then fix it appropriately. A comment would leave you second guessing.

    def auto_increment
      self.count += 1
    end
(though, for the purposes of self documenting code, count probably is not a great variable name either)


Rather ironically, it appears my poor choice of example could have done with some more documentation.


I'm now curious to know what you would have written for documentation.

Though, I think your example turned out to be a great one because it highlights that not everyone reads code the same way. Personally, I load large segments of code into memory and then mentally step through. You left me wanting more to see the context in which the method was to be executed, but I didn't really feel the need for comments.

However, with just the one method that you wrote in your example, that seems to indicate that you read just one function at a time. If you are not observing the code as whole, I guess a comment would help. I often find them taxing though, as they have to be read into memory as well.

I think that discrepancy is why the comments vs. self-documenting code debate exists.


The problem was I initially hinted at the context in my first example, with a call to Rails' `before_create` callback method. I then omitted it from every other example, thinking it'd be inferred. Evidently that wasn't very clear.

But the way in which people read code is an interesting point, which I actually think might be worthy of its own discussion. Looking at the psychology behind this would be good, I think.


> Evidently that wasn't very clear.

Actually, I would say your intent there was quite clear, which is where I came to realize that the code did nothing. Without that context, one could assume the method was used for its return value where the code could very well have had purpose as written.

What wasn't clear was how the count attribute was intended to be used throughout the rest of application. In the real world I would start to build a mental model around the uses of count, which was not available from your example. In terms of self-documenting code, I liken a short code snippet like your example to a sentence fragment in english. The entire sentence, or statement if you will, encompasses much more of the codebase.

This is definitely an fascinating topic, but unfortunately one that is very difficult to discuss for many reasons. I wonder how we can dig into the physiology aspects that you raise without the prevalent "my way is the only true way" attitude?


Thanks for trying!

Now we just put the comment in the variable name. The compiler just checks the variable names all match up, but doesn't check whether their names make sense.

Perhaps the example chosen was too much of a toy to yield valuable insight?


That code fails to tell the programmer why it's in the application logic and not defined in the database schema

Why isn't it a GUID? Why is it 32 bits instead of 64? Why is it signed yet starts at 1? Why isn't it a string? How will the identities be merged?

The notion that answering one single question provides clarity is ridiculous.


def auto_increment_natural_key_here_because_if_a_product_doesnt_have_a_key_assigned_because_it_came_back_from_return_and_wasnt_assigned_on_during_the_recieve_shipment_process_the_key_doesnt_exist_and_another_app_relies_on_it

Pretty sure that's it.


Your sarcasm is screwing with HN's page formatting.


This is what element inspectors/editors are for. Snip, snip.


I had to use inspector to make the page readable, but it's a PITA. GP is a jerk.


Agreed. Just pointing out there's a workaround.


Your hubris is certainly self-documenting, if it gives you any comfort.


He (or she) is just early on the path, and like a newborn kitten their eyes are still closed. In the mean time keep them away from pointy things.


I hope that caricature gives you some comfort in your utter mediocrity.


What a useful contribution.


Do you have github/sourceforge? I'd love to read some of your non-trivial code.

I'm not trying to be an a$$hole btw. I am not a coding guru, I genuinely want to minimize the need for comments in my code and am willing to learn from examples.


Do you have github/sourceforge? I'd love to read some of your non-trivial code.

Read almost any non-trivial successful project for good examples. The Linux kernel. Firefox. etc. The frequency and verbosity of comments tends to have a direct correlation with the simplicity of the code (which is the exact opposite of normal expectations).


Linux and Firefox code basis are messes.

Have you written any large projects that you've had to maintain over years, or worked with large teams, or handed off maintenance of a large project to others?


Two projects that are enormous successes, both with more contributors than any code that you've ever touched, I would wager. "Messes". Indeed.

To your questions, while you're rhetorically asking, trying to wink to the crowd in the implication that the answers are telling, yes, actually I have. To very good effect. I'm speaking from actual experience here, not just the hilarious patter of the bottomfeeder that is far too typical on HN.


> Two projects that are enormous successes, both with more contributors than any code that you've ever touched, I would wager.

No.

> "Messes". Indeed.

Yes, messes. Why do you think Chrome is eating Firefox's lunch ? Google has both a better-implemented product and sufficient marketing clout to push it.

Have you worked on Linux kernel code?

> I'm speaking from actual experience here, not just the hilarious patter of the bottomfeeder that is far too typical on HN.

What have you worked on?

I've worked on FreeBSD, Mac OS X, and an assortment of smaller widely used software projects, including user-facing applications.


Why do you think Chrome is eating Firefox's lunch?

Humorous given that both webkit and from that Chromium are largely comment free. What nonsense are you arguing again?

I've worked on FreeBSD, Mac OS X, and an assortment of smaller widely used software projects, including user-facing applications.

"Worked on" in HN parlance means "I did a coop term and wrote some test cases for some irrelevant little utility". Given your comical claims about Linux and Firefox re: Chrome, I have enough information about your skills.


> Humorous given that both webkit and from that Chromium are largely comment free. What nonsense are you arguing again?

Seriously?

http://src.chromium.org/viewvc/chrome/trunk/src/ipc/ipc_chan...

  // If the channel has already been created, then we need to send this
  // message so that the filter gets access to the Channel.
http://src.chromium.org/viewvc/chrome/trunk/src/ipc/ipc_chan...

And so on.

> "Worked on" in HN parlance means "I did a coop term and wrote some test cases for some irrelevant little utility".

Please go back to Reddit.


An enormously complex rendering and JavaScript engine. Some laughably irrelevant, trivial comments. Quite a solid proof you have there.


Those comments are trivial and irrelevant?

You clearly have no idea what you're talking about. I hope I never get stuck cleaning up your messes, but chances are that someone as intellectually lazy as you -- if not you -- will leave me an uncommented code base to maintain.

The fact that you actively advocate intellectual laziness is distressing.


Intellectually lazy? That's a mighty big term for someone like you.

Further it's utterly astonishing that you would equate writing clear and non-ambiguous code rather than nebulous code of uncertain purpose -- like the example Chromium code you linked -- is "intellectual laziness". That you hold good coding as deficient compared to lazy commenting is hardly surprising given your comments.


Failing to document code is to the detriment of future maintainers. Anyone that claims their code is clear and ambiguous without comments is lying to everyone, including themselves, as a means to justify their intellectual laziness.

"I don't need to comment" is really "I don't want to document my work because that's boring and I'm much too smart to need to do that".

You're not that smart. If you were, you'd realize just how dumb everyone is, and thus, just how necessary comments are.


Hey flatline3, I feel your pain, but it's time to stop feeding the troll.


Making the machine check as much as possible about your code is a worthy and practical goal. I often try long and hard to capture as many invariants as possible in the type system. And even though the language that we are using, Haskell, has one of the strongest typesystems you can find, that's still not very much logic guaranteed by the compiler. Of course, run time checks can catch a few more errors, but I'd rather catch mistakes as early as possible.

You seem to have lots of experience with expressing intent in code, and making that intent 'canonical'. How do you make the machine check the accuracy of your code? What language are you using for that?


You seem to be missing the point of comments. Comments are not meant to explain what your code does. They are for explaining why.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: