// don't use hardware acceleration
canvas.enableHardwareAcceleration(true);
Which is true? The comment is lie. Is this a bug? Was this changed for some reason? Should I remove the comment? Should I toggle the boolean? Why weren't we supposed to use HW acceleration? Why are we using it now? What changed? What value did the comment have in the first place?
// Hardware acceleration should be switched off.
// Originally we'd planned to use hardware acceleration but later
// on in the project's life cycle we were told we needed to support older
// versions of Foo: X and Y. This caused some bugs documented [here](#123) and [here](#234)
// due to incomplete support of feature Z and the way that [internMethod()](#internMethod) is currently implemented.
// @TODO: It would be better if we could switch it on or off depending on the device.
canvas.enableHardwareAcceleration(true);
Comments should be organic and give context.
They should describe why and the high-level how, while code should describe what and the the low-level how.
That's just my opinion. This is the kind of comment I write. From time to time it becomes incorrect when a project's moving fast, but I write enough that it's very easy to validate that the use cases and code I'm talking about are real. You're meant to delete the comment immediately if it's incorrect: you can choose to help the next person understand the code or not, that's not up to me.
I think something that's very important is trying to show where a line of code or method fits in the greater scheme of the architecture of the code by linking it towards the methods that are interrelated in important ways.
Edit: You might notice I've left the comment not matching the code. This is a fact of life: somebody will change the code without updating the comment. However, because of the comment you now have a great way of sanity checking this change without having to find the original coder or test it all. Basically: it tells you what you couldn't quickly know looking at uncommented code.
Let's look at some stylized comments I've seen over the years:
// Add tax
total = price + tax
Useless comment, isn't it?
// Iterate over the order items
for item in order:
...
Also useless.
for ($i = 0; $i < count(points); $i++) {
if (...) {
// Break out of the loop
$i = 1000000;
}
}
Not as useless as the code below it, but still pretty useless.
def add_item(order, item):
'''Appends item to order.
param order : instance of <Order>
param item : instance of <OrderItem>
return : None
''''
order.append(item)
This is a great example of a useless docstring. The developer might as well have put the code into the docstring.
# <HACK-ALERT>
# The code below uses an undocumented API, that nonetheless we must use in order to make the code work.
# As per <link to StackOverflow> and <link to unresolved ticket>, this is a known issue.
# We may be able to remove it after release X.Y where the upstream fixes it.
Widget._enableDitzelMode(Widget._DITZEL_MODE_FLAG_X)
# </HACK-ALERT>
This is not only useful, but more or less required. If you do any kind of monkey patching, please add this.
# <DANGER>
# The code below looks wrong, but is in fact correct. This @#$%ing API makes you say "true"
# when you mean "false". Do not alter without reading <link to docs>.
# Set PRODUCTION mode to ON.
Widget.setStagingMode(true)
# </DANGER>
This is also pretty much required, I think.
// Make sure to use === below since foo can be null OR '' which mean different things for us:
if (foo === null) {
alert("Value is unknown.");
}
else {
processValue(foo);
}
I'd say also useful, but the code is going to change eventually.
Sure. Let's say the author intended to disable hardware acceleration, but introduced this bug. A reader might notice the disagreement between the comment and the code, and investigate.
Now take away the comment. You would never know from reading the code that there might be a problem.
This is a bad comment, but it's still more useful than no comment.
I think it may be possible for all of the following to be true:
1. Comments explaining the 'why' can be helpful.
2. However, due to their inherent DRY violation, comments may become out of sync with the code and impose maintenance costs.
3. The value of comments still outweighs their maintenance costs.
That is to say, an example of a misleading comment doesn't necessarily prove that comments are bad in general. The converse may also be true, however. I no longer have a strong stand on this issue. I try to generally go with whatever commenting style the project I'm on uses, though I also have been known to write the occasional long descriptive pre-amble.
>What value did the comment have in the first place?
That comment is the only indicator that something may be wrong. Your next steps are the same as with any suspected bug, find out what the code is doing (seems obvious here) and then find out if that's what it should be doing.
That comment, however, is a good example of a bad comment. In this particular scenario, it's very obvious what the code is doing, so the comment should describe why the code is doing what it's doing. Much like should do:
> That comment, however, is a good example of a bad comment.
Yes, assuming there's not some contextual reason why hardware acceleration is obviously inappropriate. But even then, it would be much better to err on the side of "assume the next person to read it hasn't had their coffee yet."
Even something like "don't use hardware acceleration because compatibility issues" would be a better comment. You don't need an essay. But it should be both concise AND descriptive of the issue, not just normative or prescriptive.
Almost every time I've done this, that pattern means "I really shouldn't be doing it this way, but we'll do it this way for now because getting it done is more important. Improve it if emergent bugs or profiler results ever indicate it's worth messing with again, but I'll probably get back to it never."
It's not a TODO or a BUG, but it's helpful to make note of for future code review or reuse.
I'm of the philosophy that code should be readable, reasonably self-documenting, and remind you of relevant external material - whether that be your state of mind at the time, or reference material you drew on, or whatever.
Not everything needs an open issue, but the knowledge should be recorded somewhere. I know for a fact I won't remember it in six months, and likely not in a week either.
(I also write a large amount of utility code that's below the "project" scale and will probably never see a PM tool, but which is nonetheless part of a heavy reuse ecosystem.)
To me, that signifies that I know the way I'm doing it is wrong, but it works until I can figure out how to do it right.
Yes, I would be a horrible collaborator on a project. Most hackers would be, for the definition of hackers meaning "people who do isomething because it works, not because it's good programming".
TODO statements should be conserved to actual pending tasks.
Code in this pattern is often a compromise, and may be found as contributory to future issues, but it probably didn't merit a follow-up task at the time of writing.
It's not a pain. Source control history is the ultimate commentary. But the same ideas apply to commit messages as to source comments - if they say what instead of why, they don't help much.
Looks up the spec to see the correct behavior, just ask the person did the change, or test it yourself to see why is there a contrasting comment. May be hardware acceleration was meant to be turned off but the guy was testing it by toggling the flag and forgot to set it back. In that case the conflicting comment brings the potential bug upfront.
Find out who the author was via git blame and ask what they were thinking when writing it. Or in the case that the person who wrote it left, contact someone with some knowledge of the line in question (i.e. the person who either also wrote the majority of the code or is at least familiar with what it does) and ask. If it comes down to it and you're the only one qualified to do something about it, then just remove the line (assuming the code is functioning properly) just how I would approach it.
You're completely right, there is no sense in pointing out what kinds of comments detract from readability and anyone writing about that is a smug jerk.
All sarcasm aside, there's nothing wrong in getting your thoughts together in comments before you actually write code. What the author objects to -- and I agree with that objection wholeheartedly -- is leaving those comments in your code once you're done coding.
Other comments describe and discuss the dangers and downsides of leaving the "what" and "how" comments, so I won't go there. Instead, I'd like to propose a habit to establish when writing code: when you're done coding, remove all the "what" and "how" comments and try to read the code. If you can leave it overnight before trying to read it, even better. If it still looks easy to understand without those comments, then there's a chance it might be good enough for other people. Otherwise, do whatever you can to make it more understandable -- break it up into smaller methods with descriptive names, for example.
The point I'm trying to make is that there are two kinds of WTFs I get when I'm trying to read code: the "why the hell did they do this" WTF and the "what the hell does this do" WTF. The former is the kind of WTF you have to solve with comments, because no amount of comments is going to explain why you've done things this way, whereas the latter should be solved by writing more readable code.
It might even be checked in while development is happening.
However, the "whats" are taken out completely - the tests are better places to figure out how it works, anyway. The "hows" are mostly taken out -- if someone needs to know how it's working, it needs to be refactored. (And that's why I wrote the tests!)
What remains are the "whys." Why was this algorithm chosen? Why does this look seemingly broken? Why is this code here? (IE, performance improvement led to a little less clean code.)
Don't listen to this guy. Copious comments are great.
1. They act as a easier-to-skim narrative of the code. You can often get an outline of a well-commented component by reading the comments alone, rather than by picking apart a language designed for machine consumption. Syntax highlighting makes this especially easy.
2. They're helpful for other programmers who may not be as comfortable in the language as you are. For example, my PHP is about ten years old; I had no idea that `__construct` is the constructor, and not just another function. But thanks to the "useless" comment, I do know that.
3. They're helpful for programmers who aren't as comfortable in the problem domain. A line in a FFT implementation may be "obvious" to those skilled in harmonic analysis, but not the poor client programmer who is trying to figure out why the function is returning garbage output.
4. They can be useful as a thing to search for when you need to navigate around.
When deciding if I should write a comment or not, I ask myself a simple question: if I come back to this bit of code, will it be obvious why it’s been written this particular way? If my future self will be very thankful for an explanation, then it’s a no brainer, I write the comment.
Note the assumption that the code will only be consumed by "my future self".
Ever maintained someone else's under-commented or no-commented code? I'm sure the original programmer did not have any trouble with it, and will never know what he inflicted on his successors. Spend some time working in a comment desert, and you'll never complain about the rain.
Don't code for machine consumption, code for programmer consumption. Code is read 5x more than written, etc. Use function/method/class names that are readable like an outline.
Code comments are a poor teaching tool. Use a coding style guide/standard, pair programming, training, or a book to teach basic language idioms.
I don't buy the "searching argument". Ctrl+F for "account" will match a method named "lookupAccount" just as well as a comment that says "//lookup account". If you use a somewhat consistent naming scheme, it will probably be easier to search for something - try finding more than 2-3 words in a row in prose.
Putting so much perceived value and trust into code comments is like trusting "Architecture Design.docx" instead of looking at the actual running code.
If "copious comments are great" is true -- does that mean we should write copious comments?
I'm talking about opportunity cost here -- the time spent writing comments is time not spent on the code, design, test, etc. So for me the question becomes what I should do to provide the max benefit for the least cost -- should I write comments, improve the design, fix up some code to eliminate special cases, test for corner cases?
Since it's an inherent trade-off, I don't see this as being an easy question to answer. Probably, there are multiple adequate answers.
I suspect part of this is enforced by TA markers in university.
When marking a TA isn't trying to understand the code, they just do not have time for that. So when evaluating the documentation or comments portion of the mark they just scroll through and see how much gray is on their screen. No marks are ever deducted for bad comments.
The situation can get so silly I've had TAs complement my code and the design then deduct full documentation marks.
This has led some people I know to go over their code before submission and add worthless comments. To them "documentation" is a separate step which occurs after you've written and tested everything. The whole situation is a shame.
I never counted students off for comments, although I also never worked with a professor who had a policy of "All Code Must Be Commented Or Else." I don't think many professors did, at least not for upper-division classes. Perhaps related - most students didn't comment at all (I largely dealt with CS seniors).
Then we had a bunch of students get counted off for bugs, unimplemented features, or general weirdness in their code.
As a rule of thumb, the very few people who did comment got much better grades simply because I was allowed to give partial credit. If they at least commented what the heck they were trying to do and how, and why they thought it advanced the project - I could probably figure out what went wrong and award points accordingly.
You know that Tolstoy quote, "Happy families are all alike; every unhappy family is unhappy in its own way"?
It applies perfectly to bad code. Whether we're talking university or industry, having SOMETHING there so that your teammates or the senior developer on the team can figure out what you were TRYING to do is an enormous help.
Going comment-light is fine in a perfect world where you have concise, elegant code that works perfectly and is absolutely clear when you come back in six months and try to figure out how you structured the program and what role any particular snippet serves within the greater whole.
It's not a perfect world.
(At the same time - readability functions such that if you put a bunch of trash comments in, people reading your code will assume that most of the comments are trash. You can't just tick the box and expect that to be enough.)
Working as a contractor, there are often deals that mandate "100% of functions documented" or other silly stuff (I would never strike such a deal, but have inherited projects with this). Since the client actually never checks the code (only metrics) and will never pay what it would cost to create amazing documentation (which only makes sense for public APIs) we just end up with tools that automatically adds comments to functions, which means the codebase ends up with useless javadoc-like clutter.
It's the same with "100% test coverage", which is similarly abused, programmer's are a lazy bunch, and smarter than any tool that measures the quality of what they do. So forcing them doesn't work out great.
Working as a contractor, there are often deals that mandate "100% of functions documented" or other silly stuff
I'm not so sure that's silly. It's absolutely overkill, but in a contractor/client relationship it makes sense that the client will want to make sure they have all the coverage they can get. And as a contractor you can bill for it.
I've argued my way out of TAs downgrading me because of comments, when the comments I DID have conceptually covered several lines of source code (and they were looking for a comment on each line).
This is one of the reasons that programmers who haven't read much of other people's code are a liability. They're as lost as novelists who don't read books.
The difference comes down to empathy: if you can get inside the head of your future readers, you'll know when to comment, and what to name that function, and how long the functions should be, etc...
So can we say the same about people who try to lobby everyone not to use any comments just in case they might be wrong? Because a helpful comment can be a very helpful thing to a reader of code
The example that he gives that I take issue with is the "Constructor" one in a JavaDoc comment.
When using documentation tools, every undocumented function spews a warning. And that is as it should be. But some simple constructors don't have any functionality worth documenting.
I code as if all warnings should be addressed, and that's true of my documentation generation. If a public function has no documentation, that should be considered an error that needs fixing. If the documentation is obvious, then so be it.
That is the price you pay for reliably good documentation; without enabling those warnings you don't know when you've missed documenting an important function. And even sometimes the "obvious" is useful; I don't know how many ambiguous Boolean parameters I've seen where it wasn't clear what value "true" represented.
+1 I'd much rather side with the "document every function" camp and have a few extra comments, than inevitably degrade to the "document close to nothing" camp and have functions named "normalize" and "resolve" that have to be in their entirety to understand what they do. That being said, I like to drop the `@return void` and `@api public` type entries because they're almost always self-evident, or even not true, like in Javascript where everything is public if exposed and people will reach in no matter what you do.
Writing docblocks can also be a nice way to check yourself from writing bad code. If you find yourself adding 4 different `@param` entries it makes you stop and think, "why is my function taking 4 arguments, it's probably poorly designed".
If you're only documenting after the fact, your function isn't worth documenting: it means you conceptually understood it well enough that you didn't have to think much about it's inputs or outputs. If you did have to think through it, or your code reviewer doesn't understand it, add a comment explaining it. In any other case, commenting on it is probably useless and adding to clutter. Javadocs are painful to read, not because it's a bad idea, but because so often it's things like "toString(): returns a string that is the string of this object".
Sorry, I only need to know that function exists and it's return. I want to be able to scan through and see only those functions that are conceptually strange or unique, not the boilerplate that every class has to have, and is identical. If there's a comment on the toString() function, it had better be documenting something interesting, or else it's more useless than nothing.
>If you're only documenting after the fact, your function isn't worth documenting
I can't disagree more. You can completely understand what you intend as you're writing a function, and then later, as you look back with a fresh perspective, realize in what way(s) the function could be misunderstood.
>Javadocs are painful to read, not because it's a bad idea, but because so often it's things like "toString(): returns a string that is the string of this object".
Straw man. "Bad docs are painful to read." Sure they are. If you have good documentation practices, you'll explain in toString() HOW the object is represented. "Return A string that indicates the (derived) object type, its x,y coordinates, and its current state, along with any additional state specific to the derived object type. You should not rely on its precise format, as it may change in the future."
The real problem is that most documentation sucks. But the only way that developers will ever get better at documentation is to practice.
I also am confused as to why "scanning" JavaDocs would ever need to be a thing; you do end up with your JavaDocs as a web page or help file, right?
If I'm confused about a function, I want to be able to click on it and see docs; if there are no docs on half the functions, that's a failure of the imagination of the API author(s). If they can't see how someone might be confused, and yet I'm confused, then they blew it.
This isn't always possible in every case--it's not too hard to imagine a lot of trivial assignment all going on at once, that isn't immediately obvious what it is or why on earth it exists.
//really bad example, just something really repetitive
function main()
// set up month boundaries
janStart = blah;
janEnd = blah;
// ...
decStart = blah;
decEnd = blah;
end
where it's not too hard to imagine many languages without great pointers needing to keep that inline to avoid making all of those variables global. In some (hopefully most) cases just better design in general can get around it, but I wouldn't always count it out immediately.
What's to say a function gets "fixed" without updating the name, in the same way that comments will not get updated? I see it would be less likely in a function, but not impossible.
> Descriptive function names never lie, comments often do.
Description function names lie just as much as comments. For example, I have run into cases in the wild where things like "get_item()" create database entries before returning a value. Yes, side effects are evil, etc etc, but the point is that at some point, somebody maintained the code and did not update every use of get_item() to now be get_and_or_create_items_if_it_is_sunday(). In rare cases, I have seen them at least update the local documentation.
I cannot recall a time in my career as a programmer where the inclusion of a comment has caused me serious problems.
However, I can recall many, many times where I've read code that does something odd, and wished that there was some documentation explaining it.
I've met many programmers who rarely comment and make points similar to those made in this article. It's an easy argument: code should be self-documenting. But I've seen too many programmers jump from "code should be self-documenting" to "I shall never use comments/docstrings."
I feel like the problems outlined in the article are overstated. It really isn't a big deal when you read a comment that doesn't make sense, or is empty of content. It's a much bigger deal when you read strange code which really deserves documentation but there is no documentation.
If you write this: x = 1; // sets x to 1
I HATE YOU
Explain the WHY not the WHAT
It's the same crap with the Hungarian notation, where half MS didn't get how to do it properly. It's not the computing type, it's what the variable represents. Thank you, I know this is an int, the compiler knows it's an int. What I need to know is what this is counting/representing/etc
I'm beginning to believe that if code is simply a machine-interpretable codification of human expertise, then we should be able to express precisely what the code should be doing using written language as well.
I've been turning this over in my head to figure out how it should look in practice, but I'm wholeheartedly believing the following statement is true:
"All code should be composed in two languages: first in whatever programming language the task requires, and second in whatever language the programmer speaks natively."
I guess an extension of what I mean is maybe we should write our comments in a way that a human could read a program like a set of how-to instructions, complete the same operations, and arrive at the same result interpreting your work in written language as the computer would arrive at running the code. In my way of thinking about things, code wouldn't be complete until it could be interpreted by man and machine equally.
This allows for the preservation of our human expertise by guaranteeing that any program can be translated in the future by another human reading the same written language into any other programming language (even if they can't understand your code). This could be important especially for some of the more exotic languages with sparse documentation today, imagine what it will be like trying to decipher these things in 200 years!
Comment first: project the document instead of documenting the project.
In other words, write the comments first, then write the code,
then review and tidy up both the code and comments.
By writing the text first, you clarify the why before you write the how.
You also capture the high-level view before you get down to the gnarly
details, after which the high-level view can become a vague ghost of
a memory.
Once that high-level view is left behind, many people become so immersed
in the coding details that "introductory" material written after coding
often begins with the esoteric details of the implementation of the
central algorithm, and fails to mention what the tool/packages/code/app
is for in the first place.
To put it another way, documenting is to code as foreplay is to sex.
Both code and sex can be effective without comments or foreplay, for some
values of effective, but they are more likely to be more pleasant and
repeatable over time if people put in a little time and effort before
rushing ahead to what they see as the most interesting parts.
I'll suggest there's a missing ingredient here...I found I was able to eliminate many of my comments by asking myself if that someone whom might read my code would be better served with a unit test instead. I also found, however, that this needs to lead to an understanding that unit test are in fact a form of documentation and should be treated as such.
I've learned coding in Forth, so my code is often creating a domain specific language to solve a class of problems, and Forth shadow pages caused the documentation to be roughly same size as the code itself. But I normally comment in manual style. So the comments in my code do not tell how it works internally, but how to use it, and they are extracted from the code to create a standard Unix roff manual page. I think the Perl community did a good job in constraining a documentation style that is useful for those who want to use a module.
There are seldom exceptions, where I actually comment the code itself. Those are clear warnings that this code is not trivial to understand for average programmers. E.g. my w3dig search engine implements a recursive descendent parser for the site description language, that is not always executed linear, but sometimes pushes a parser class instance together with a closure to a queue, for parallel execution of the spider.
Not that I don't agree, sometimes unnecessary comments kind of make it a bit complicated to understand what's going on. BUT, an important point to mention is that coders write code in different styles and manners, there is no right and wrong when it comes to comments. Sometimes just seeing that comments exist (even if some lines are pointing the obvious) makes a difference to the inexperienced or to the new-comers. Not to mention that "obvious" here depends heavily on the experience of the developer with language, framework, or whatever they're using. I guess the person writing the code should at least get to write comments the way the like. You're a programmer, reading a couple of extra comments won't ruin your day, just skip it if it's obvious.
Comments in production code have always been a pet peeve of mine. I understand the OP's frustration on useless comments where the function clearly states enough in it's naming convention.
I brought this up to one of my instructors before and he said that comment overhead is negligeble on bandwidth (I was referring to css and js commenting at the time), but I don't think that's true when you factor in mobile networks and when some teams comment every freaking line when naming convention and common sense should suffice.
One of my guiding principles for code comments has always been "say why not what". If I can't figure out that what on my own then something is probably very wrong with the code. What I want to know is why you used a for() instead of a while() to iterate over an array or things like that. Comments that explain what you're doing I find to be cruft. I don't necessarily hate on them but I do find them unnecessary and unhelpful.
My current employer makes the useless code comments mandatory. They do not need to make sense or be useful; the requirement is that they exist. Fortunately, they pay me enough that I am not looking for other jobs over it.
No, I'm looking elsewhere due to the many other aggravations that are not worth the salary.
Not only are businesses training younger developers to do this, but they are training older developers to expect it. Of course it is going to bleed over into the real world.
Good code has documentation, therefore our bad code will become good by adding documentation. Truthful comments, such as the following, would likely get the writer fired and not improve the code one little bit.
/* This code block is a crufty, kludgy crock of dung. I have argued several times that it represents a morass of technical debt, security holes, and degraded performance, but I have so far been explicitly denied permission to fix anything in it. In addition, it is so tightly coupled to equally bad code that it is impossible to test easily. But now the good news. If you can stand to look at it, this code will pay your mortgage, and the mortgages of 20 other people, because your bosses have more money than brains. /
I can agree with the seeming intention of the OP, but the analogy of adding labels to wires in an electrical box is problematic. How does having blank labels on wires equate to poor commenting?
Good or bad, a comment says something about the code it's commenting (even if the code is self explanatory). A blank label says nothing about the wire.
The better analogy might be having labels on wires that state the color of the wires -- red, blue, green, etc.
To author, the constructor is not a function it's a method.
I agree with useless comments but don't agree with blank 'constructor' method doc blocks that just say constructor as a filler.
Since most of the methods will have params/returns and better description than a simple constructor, leaving constructor without any doc-block is kind of counter productive and silly.
Or, while deep in thought, someone taps out a bit of redundant commentary on a line or two of their code...
Or someone needs a bit of natural language to provide an anchor in their code.
The important thing here, I think we can all agree, is that we are smarter than that person.