I saw someone quip (on twitter, I think) many years ago something like:
"A junior engineer writes comments that explain what the code does. A mid-level engineer writes comments that explain why the code does what it does. A senior engineer writes comments that explain why the code isn't written in another way."
(except punchier, of course. I'm not doing the quip justice here)
> writes comments that explain why the code isn't written in another way."
Exactly! I have written code that required comments five times as long as the code itself to defend the code against well meaning refactoring by people who did not understand the code, the domain, or the care needed to handle large dynamic ranges.
I have also written substantial functions with no comments at all because it was possible and practical to name the function and all the variables so that the meaning was clear.
I do all of the above. Summary comments are incredibly helpful and have been validated by empirical research. Too bad many have drunk deeply from the Clean Code koolaid and can’t be saved.
I got some flak at a prior job for saying I had some quibbles with clean code (a few years after I had read it), and I'm glad this opinion is more popular today. There's so much cargo culting hype with "best practices" and style, I hate it. Same with how overly dogmatic people were with OOP paradigms when it came out (remember using anonymous interfaces to pass a function around in java?). Same with the functional backlash to that.
It's fun and enlightening to go ham on any particular style/framework/philosophy, but actually living by dogma in prod gets kinda dangerous and imo is counter to the role of a senior+ engineer
Yes I write comments like a maniac. Long doc strings that are informally written. It’s more important for me to say what I need someone else (or future me) to know about a function and its context than it is for me to have some beautiful, sterile 300-line autogenerated soulless docstrings.
This 'empirical research' is highly doubtful. The first question to ask is what the code with summary comments looked like. While summary comments can sometimes be helpful, this is mostly the case in functions that are relatively long. A question that always arises in that case is whether it is a good idea to split them instead of commenting.
We could have the best of both worlds if comments could be easily hidden, or better yet, just additional meta-data on rich text code. But nope, we can't get away from ascii.
Junior programmers tend to either document nothing, or document everything. With experience you realise that you just want to document the unusual stuff, and as you get more experienced, you realise there is less and less unusual stuff, so the amount of comments drop down.
So, less comments wins out, but faced with a code base without comments you have to inspect it to tell the difference between a beautifully crafted piece of brilliance or a totally flaky codebase written by a bunch of newbie hacks.
> and as you get more experienced, you realise there is less and less unusual stuff, so the amount of comments drop down.
This is a common experience when I use a new language or framework. At the start I comment a lot of things because I think it's useful for future me, but as I learn more I realize that many of the comments are redundant so I end up removing them.
You have to consider who the comments are for. Senior engineers comments are more useful for senior engineers, but the junior comments will be more useful for junior engineers.
There's also the comments that tell you why the code does something obviously stupid but needs to continue replicating this stupid behavior because something else depends on it behaving this way.
That sounds like "explain[ing] why the code isn't written in another way" where the other way is "the way you are right now thinking it should be as you read this: the way that isn't obviously stupid".
> A senior engineer writes comments that explain why the code isn't written in another way.
And C-level engineers write a comment "X hours have been wasted on refactoring this code. Should you decide following the example of your priors, please increment this counter."
Sometimes, even what appears to be an utter hack job actually is the best you're gonna get.
I think of comments as an apology to the engineer reading the code.
I'm apologising because the code isn't obvious, or the language not sufficiently expressive, or the good-idea-at-the-time no longer is. Ideally I wouldn't need to write many comments, but I often find myself sorry things are not simpler.
In the end a comment should be like a shortcut that allows people to understand your code faster or a reminder why certain choices were made.
You are right in spirit to say sorry when the code cannot be self-explainatory, but consider that sometimes even if the code is self explainatory, comments can help your reader to see the grand picture faster or to avoid interpersonal ambiguity by allowing you to use two different ways of phrasing a thing.
I find that purpose of comments is to give context to the written code. Sometimes the context explains what the code does, and more often it explains why, but the best comments gives me the reader an insight so that I can have a intuitive feeling for what the author are writing.
I resonate with that example. It's usually about a piece of code that didn't turn out the way you wanted to due to an issue. If there's a literal github issue or source I can link, I'll include the URL in case someone checks later and it's no longer a blocker.
Somethings I include brief explanations or links to a particular piece of hard-to-find documentation.
> A senior engineer writes comments that explain why the code isn't written in another way
I suggest providing that sort of high-level decision information in a separate design document. This sort of documentation is written before the code and is presented/discussed with management and peers.
That is how it was done at a couple of companies I worked at and it was very effective. Naturally, this was done at the feature level, not on a function to function basis.
Then you end up with a design document that corresponds to the code as it existed conceptually before v1 of that code was even written. By the time v1 is written, the design doc will be slightly out of date; by the time the code reaches v3, the document is more than 2 versions out of date.
The nice thing about comments is that they're in the code. You can't update the code without at least looking at them; that's more visibilty than you'll get from anything else.
That still needs discipline though - or you end up with N half-finished Confluence pages describing the intention behind the design, all of which are now out of date (and naturally in completely different places). The best way I've seen to keep track of changing things is to have the design linked to the ticket somehow (and if it's a link, then that needs to be a permalink to something that will not go away in a year's time).
I really have to push back against this "design document" stuff. Unless you're writing some sort of uber-complicated, mission-guidance-systems-level code with multiple standards and audit compliance and and and, then you don't this.
Alternatively, if your org or reach for this feature is so large that you need to communicate and decide its internals with a lot of people and as such require something like a design document, then you've already failed and you have way too-many cooks in your kitchen. Design by committee is always doomed to failure.
Thirdly... if you need a design document to communicate your feature to "management" then that means you don't have autonomy to design this feature as an expert, and again, you have too many "fingers" in your pie.
Does this mean you should go into a basement and design your feature like a hermit? No, but a design document shouldn't be your answer, it should be a better team and process around you, as well as a clear business specification.
I understood that to mean "I've tried doing it x way and it didn't work because y." rather than the functional part. At that point, why not keep the documentation together with the code?
I comment everything that I think would be useful for me when revisiting the code a year later. Usually "why" and "why not". Sometimes a short "what" when the code is complex and it's nice to see the sequence more clearly.
What's not so useful: mandatory comments. A public API should be thoroughly documented, but some shops insist on writing comments for every function in the code, even private ones and even if its purpose is so obvious that the comment just rephrases its name. This practice is not only a waste of time, but also insensitizes you about comments and teach you to ignore them.
Other wasteful comments are added by some tools. I hate the one that marks every loop wiht a //for or //try comment.
For some reason a lot of syntax highlighting color schemes de-emphasize comments, making them low contrast, which is probably because a lot of mandatory / generated comments are low information. Get rid of mandatory and generated comments, and change your color scheme to make them a bright neon colour instead (on a dark theme) to draw the attention, because IF something is commented then it's important.
I disagree with this. Comments are important but not every time you're in that part of the code. You might already know from just the code what's going on, or have already checked out the comments. There's no value to them always being emphasized. That would be like reading all NPC dialogs every time in an RPG.
> I comment everything that I think would be useful for me when revisiting the code a year later.
Do you code solo or do you work with a team? If so, how large is the largest team you've worked with?
I used to be a dogmatic "all comments are code smells" person and, to a large degree I still am. But working on a very (and I mean VERY) large code-base that is actively developed and maintained by hundreds of other software developers, I have relaxed my position slightly into the "if you need to do something weird, explain why" ... because a large legacy system that lives in a business environment of tight deadlines means that there are often weird things that need to be done to keep things moving at a pace that the business is willing to pay for.
Anyway, one of the many reasons that I argue AGAINST code comments is that the comments become part of the code and therefore require maintenance. But few people read comments unless they are stuck trying to understand something. This "psychological invisibility" is even enforced by the fact that most code editors will grey out comments in order to make them less distracting.
And therefore, comments can easily become outdated.
So I'm curious about your situation. Since you say that you like to give yourself useful context for "future you", what context does this process serve? Do you find it useful when working on a shared codebase with lots of other developers? Or is it something that only works well when there are few developers touching the code?
> And therefore, comments can easily become outdated.
I am firmly of the opinion that keeping the comments up to date is part of the job of the developer. And if they're not doing it, they're not doing their job. It's no different than taking the time to write code that does the right thing, expresses the intent of what it's trying to do, etc. And, when code is peer reviewed, not including/updating comments in places where they are important should be a reason to send the code back to the developer.
I feel the same way about automated testing. They're both (testing and comments) way to make our code better; easier to understand, easier to maintain, more likely to be correct, etc.
I think color schemes that make comments nearly invisible are just bad. Visual Studio's default color schemes have it right. Comments are not treated as lesser than anything else.
As long as they aren't being placed every couple of lines they shouldn't really be a nuisance when reading through code.
And to me not updating the comments is the same as not updating the name of a variable when its purpose changes. The compiler doesn't care that you didn't update the name, but people reading the code do.
Also when it comes to "future you", you basically should think of yourself in the future as a different person. Because unless you are constantly working with the same bits of code, you will forget details and possibly even the high-level.
Yes, completely agree. Also, too many comments make it difficult to see what is in a class/function. If the comments make a class/function that would otherwise fit on one screen no longer fit on one screen there is a readability cost to this.
I wish they would put the comments before the function name in python, as otherwise the useful code is separated by useless verbiage. I also wish comments would include examples of the shape and dtype of inputs and outputs.
Collapsing/hiding comments should be a required feature in editors.
In Leo[1], you can make nodes out of them and just hide them. If Emacs weren't so good, I'd be using Leo. Similar power when it comes to extensibility, but extended via Python, not elisp.
Related anecdote: yesterday I was on a code portion of a personal project with a "Is this really useful?" comment on a line that seemed it could easily be removed. I tried to use the newer and cleaner class instead and the particular old way was indeed needed. So I appended a "=> yes!" to the existing comment as well. I'm glad my former self documented the interrogation.
At work, especially on bugfix, I often write a one or two lines comment with the ticket issue number over a non-obvious change.
It was pretty common say 25 years ago when you would be developing in a terminal. When you were limited in the number of lines displayed, it sometimes made it easier to follow the code when functions and control structures were large.
I know I had coworkers using brief configured to do that.
I think the favourite type of comment I've ever left in my code follows this template:
DEAR MAINTAINER:
This code is the way it is because of <reasons go here>.
Once you are done trying to 'fix' this, and have realised what a terrible
mistake that was, please increment the counter as a warning to the next
person:
total_hours_wasted_here = n
I'm not the original author, but have gratefully used it once or twice, and been amused when there was a single line commit incrementing the counter.
I one time wrote this fairly elaborate SQL generation thing that required pretty liberal use of recursion in order to fulfill all the requirements. It ended up being a lot of mutual recursion and the code was admittedly kind of messy but it was a necessary evil to do everything asked of me.
A more senior engineer ended up taking over the codebase, "fixed" all my code to be this iterative thing, made a point to try and lecture me about why recursion is bad in an email, only for his code to not actually do everything required and him reinventing effectively everything I did with recursion.
In fairness, he did actually apologize to me for some of the comments he made, but if I had thought about putting this comment on the top maybe we could have avoided the whole thing.
I agree that the title is ambiguous - it's what piqued my interest to read the article in the first place. Personally I lean toward fewer comments overall - perhaps to a fault - but explanatory comments as shown in the article are absolutely valuable. It's a good reminder to explain the whys and the why nots.
This especially applies to your own code that you write and still have to maintain 5, 10, 15 years later. Just the other day I was reviewing a coworker's new code and thought "why choose to do it this way?" when the reason was 10 lines up where I did it the same way, 8 years ago. She was following the cardinal rule of maintenance - make the code look like the existing code.
This is so undervalued when maintaining an older codebase. Please, for the sanity of those who come after you - make the code look like the existing code.
"Please, for the sanity of those who come after you - make the code look like the existing code."
I think it's a great rule of thumb... but there are exceptions.
For example, Funnily enough I was reviewing some code just today written by someone else and that I'm going to be asked to expand on or maintain. It looks like this:
var example1 = Object;
var example2 = Object;
var example3 = Object;
...
var example147 = Object;
And then later there are corresponding variables assigned to different objects which are:
var tempExample1 = <some object instantiation>;
var tempExample2 = <some object instantiation>;
var tempExample3 = <some object instantiation>;
...
var tempExample147 = <some object instantiation>;
And this goes on and on. It's real special once we get into the real business logic. (and to be clear... "example1" are the actual names, I'm not just obfuscating for this comment.)
The reason it looks like this is because the original developer copied the examples from the developer technical documentation for what they were doing verbatim; this documentation only had one variable so the numbering was the way to get multiple variables. Knowing this system, they didn't have to do that, they could have very easily assigned meaningful names for all of this. (To be fair, the original developer isn't a developer but a consultant business analysist saying, "Oh yeah, I can do that!" to the client.... billing all the way).
I can tell you with great certainty and righteousness: I'm not going to make my code look like the existing code. I may well do some refactoring to make the existing code vaguely scrutable.
I appreciate that what I'm describing is an extreme case and not really what you or parent comments really were addressing. I just stop to point out that what you describe is a rule of thumb... a good one... but one nonetheless. And, as an absolute rule of thumb about rules of thumb, there are no absolute rules of thumb. Ultimately, experience and judgement do matter when approaching the development of new code or decades old code.
Unless of course you work in a wild-west codebase where you can basically tell who wrote what code because everyone has a distinct style and they never converge. ugh
This is just a special case of a broader, more general advice that I follow:
Comment on whatever would be surprising when you read the code.
When I write code, a voice in the back of my head constantly asks “will I understand this code later?”. (People who just instinctively answer ‘yes’ every time are arrogant and often wrong.) Whenever the answer is ‘not sure’, the next obvious question is “why not?”. Answering that question leads you directly to what you need to write in your comment.
Sometimes the answer is “because the reader of the code might wonder why I didn't write it another way”, and that's the special case this article covers. But sometimes the answer is “because it's not obvious how it works or why it's correct” and that clearly requires a different type of comment.
As an addition, if you first try to write the code one way, and then it doesn't work and you need a second approach, that's a really good indication that you want some kind of comment there. You were surprised while writing it, so if you'll forget that surprise in a year, you'll be surprised by reading it too.
My driving principle in the same vein is "where do I have to look when/if this doesn't behave as expected?" - if the answer is not in the docs (wiki -> package/module -> file -> class -> function / method) or is otherwise > 10 lines away, it gets an inline comment (or the docs are updated). Usually this happens when chopping up strings or during intermediate navigation steps over an odd data structure.
> I see more people arguing that whys do not belong in comments either, that they can be embedded into LongFunctionNames or the names of test cases. Virtually all "self-documenting" codebases add documentation through the addition of identifiers.
Identifiers can go a _long_ way, but not _all_ the way. I personally am a fan of requiring documentation on any public methods or variables/fields/parameters (using jsdocs/xmldoc/etc). Having a good name for the method is important, but having to write a quick blurb about what it does helps to make it even clearer, and more importantly, points out obvious flaws:
* Often even the first sentence will cause you to realize there's a better name for the method
* If you start using "and" in the description, it is a good indication that the method does too much and can be broken down in a more logical way
People often think properties are so clear they don't need docs, then write things like:
/** The API key */
string ApiKey;
But there's so much missing: where does this key come from? Is this only internal or is it passed from/to external systems? Is this required, and can it be null or empty? Is there a maximum? What happens if a bad value (whatever that is) is used? Is there a spot in code or other docs where I could read more (or all these questions are already answered)?
This is stuff that as the original author of the code you know and can write in a minute or two, but as a newcomer -- whether modifying it, using it, or just parachuted in to fix a bug years later -- could take _hours_ to figure out.
I often write comments like this when I can predict what an overly nitpicky reviewer will say in a code review - "I didn't do X because Y" hoping to save some annoying back and forth about it.
They have value in the code because they save time when someone has to deal with that code a couple of years later. Certainly the explanation could be in the code reviews or the commit message, but it's easiest if it is right there.
This is a great idea for a lot of things! Sometimes I will write a loop I know is slow as hell but works for now, and it would be cool to use a timer and do, "if this takes more than X seconds, log a warning." I mean, the perfect logging and observability should theoretically time all the components of your app, log debug information often, and etc., but who really uses a perfect system like that? I think it's more important to make specific effort to log in areas where performance might suck later or where you didn't have time to optimize or do exactly what you wanted to do.
Your comment is super obvious, in hindsight, but I never thought to do something like this, usually at past places of work we've just agreed to make a comment on things we need to reconsider later and hopefully we remember about that comment when things go downhill!
I'd caution that it's a very "80/20" thing, since the cost/complexity of detecting all "unusual" cases can easily become not-worth-it.
For example, if the slowness of the method depends on non-trivial aspects of the input, or if the performance problem in production comes from someone calling your method too many times on (individually) reasonable chunks of data.
I find that a lot of well-meaning tools (e.g. bazel) regard non-error output as noise to be hidden. They'll often route any messages like this to the nearest wastebin they can find, which makes logging incredibly unreliable as a means of communicating constraints in some domains.
I'm thinking the log message is something you wouldn't want to trigger in production anyway, unless you're pretty confident that it won't lead to a ton of spam on the day that inputs rise over the threshold.
Using a debug log-level helps prevent that problem from occurring in production, while still making it visible to developers that have more logging enabled in their dev/test environments.
"A junior engineer writes comments that explain what the code does. A mid-level engineer writes comments that explain why the code does what it does. A senior engineer writes comments that explain why the code isn't written in another way."
(except punchier, of course. I'm not doing the quip justice here)
Exactly! I have written code that required comments five times as long as the code itself to defend the code against well meaning refactoring by people who did not understand the code, the domain, or the care needed to handle large dynamic ranges.
I have also written substantial functions with no comments at all because it was possible and practical to name the function and all the variables so that the meaning was clear.
It's fun and enlightening to go ham on any particular style/framework/philosophy, but actually living by dogma in prod gets kinda dangerous and imo is counter to the role of a senior+ engineer
I have regretted following that lesson ever since.
So, less comments wins out, but faced with a code base without comments you have to inspect it to tell the difference between a beautifully crafted piece of brilliance or a totally flaky codebase written by a bunch of newbie hacks.
This is a common experience when I use a new language or framework. At the start I comment a lot of things because I think it's useful for future me, but as I learn more I realize that many of the comments are redundant so I end up removing them.
If it's not answering why or at least providing a very concise how to very verbose code, then it's just adding noise
And C-level engineers write a comment "X hours have been wasted on refactoring this code. Should you decide following the example of your priors, please increment this counter."
Sometimes, even what appears to be an utter hack job actually is the best you're gonna get.
I'm apologising because the code isn't obvious, or the language not sufficiently expressive, or the good-idea-at-the-time no longer is. Ideally I wouldn't need to write many comments, but I often find myself sorry things are not simpler.
You are right in spirit to say sorry when the code cannot be self-explainatory, but consider that sometimes even if the code is self explainatory, comments can help your reader to see the grand picture faster or to avoid interpersonal ambiguity by allowing you to use two different ways of phrasing a thing.
Somethings I include brief explanations or links to a particular piece of hard-to-find documentation.
I suggest providing that sort of high-level decision information in a separate design document. This sort of documentation is written before the code and is presented/discussed with management and peers.
That is how it was done at a couple of companies I worked at and it was very effective. Naturally, this was done at the feature level, not on a function to function basis.
The nice thing about comments is that they're in the code. You can't update the code without at least looking at them; that's more visibilty than you'll get from anything else.
Alternatively, if your org or reach for this feature is so large that you need to communicate and decide its internals with a lot of people and as such require something like a design document, then you've already failed and you have way too-many cooks in your kitchen. Design by committee is always doomed to failure.
Thirdly... if you need a design document to communicate your feature to "management" then that means you don't have autonomy to design this feature as an expert, and again, you have too many "fingers" in your pie.
Does this mean you should go into a basement and design your feature like a hermit? No, but a design document shouldn't be your answer, it should be a better team and process around you, as well as a clear business specification.
What's not so useful: mandatory comments. A public API should be thoroughly documented, but some shops insist on writing comments for every function in the code, even private ones and even if its purpose is so obvious that the comment just rephrases its name. This practice is not only a waste of time, but also insensitizes you about comments and teach you to ignore them.
Other wasteful comments are added by some tools. I hate the one that marks every loop wiht a //for or //try comment.
Do you code solo or do you work with a team? If so, how large is the largest team you've worked with?
I used to be a dogmatic "all comments are code smells" person and, to a large degree I still am. But working on a very (and I mean VERY) large code-base that is actively developed and maintained by hundreds of other software developers, I have relaxed my position slightly into the "if you need to do something weird, explain why" ... because a large legacy system that lives in a business environment of tight deadlines means that there are often weird things that need to be done to keep things moving at a pace that the business is willing to pay for.
Anyway, one of the many reasons that I argue AGAINST code comments is that the comments become part of the code and therefore require maintenance. But few people read comments unless they are stuck trying to understand something. This "psychological invisibility" is even enforced by the fact that most code editors will grey out comments in order to make them less distracting.
And therefore, comments can easily become outdated.
So I'm curious about your situation. Since you say that you like to give yourself useful context for "future you", what context does this process serve? Do you find it useful when working on a shared codebase with lots of other developers? Or is it something that only works well when there are few developers touching the code?
I am firmly of the opinion that keeping the comments up to date is part of the job of the developer. And if they're not doing it, they're not doing their job. It's no different than taking the time to write code that does the right thing, expresses the intent of what it's trying to do, etc. And, when code is peer reviewed, not including/updating comments in places where they are important should be a reason to send the code back to the developer.
I feel the same way about automated testing. They're both (testing and comments) way to make our code better; easier to understand, easier to maintain, more likely to be correct, etc.
As long as they aren't being placed every couple of lines they shouldn't really be a nuisance when reading through code.
And to me not updating the comments is the same as not updating the name of a variable when its purpose changes. The compiler doesn't care that you didn't update the name, but people reading the code do.
Also when it comes to "future you", you basically should think of yourself in the future as a different person. Because unless you are constantly working with the same bits of code, you will forget details and possibly even the high-level.
In Leo[1], you can make nodes out of them and just hide them. If Emacs weren't so good, I'd be using Leo. Similar power when it comes to extensibility, but extended via Python, not elisp.
[1] https://leo-editor.github.io/leo-editor/
Related anecdote: yesterday I was on a code portion of a personal project with a "Is this really useful?" comment on a line that seemed it could easily be removed. I tried to use the newer and cleaner class instead and the particular old way was indeed needed. So I appended a "=> yes!" to the existing comment as well. I'm glad my former self documented the interrogation.
At work, especially on bugfix, I often write a one or two lines comment with the ticket issue number over a non-obvious change.
You will read it in 3 months and cry in despair "But why, my past self, why is it needed?!" :-)
Oh god, that's horrible, what kind of tool does that?!
I know I had coworkers using brief configured to do that.
I one time wrote this fairly elaborate SQL generation thing that required pretty liberal use of recursion in order to fulfill all the requirements. It ended up being a lot of mutual recursion and the code was admittedly kind of messy but it was a necessary evil to do everything asked of me.
A more senior engineer ended up taking over the codebase, "fixed" all my code to be this iterative thing, made a point to try and lecture me about why recursion is bad in an email, only for his code to not actually do everything required and him reinventing effectively everything I did with recursion.
In fairness, he did actually apologize to me for some of the comments he made, but if I had thought about putting this comment on the top maybe we could have avoided the whole thing.
It's a problem if you're overflowing the stack, of course, but otherwise…
This especially applies to your own code that you write and still have to maintain 5, 10, 15 years later. Just the other day I was reviewing a coworker's new code and thought "why choose to do it this way?" when the reason was 10 lines up where I did it the same way, 8 years ago. She was following the cardinal rule of maintenance - make the code look like the existing code.
This is so undervalued when maintaining an older codebase. Please, for the sanity of those who come after you - make the code look like the existing code.
I think it's a great rule of thumb... but there are exceptions.
For example, Funnily enough I was reviewing some code just today written by someone else and that I'm going to be asked to expand on or maintain. It looks like this:
And then later there are corresponding variables assigned to different objects which are: And this goes on and on. It's real special once we get into the real business logic. (and to be clear... "example1" are the actual names, I'm not just obfuscating for this comment.)The reason it looks like this is because the original developer copied the examples from the developer technical documentation for what they were doing verbatim; this documentation only had one variable so the numbering was the way to get multiple variables. Knowing this system, they didn't have to do that, they could have very easily assigned meaningful names for all of this. (To be fair, the original developer isn't a developer but a consultant business analysist saying, "Oh yeah, I can do that!" to the client.... billing all the way).
I can tell you with great certainty and righteousness: I'm not going to make my code look like the existing code. I may well do some refactoring to make the existing code vaguely scrutable.
I appreciate that what I'm describing is an extreme case and not really what you or parent comments really were addressing. I just stop to point out that what you describe is a rule of thumb... a good one... but one nonetheless. And, as an absolute rule of thumb about rules of thumb, there are no absolute rules of thumb. Ultimately, experience and judgement do matter when approaching the development of new code or decades old code.
Comment on whatever would be surprising when you read the code.
When I write code, a voice in the back of my head constantly asks “will I understand this code later?”. (People who just instinctively answer ‘yes’ every time are arrogant and often wrong.) Whenever the answer is ‘not sure’, the next obvious question is “why not?”. Answering that question leads you directly to what you need to write in your comment.
Sometimes the answer is “because the reader of the code might wonder why I didn't write it another way”, and that's the special case this article covers. But sometimes the answer is “because it's not obvious how it works or why it's correct” and that clearly requires a different type of comment.
My driving principle in the same vein is "where do I have to look when/if this doesn't behave as expected?" - if the answer is not in the docs (wiki -> package/module -> file -> class -> function / method) or is otherwise > 10 lines away, it gets an inline comment (or the docs are updated). Usually this happens when chopping up strings or during intermediate navigation steps over an odd data structure.
Identifiers can go a _long_ way, but not _all_ the way. I personally am a fan of requiring documentation on any public methods or variables/fields/parameters (using jsdocs/xmldoc/etc). Having a good name for the method is important, but having to write a quick blurb about what it does helps to make it even clearer, and more importantly, points out obvious flaws:
* Often even the first sentence will cause you to realize there's a better name for the method
* If you start using "and" in the description, it is a good indication that the method does too much and can be broken down in a more logical way
People often think properties are so clear they don't need docs, then write things like:
But there's so much missing: where does this key come from? Is this only internal or is it passed from/to external systems? Is this required, and can it be null or empty? Is there a maximum? What happens if a bad value (whatever that is) is used? Is there a spot in code or other docs where I could read more (or all these questions are already answered)?This is stuff that as the original author of the code you know and can write in a minute or two, but as a newcomer -- whether modifying it, using it, or just parachuted in to fix a bug years later -- could take _hours_ to figure out.
Another twist on this is to put in a debug logging statement which triggers when the inputs are much larger than the original design constraints.
It's roughly the same message to a future-developer, but they might find it much sooner, short-circuiting even more diagnostic and debugging time.
Your comment is super obvious, in hindsight, but I never thought to do something like this, usually at past places of work we've just agreed to make a comment on things we need to reconsider later and hopefully we remember about that comment when things go downhill!
For example, if the slowness of the method depends on non-trivial aspects of the input, or if the performance problem in production comes from someone calling your method too many times on (individually) reasonable chunks of data.
The "et" in "etc" means "and", so you have that already.
Using a debug log-level helps prevent that problem from occurring in production, while still making it visible to developers that have more logging enabled in their dev/test environments.