I worked with some Rails folks a while back who were utterly convinced that comments were to be avoided because it meant your code was not clear.
I agree that comments explaining 'what' is happening are mostly useless. Write clearer code. But 'why' comments are good. Most things can be coded up different ways. Tell me why you chose this way. Tell me about constraints that might not be immediately obvious. Let me know if indeed, it could be cleaner, but you were in a hurry (this is a thing that happens in the real world), or if it's that way for a specific reason.
Many people think their code is clear. The problem is it is clear often only for the author and sometimes for a limited time even for the author. If anyone else start to working with the code questions usually arise. And you can prepare comments for at least some of such questions.
In my practice I often see code where useful comments are missing and hours of research required to learn something author for sure knew. Code which has too much comments to me is an imaginary problem - I've seen it at most a couple times in my career and one of them was the code written by a junior developer in a style one can expect in a tutorial or a book. But usually people quickly learn to not add unnecessary comments (and eventually start adding too little of them).
This is true, but if you just get these same people to write more comments, they will also think their comments are clear when they're, in fact, not. I think anyone who is capable of writing clear comments is also equally capable of writing clear code.
If I was to suggest investing time in learning some skill, I would suggest learning how to make your code actually clear by getting the right people (with relevant domain expertise, but without experience with the code) to critique it for clarity rather than learning how to make your comments actually clear.
Why questions are best answered in architecture documentation, the code itself should be self explanatory (given the architecture documentation) for the most part with specific why comments carefully placed in places where it doesn't make sense to use the architecture documentation.
I've read code from various codebases from various companies, large and small. I very rarely see a comment which is genuinely both well placed and useful. From the bits of the linux kernel that I have worked on, I have generally seen pretty good why comments, although I think a lot of them could be shifted into architecture documentation.
All in all, when reading code, my default stance is to ignore comments unless I get lost reading the code, then I attempt to read the comments. It has been incredibly rare that I've found unclear code to have clear comments.
The problem with this argument is that it's implying that there is no such thing as clear code. Sure some people think their code is clear when it is not, but that shouldn't stop you from striving to write clearer code.
A long time ago, I had a tendency to write comments to explain code that could be simplified. Refactoring it usually made the comments redundant.
Comments are still very useful when the why is unclear.
I agree with you. It’s like having too much doc, or doc so outdated it’s harmful. These are fairy tails. I’d take too much doc or outdated doc any time of the day over no doc/comments.
Having worked with Rails folk for many years, they do have some weird strong opinions, this being one. The argument that comments shouldn't be made because they'll "become stale" is pretty lame IMO. It's either not a big deal or the end of the fucking world for some reason lol. Maintaining code is just... work. You just do it. That includes comments.
> Maintaining code is just... work. You just do it.
There is an argument about reducing the amount of work.
On the staleness of comments, it's a real thing. In particular, on comments explaining design decisions, they will often touch on aspects of the system that are outside of the specific method they are attached to, and nobody will go back to them to rewrite all that prose.
We had a project with a ton of documentation written in the first 2 years, and as engineer count grew, these comments just disappeared as again and again they were causing misunderstandings, and actual documentation was already written in the internal wiki as each refactorings and new features were discussed and designed.
It's not just a rails thing, and after a while people stop trusting comments altogether, which make updating them a chore more than anything.
Rails developers (myself included) are lazy by design, and thus eschew anything requiring redundant work. Most operate under the principle that "it was hard to write, it should be hard to read"
The 5 programming languages with the least amount of bugs are:
Haskell
Ada
Scala
Rust
*Drum roll please*
Ruby
Ruby is nothing like the other languages above in design, but that community has fantastic conventions around code clarity, code quality, testing, continuous integration, etc.
Comments are for things like, `Todos`, Noting a specific algorithm, maybe a link to a white paper, noting a violation of a convention for speed, security, or some other performance reason.
Comments are for things that are __impossible__ to tell from the code.
I wish I could get this point across to my team. They will happily write:
db.insert(record); // save the record to the database
But when they write some crazy off-the-wall code (that's usually because they didn't understand the proper way to do something) I have to check the logs to see who wrote it and ask them why.
Just the other day I was debugging an application that had a 6 second sleep at the end of the main() function. I just figured it was some dumb thing left in for debugging and deleted it, because there's no good reason to do that. The next day, the dev who put it in messaged me and said he put it there because the application was exiting before it had logged it's completion to our logging system. So I explained that the proper way to do this is to flush the log, not just hang the application for 6 seconds so that the last messages just happen to go through.
If there was a comment explaining why there was a 6 second sleep, I could have just fixed it and educated the developer without causing any grief.
Interesting paper, thanks for posting. The paper goes on to say:
> One should take care not to overestimate the impact of language on defects. While the observed relationships are statistically significant, the effects are quite small. Analysis of deviance reveals that language accounts for less than 1% of the total explained deviance
Where are Ada and Rust mentioned in that link? The top listed down to Ruby in that link by general failure seem to be: Scala, Perl, Clojure/PHP (tied), Haskell/Go (tied), TypeScript, Ruby.
The Ruby community has a very good culture of testing application and framework code, but in my experience is quite poor at properly specifying behaviour or writing truly robust code.
Many functions in the standard library behave subtly differently from there documentation or have behaviour that is not documented but depended on by applications, and I’ve certainly seen lots of concurrency bugs in both code and tests because the GVL makes it hard to provoke the worst case behaviour.
The unit tests are really useful for Ruby language implementations because they help give us confidence we’re replicating all the required behaviour, but from that point of view I wish the underlying things were better specified so those tests weren’t quite so necessary.
Don’t get me wrong. I love Ruby as a language and loved working on TruffleRuby, but I don’t think the community should be too smug about code quality and testing.
Agree with most of what you said, except on the __impossible__ part.
You can tell everything with code, given enough time and resources. Nothing is "impossible". But there's a point where you hit diminishing returns. It's about efficiency.
Other devs, or your future self, will have to time trying to build the same "castle in your head" as you did. Can a comment shorten that time? If a one-line comment saves 15 minutes of investigation in aggregate, that's a no-brainer. You should add it. Conversely, a line that says "add 5 to x" is just wasting everyone's time.
As a general rule, once I have finally understood a particularly hairy piece of code, I don't want to do it again in 6 months. I have even done ASCII diagrams in the comments explaining how a particularly hairy piece of code worked, when I hated it enough.
Comments are critical at creating beginners to the code base, something rarely the expert class think about accelerating.
For my code? I agree
Code for others to participate in? The simplest possible way for the greatest number of developers to understand as quickly as possible. Not about my best practice or preference but for the greater good.
Coding standards for the elite devs are only so effective at growing that growing quick enough.
The best comments I've seen go something like this:
# this is going to loop 4x and call foo_bar on the 4th time because when you calculate this number it needs the 4th time to calculate the difference from the sales tax. weird, I know, but the business has special rules about how taxes work in California
Shed a tear for how little our industry values conciseness, and then consider:
# Call foo_bar only on the 4th loop iteration to handle the weirdness of calculating taxes for California.
(I've just joined a company where everyone's constantly writing giant docs, and no one seems to grok the idea of a "living doc" that gets edited and refined. I think it's slowly making me allergic to verbosity.)
This is overly expository and could be much shorter. It also shows the programmer had no interested in actually understanding what their code was doing. The comment makes absolutely no sense whatsoever. "It needs the 4th time". What needs it? I absolutely guarantee you you do not need to loop 4 times to "calculate the difference from the sales tax". "Weird, I know" -- I guarantee you it's not weird if you actually understand anything about the calculation you're supposed to be implementing. This comment barely passes as an English sentence, much less someone who knows anything about taxes would ever say. This is such a great example of an absolutely terrible comment belying lazy, thoughtless programming.
I'm not sure I've seen all the "comment everything" advocates in this thread provide a single example of a good comment.
I worked at a late-stage Rails-based startup that had "dont write comments" as an engineering principle!
The python folks before me used this to avoid writing docstrings for modules/classes/methods, so code could only be understood by reading the entirety of it. Throw in some deep class hierarchies and it was very hard to onboard there.
TBF, deep class hierarchies will hard to onboard whatever you do.
If you're relying on comments to help with that, you'll have to share the same mindset as the person writing the comments, except there's probably multiple years of understanding gap between you and them.
I went from a rails developer to iOS; Apple and iOS developers in general are pretty good at comments, and I now value them more. Comments at the API level mean I don’t have to go diving however deep to find out what a method does. If they’re really good, they can also be used to distinguish the specification from what’s actually happening when there are bugs.
In the simplest cases, sure you don’t need to write “getName returns a user’s first name and last name separated by a space character,” but I’m guessing the method requestPurchase will have a lot of nuance and I hope it’s documented (yes, even the “what happens”)
I'm at the point where I want to see docs on any non-private properties/fields, methods, parameters, classes, etc.
I think there's nearly always value to be added:
* Explaining required fields, if null/blank/0 is allowed, where an ID comes from (db vs app-generated), if string values are formatted or require formatting (credit card, phone numbers), max length or other restrictions
* If a class/method is thread-safe or not (when not obvious and misuse is dangerous), error conditions, timeouts.
* Any external or indirect dependencies for use (config, packages, etc)
* Links to other docs/wikis or tickets is hugely useful.
When you're writing/working on the code you already know all this stuff, and it takes only a couple minutes to document. When someone else (or you, 6 months later) comes along to use or modify it, figuring everything out from scratch can take hours -- or worse, bug reports from QA or customers. Docs shave this down to seconds and directly avoid bugs.
The other huge benefit I often experience is through trying to write docs for something I realize there's a better, more obvious name that makes it easier to use and requires less explanation (less docs). This happens on easily 5-10% of the things I write docs for.
A lot of code is WTF enough that a comment explaining what it is attempting to do might be helpful. The real world is full of absolutely shit code, but it still earns the company money.
I always find the 'self documenting code' concept to be a bit misleading. Because intuitively the idea is that you'd be able to read the actual code and understand what it does, without having to rely on potentially dated or otherwise invalid comments. But in reality we're not really talking about code, but about things like function names - which suffer all of the potential woes as comments, even if to a lesser degree in practice.
For instance, this [1] is a clean implementation of quicksort, which I offer as an example of any non-trivial algorithm. You can't really write it in a way that would make the idea clear to anybody who wasn't already familiar with the algorithm, because the idea itself is non-trivial. So the way intent is made clear and documented is by making sure the function is called QuickSort. And that is indeed 'self documenting', but really in a way that has nothing to do with the code itself.
I worked with some Rails folks a while back who
were utterly convinced that comments were to be
avoided because it meant your code was not clear.
One of the few things that makes me want to reach a management position is my burning desire to alter this widespread, toxic, and absolutely bizarre belief.
As an IC, even a senior IC, it's difficult to effect this change.
There were similar discussions in the PHP community, with arguments that were sensible and rather stupid on both sides of the argument.
I'm honestly a bit torn by it. Yes, your code absolutely should be written in a way that keeps it tidy and easy to understand. But you've always got complex situations which arent always going to be easy or obvious for someone fresh to the codebase.
There should be a good middle ground. I dont need to see comments saying "this is a loop that gets all the users". If its got a variables called users, calling a methog called "getUsers()" then thats pretty damn obvious whats happening.
However if you then go on to do something weird like loop over each user and calculate a score based on the number of posts they've made then theres undoubtedly going to be some logic in there that even just a simple one sentence comment will help someone understand.
It's a fine line, and getting it right is a skill in itself.
Right, it's about the "why". For instance with your loop that calculates a score, I might want to know why it wasn't done in SQL. Or if it could be, but whoever was writing it just wanted to hurry along. Is there a TODO to get rid of an N+1 problem associated with it?
I tend to be the one who comments code the most on my team. I’ve learned how often and what to comment via my side projects. I tend to stop and go with them, sometimes going a year or two before picking them back up again. You figure out what you wish you’d left yourself as comments.
Rails guy turned rustacean here. If I have a piece of code that looks gnarly, I'll write a comment above it explaining what it does. Elegance != readability always. This can often happen with complicated map/filter/etc chains (both in ruby and in rust!) that are compact but are complicated enough that your eyes glaze over when you read them. Anything eye-glaze-over-ey is probably worth a comment in my opinion.
Other times to comment include when there is some sort of dirty hack, TODO annotations, etc.
The why should be clearly explained in the Jira ticket associated with the commit.
Comments are useful only to explain non obvious corner cases and invariant.
You can write whatever you want in your Jira instead of polluting the code for everyone.
> I worked with some Rails folks a while back who were utterly convinced that comments were to be avoided because it meant your code was not clear.
What this means is that if your Ruby code is clear it should read like natural language. Injecting subtitles into the middle of the expression
# I decided to phrase it this way because I was in a rush and it was the first thing that came out. With more time I could no doubt articulate this in a more communicative way, but for the sake of a random post on the internet I'm not terribly worried.
interrupts the flow when one is reading the code, which makes for a much less pleasant experience. Ruby may not be the only language that is like this, but it is relatively unique in this regard. Comments in other languages don't seem to cause the same interruption.
# That's all I've got. Time to clean up.
I'm not sure this means don't provide additional information to future readers that may be beneficial, but be discriminating in where you put it. Or do whatever you want. Who cares what someone else thinks?
> Because the culture of many development organizations undervalues comments, team leads (and managers) allow comments to get out of sync with the code—thereby increasing technical debt instead of reducing it.
Comment bit rot is inevitable, because comments don’t compile and can’t be tested. The only way to keep them in sync is by hand, which takes a lot of time and energy and is far from perfect. Of course,
> The first problem is that most developers are under great time pressure and don’t have the time to make the code so utterly clear that it requires no further comment.
So they don’t have time to write the code clearly, but they somehow magically have time to read and review all the comments and to keep them in sync with the code? And the reviewers too?
“If only developers worked harder…”. It’s nonsense.
Comments are great, they have an important place in software engineering, and I always regret when I forget to write some in a file or class. But they are not a silver bullet, and must be treated with suspicion, because there is no way to prove if they actually describe what’s going on. And that’s the same reason that they are hard to keep in sync.
This, I prefer an inconsistent comment that can still shred light on some code than no comment at all. Code also becomes obsolete and no comment just makes it worse.
But then are you looking at the git context of all the comments you come across ?
I'd argue you could do the same on methods and class you want more context on, removing the need for the majority of comments, and most companies will have the associated ticket numbers or design discussions attached to the MR/PR.
I think there will still be rare situations where comments are absolutely needed, but in these rare cases they should probably refer to an external resource (a bug report for a specific library, an incident that required a specific fix, etc.)
> So they don’t have time to write the code clearly, but they somehow magically have time to read and review all the comments and to keep them in sync with the code? And the reviewers too?
Exactly. I used to love writing comments, but they have become for me a last resort. I'd rather put the information I'm trying to convey almost anywhere else. Variable names, method names, improved interfaces, better object relationships, doc strings, test code, test names, commit comments, or my colleagues' heads.
Having information in your colleagues heads only is exactly how you create organisational friction to begin with (now newcomers are likely required to ask questions to your team directly). Also over time this information gets completely lost (forgotten by people or when they leave the company).
Multiple languages and documentation tools disagree on "comments don't compile/test" fwiw. You definitely can do this, in any language (though some make it much easier than others).
Though I fully admit that automated tests cover nothing related to explanations / things that aren't inherently true or false.
Personally I've wanted a way to link code to comments, not just the reverse, so I can change code here and be notified that it affects comments over there, especially during review time (just show every related comment next to the change). It seems literally essential for reliable documentation, but I haven't yet seen it except maybe in WEB (the literate programming language) or similar.
> I fully admit that automated tests cover nothing related to explanations
but ... it's the explanations that are important.
I mean there are plenty of tools to check that a comment matches a function signature or otherwise describes the properties of a bit of code. But who needs that? At least in a strongly typed language, reproducing the signature or doing anything else that reflects existing code within a comment adds very little.
Anyway, I am not arguing against comments. I'm just arguing that they can't somehow magically reduce technical debt. Or that they have anything at all to do with technical debt. Or that the OP made any sense at all.
> Personally I've wanted a way to link code to comments, not just the reverse, so I can change code here and be notified that it affects comments over there,
If your code is separated from comments explaining it so much thag this isn't visibly obvious on review, there’s probabky a bigger problem than “I don’t have a way to link commebts to distant code and vice versa.”
If I've written a comment, and I have, it's because I have to move on, not because I think it's adding an extra layer of quality.
I don't want to write a comment, I'd rather write clean code that looks good, but when I run out of time to spend on a problem, and I don't think the code is clear enough, I think then it's acceptable to add a comment.
I just think too many devs have their egos wrapped up into their jobs, so hearing, "Commenting is failure!" evokes an emotional response. What these devs don't realize is you can make no mistakes and still "fail" to write clean code, and that's totally okay.
Uncle Bob is just saying that pulling out a comment before you've tried is premature. Try to avoid it first, if you have time to.
Exactly. A comment is the last step. I strive to write no comments, but if I feel that's the best option I will. In my opinion it is very rarely the best option.
More generally... my unwritten article is "Reducing developing bad beliefs about code by not listening to Uncle Bob".
He has been trying to say profound things for a long time now. He was super active in the XP community in early 2k onwards and he was nearly always saying things that I felt were a bit "off". i.e. there was a gem of an idea, but the idea was turned into some principle or rule that lacked nuance and context. Reality is, there isn't any fundamental rules/principles... just ideas, some ideas seem more universal than others, but these ideas are just a bunch of strategies you can use when approaching software development and depending on context they may or may not be good strategies.
In terms of commenting, some of this weird "wisdom" around commenting was fundamentally rooted in the idea you can't fix bad code with comments. People noticed that a lot of times where there was comments in "poor" code it actually was a spot where you could do some kind of refactoring to make the code clearer. Eventually this morphed into "If you need to comment your code you have failed" type sayings. However, there was plenty of people advocating commenting to explain things the code can't tell you, but too many were swayed by "commenting is failure to write good code" that they threw out some of the reason why people like to put comments in. Many in their first 10 years of coding really want guidelines and rules and principles and argue strongly for things they have found effective compared to how they approached coding previously. But these things you learn are almost never universal, even if you can see/argue how you could apply it to all kinds of things, other approaches might actually work better, or might work better in different contexts.
100% agree with this. I was religiously following clean code but never really saw benefits. Nowadays I start by making code work and only abstract/refactor if it feels right. And I don't know how to articulate "feels right" but what I can say is a lot of times, the resulting refactor is the opposite of what uncle bob recommends.
> he was nearly always saying things that I felt were a bit "off"
One of such things is "screaming architecture". It is a good idea in theory, but only if you already know what the architecture should be. Most new projects don't know what they need up front, and discovery happens over time. Screaming architecture is bad for this process. It inhibits it, requiring a ton of refactoring because of early assumptions. One thing that is known up front is entry points. (CLI, requests, tests, bg jobs). They're a lot more likely to stay around forever. Custom architecture should emerge underneath them. I guess we can call it whispering architecture.
If you can't organize your code into sections and chapters using the constructs provided by your programming language, for everyone's sake, get a better programming language. If you're not allowed to, get a better job. If you can't right now, then go ahead and use comments for that purpose, but I pity you.
As an aside, my first try is always to try to clarify the code itself if someone has a specific question, so the obvious answer is in the code. But if I'm unable to signal that in code, a comment will do just fine.
Comments are critical to long term project quality and consistency, but they're always going to rot until tooling starts taking them seriously.
For instance, it's great that code reviews have become standard practice at most organizations and for many projects, but the tooling for those reviews almost always rely on showing the few lines above and below a code diff. The reviewer has no convenient way of seeing how the changed code may conflict with any applicable comments unless the comments happen to be within those few nearby lines or the diff happens to include comment changes. Even then, the big picture is out of view and rot is still likely to seep in.
It would be nice if incoming developer-support AI could start tackling this, by surfacing impacted comments and even "linting" them for applicability and accuracy.
> It would be nice if incoming developer-support AI could start tackling this, by surfacing impacted comments and even "linting" them for applicability and accuracy.
That only applies to comments that address what the code is doing or how it does what the comment says. It does absolutely nothing for the most critical type of comments: the ones that say why the developer decided to do it a particular way. Maybe they tried it three other ways and this was the most efficient way. Maybe they chose this way because it matches up with a business requirement that things be done in a particular order (regardless of efficiency). Maybe it must be done that way for consistency with another part of the system that is only obvious from the comment.
It will be a long, long time before AI will be able to reasonably vet such comments for accuracy. Until then, comment your darn code!
Even better if the language supports scoping comments to particular code blocks, and comments can be made in markdown/mermaid (or equivalent) so you can diagram, link and TODO comments.
Documentation tooling should be able to make a good job of constructing a class/function DAG with scoped commentary. This is kind of a reversal of Literal documentation, but I suspect it may be more maintainable by teams.
Literal docs only seem to go in one direction, that is documentation->code, not the other way around. This I guess is more in-line with scientific hypotheses. Literal tests may be even more tricky as TDD doesn't gel well with Literal hypotheses.
I guess a Doc-driven dev process would be a novel approach here, and probably more usable than AI-supported systems. Copilot has been quite divisive on it's effectiveness.
DDD in that every eg. Class requires a comment and a test even if they are blank, to force at least a thought about them. Having a code manifest at the root of a repo can also be used to configure the envs the code runs in, and the integration tests that it needs to do both local and in-place.
Lastly, as mentioned elsewhere, logs are comments as well, and again would be well to be scoped in the language.
At the time we have AIs that can match up the meaning of comments and the meaning of code there won't be any need for developers any more. ;-)
The other thing I wanted to mention: People don't do code review in their IDEs? Really?
Modern languages with type inference are not fun to analyze without an IDE… Also you can't navigate to related code without IDE features. Just looking at a diff can be very misleading!
I only recently started working in a big team again and when I'm doing Github code reviews I often find myself checking out the branch locally and reading the file in my IDE and then going back to the Github interface to write my review comments.
Not only is this often the only way to understand the context of a change but it also makes it much easier to spot refactoring opportunities. But it's cumbersome and slow.
I always write comments, even on code I've written myself it comes in handy.
6 months later I wont remember why the "easy" solution wasn't the path that was taken, or some complexity that needed special handling in a single case that was discovered through a few hours of debugging.
Sure you could write perfect code, but writing out your thought process helps tremendously with understanding a thought process and getting up to speed far faster.
Same - if my code is complex enough to not be easily written in a few lines I'll drop a comment about what it is doing and maybe even why. It takes a minimal amount of effort while I'm coding and saves a lot of time when I (or someone completely unfamiliar with the code) have to revisit it months/years later.
My guiding principle is that I don't want someone to read my code years later, exclaim "Who the hell is this alyandon guy?!?!" and be motivated enough to create a time machine so they can go back in time and smash my keyboard to bits before I wrote said code.
I agree. Over years, I have saved probably many hundreds of hours explaining the systems I own to new engineers on the team by maintaining good code comments. It also helps prevent bugs as sometimes people might change code without understanding it well, but comments mostly make that impossible.
It is difficult for me to understand why the debate surrounding code comments is so heated. I had some strong opinions about these things when I was very new to engineering but I rarely see anyone senior doubt the effectiveness of code comments. I get the idea of self-documenting code, but very few things are self-documenting to a new person on the team that never worked with your massive proprietary codebase. They need a lot more context.
I would like to see some examples of self-documenting codebases. Sadly, people like Uncle Bob who loudly hate code comments tend to have codebases that are not very self-documenting. Perhaps not writing any code comments is an interesting exercise, but I think it might work much better in small siloed projects than in companies where hundreds of people have to collaborate on the same code and not introduce defects. I wonder if this is where the disagreement about things like code comments comes from - different circumstances of the programmers.
>Perhaps not writing any code comments is an interesting exercise
It's an interesting exercise very similar to the infamous Perl one-liners from the 2000s.
>but I think it might work much better in small siloed projects
The problem here is that those "small, siloed" projects frequently get out of their silos and become bigger and more important than originally envisioned. Then all the new people looking at it have no idea what it's doing.
Exactly. I don't remember what I had for breakfast, much less some brain fart I had 6 months ago.
As a kid, I somehow got the impression that Microsoft had a coding standard for 1:1 comments to code. So I thought I'd give it a try. (I had a lot of free time.)
For the 1.x to 2.x version bump of my text editor, I meticulously went thru and commented everything. (I also switched to 1 statement per line guideline.)
The outcome was awesome. By requiring a comment, any comment, for every statement, it evolved into a form of story telling. I wasn't just explaining obvious stuff. It helped tremendously with future maintenance.
Alas, I've never repeated that experience. I'm not entirely sure why.
It's a bit like Knuth style literate programming or TDD. Some kind of Platonic ideal. An esthetic ideal to strive for, but not very practical.
> some complexity that needed special handling in a single case
Shouldn't that be expressed in a test? To me, "there's a special case that drives the code in a particular direction" is Exhibit A for "things that belong in tests".
Having done some "code archaeology" in my past, I loved coming across a good comment block, with clear rationale as to why something was done, which looked incorrect if you only had the code.
Why must that documentation go inline with the code? There are so many better ways to document design and implementation decisions that don't involve embedding English into source code files.
We preach endlessly the idea of orthogonality and abstraction, but then we smash together plain English and Python/C++/Erlang/whatever?
If the information in the comment directly relates to the code and is for developers then putting it next to the code makes a lot of sense. Putting it somewhere else just increases the likelihood it will go stale and decreases discoverability of the information.
> Why must that documentation go inline with the code?
Discoverability and context would not be nearly as useful, to start. Why you need to ask the question, as if there is no suitable answer, is suspect of a thoughtless conclusion.
In the late 80s, there was an idea floated that every file could have a sister file with comments, such that they would not need to be parsed/discarded by a parser. This would aid in generating documentation, among other tooling. When I was starting out, I expected this to take hold, but it never did.
> There are so many better ways to document design and implementation decisions that don't involve embedding English into source code files
While I'm not a fan of excessive comments in code, I am a firm believer in keeping project documentation next to the project. I can't tell you how many places I've been where project documentation was spread across OneNote, Confluence, documents in SharePoint, etc, etc, etc. Any project I have this sort of control over will have the documentation for the project in the repo. I find having a git history of your documentation that can be viewed alongside the history for your code adds so much value to the documentation.
Tests can show what code is expected to do from the point of view of the tests author. They usually have no information why code works this way. Also I've seen more than a few times tests which ossify wrong behavior. Tests need comments too.
I agree that comments explaining 'what' is happening are mostly useless. Write clearer code. But 'why' comments are good. Most things can be coded up different ways. Tell me why you chose this way. Tell me about constraints that might not be immediately obvious. Let me know if indeed, it could be cleaner, but you were in a hurry (this is a thing that happens in the real world), or if it's that way for a specific reason.
In my practice I often see code where useful comments are missing and hours of research required to learn something author for sure knew. Code which has too much comments to me is an imaginary problem - I've seen it at most a couple times in my career and one of them was the code written by a junior developer in a style one can expect in a tutorial or a book. But usually people quickly learn to not add unnecessary comments (and eventually start adding too little of them).
This is true, but if you just get these same people to write more comments, they will also think their comments are clear when they're, in fact, not. I think anyone who is capable of writing clear comments is also equally capable of writing clear code.
If I was to suggest investing time in learning some skill, I would suggest learning how to make your code actually clear by getting the right people (with relevant domain expertise, but without experience with the code) to critique it for clarity rather than learning how to make your comments actually clear.
Why questions are best answered in architecture documentation, the code itself should be self explanatory (given the architecture documentation) for the most part with specific why comments carefully placed in places where it doesn't make sense to use the architecture documentation.
I've read code from various codebases from various companies, large and small. I very rarely see a comment which is genuinely both well placed and useful. From the bits of the linux kernel that I have worked on, I have generally seen pretty good why comments, although I think a lot of them could be shifted into architecture documentation.
All in all, when reading code, my default stance is to ignore comments unless I get lost reading the code, then I attempt to read the comments. It has been incredibly rare that I've found unclear code to have clear comments.
A long time ago, I had a tendency to write comments to explain code that could be simplified. Refactoring it usually made the comments redundant.
Comments are still very useful when the why is unclear.
Better not write tests either, because those will become stale too.
And any sort of user documentation/support/etc. It'll all just become stale.
It's almost as if code is just part of a larger 'thing' that has to be maintained.
There is an argument about reducing the amount of work.
On the staleness of comments, it's a real thing. In particular, on comments explaining design decisions, they will often touch on aspects of the system that are outside of the specific method they are attached to, and nobody will go back to them to rewrite all that prose.
We had a project with a ton of documentation written in the first 2 years, and as engineer count grew, these comments just disappeared as again and again they were causing misunderstandings, and actual documentation was already written in the internal wiki as each refactorings and new features were discussed and designed.
It's not just a rails thing, and after a while people stop trusting comments altogether, which make updating them a chore more than anything.
The 5 programming languages with the least amount of bugs are:
*Drum roll please* Ruby is nothing like the other languages above in design, but that community has fantastic conventions around code clarity, code quality, testing, continuous integration, etc.Comments are for things like, `Todos`, Noting a specific algorithm, maybe a link to a white paper, noting a violation of a convention for speed, security, or some other performance reason.
Comments are for things that are __impossible__ to tell from the code.
db.insert(record); // save the record to the database
But when they write some crazy off-the-wall code (that's usually because they didn't understand the proper way to do something) I have to check the logs to see who wrote it and ask them why.
Just the other day I was debugging an application that had a 6 second sleep at the end of the main() function. I just figured it was some dumb thing left in for debugging and deleted it, because there's no good reason to do that. The next day, the dev who put it in messaged me and said he put it there because the application was exiting before it had logged it's completion to our logging system. So I explained that the proper way to do this is to flush the log, not just hang the application for 6 seconds so that the last messages just happen to go through.
If there was a comment explaining why there was a 6 second sleep, I could have just fixed it and educated the developer without causing any grief.
> One should take care not to overestimate the impact of language on defects. While the observed relationships are statistically significant, the effects are quite small. Analysis of deviance reveals that language accounts for less than 1% of the total explained deviance
Many functions in the standard library behave subtly differently from there documentation or have behaviour that is not documented but depended on by applications, and I’ve certainly seen lots of concurrency bugs in both code and tests because the GVL makes it hard to provoke the worst case behaviour.
The unit tests are really useful for Ruby language implementations because they help give us confidence we’re replicating all the required behaviour, but from that point of view I wish the underlying things were better specified so those tests weren’t quite so necessary.
Don’t get me wrong. I love Ruby as a language and loved working on TruffleRuby, but I don’t think the community should be too smug about code quality and testing.
You can tell everything with code, given enough time and resources. Nothing is "impossible". But there's a point where you hit diminishing returns. It's about efficiency.
Other devs, or your future self, will have to time trying to build the same "castle in your head" as you did. Can a comment shorten that time? If a one-line comment saves 15 minutes of investigation in aggregate, that's a no-brainer. You should add it. Conversely, a line that says "add 5 to x" is just wasting everyone's time.
As a general rule, once I have finally understood a particularly hairy piece of code, I don't want to do it again in 6 months. I have even done ASCII diagrams in the comments explaining how a particularly hairy piece of code worked, when I hated it enough.
For my code? I agree
Code for others to participate in? The simplest possible way for the greatest number of developers to understand as quickly as possible. Not about my best practice or preference but for the greater good.
Coding standards for the elite devs are only so effective at growing that growing quick enough.
I'm not sure I've seen all the "comment everything" advocates in this thread provide a single example of a good comment.
The python folks before me used this to avoid writing docstrings for modules/classes/methods, so code could only be understood by reading the entirety of it. Throw in some deep class hierarchies and it was very hard to onboard there.
If you're relying on comments to help with that, you'll have to share the same mindset as the person writing the comments, except there's probably multiple years of understanding gap between you and them.
In the simplest cases, sure you don’t need to write “getName returns a user’s first name and last name separated by a space character,” but I’m guessing the method requestPurchase will have a lot of nuance and I hope it’s documented (yes, even the “what happens”)
This would be actually a quite interesting comment as it indicates that the implementation of `getName` is buggy in regard to internalization.
Here's the classic post about this topic:
https://www.kalzumeus.com/2010/06/17/falsehoods-programmers-...
I think there's nearly always value to be added:
* Explaining required fields, if null/blank/0 is allowed, where an ID comes from (db vs app-generated), if string values are formatted or require formatting (credit card, phone numbers), max length or other restrictions
* If a class/method is thread-safe or not (when not obvious and misuse is dangerous), error conditions, timeouts.
* Any external or indirect dependencies for use (config, packages, etc)
* Links to other docs/wikis or tickets is hugely useful.
When you're writing/working on the code you already know all this stuff, and it takes only a couple minutes to document. When someone else (or you, 6 months later) comes along to use or modify it, figuring everything out from scratch can take hours -- or worse, bug reports from QA or customers. Docs shave this down to seconds and directly avoid bugs.
The other huge benefit I often experience is through trying to write docs for something I realize there's a better, more obvious name that makes it easier to use and requires less explanation (less docs). This happens on easily 5-10% of the things I write docs for.
1. Rewrite your code to make the answer obvious.
2. If that's not possible use a comment.
For instance, this [1] is a clean implementation of quicksort, which I offer as an example of any non-trivial algorithm. You can't really write it in a way that would make the idea clear to anybody who wasn't already familiar with the algorithm, because the idea itself is non-trivial. So the way intent is made clear and documented is by making sure the function is called QuickSort. And that is indeed 'self documenting', but really in a way that has nothing to do with the code itself.
[1] - https://www.w3resource.com/csharp-exercises/searching-and-so...
As an IC, even a senior IC, it's difficult to effect this change.
I'm honestly a bit torn by it. Yes, your code absolutely should be written in a way that keeps it tidy and easy to understand. But you've always got complex situations which arent always going to be easy or obvious for someone fresh to the codebase.
There should be a good middle ground. I dont need to see comments saying "this is a loop that gets all the users". If its got a variables called users, calling a methog called "getUsers()" then thats pretty damn obvious whats happening.
However if you then go on to do something weird like loop over each user and calculate a score based on the number of posts they've made then theres undoubtedly going to be some logic in there that even just a simple one sentence comment will help someone understand.
It's a fine line, and getting it right is a skill in itself.
I found that pretty much any methodology works fine in a team like that.
"Don’t comment the code" still sounds pretty crazy to me, but I can believe that it works for them.
Other times to comment include when there is some sort of dirty hack, TODO annotations, etc.
Obviously, unclear code without comments is better then unclear code with comments.
if (theWhy()){ theWhat() }
What this means is that if your Ruby code is clear it should read like natural language. Injecting subtitles into the middle of the expression
# I decided to phrase it this way because I was in a rush and it was the first thing that came out. With more time I could no doubt articulate this in a more communicative way, but for the sake of a random post on the internet I'm not terribly worried.
interrupts the flow when one is reading the code, which makes for a much less pleasant experience. Ruby may not be the only language that is like this, but it is relatively unique in this regard. Comments in other languages don't seem to cause the same interruption.
# That's all I've got. Time to clean up.
I'm not sure this means don't provide additional information to future readers that may be beneficial, but be discriminating in where you put it. Or do whatever you want. Who cares what someone else thinks?
The history of programming is full of that notion and it never really works out. See: COBOL, SQL, and so on.
I think we can all agree that code that is easy to read is better, but sometimes the 'why' needs spelling out.
Comment bit rot is inevitable, because comments don’t compile and can’t be tested. The only way to keep them in sync is by hand, which takes a lot of time and energy and is far from perfect. Of course,
> The first problem is that most developers are under great time pressure and don’t have the time to make the code so utterly clear that it requires no further comment.
So they don’t have time to write the code clearly, but they somehow magically have time to read and review all the comments and to keep them in sync with the code? And the reviewers too?
“If only developers worked harder…”. It’s nonsense.
Comments are great, they have an important place in software engineering, and I always regret when I forget to write some in a file or class. But they are not a silver bullet, and must be treated with suspicion, because there is no way to prove if they actually describe what’s going on. And that’s the same reason that they are hard to keep in sync.
If there have been major structural changes that make the comment useless- that’d be pretty easy to see, it’s very easy to delete comments
I'd argue you could do the same on methods and class you want more context on, removing the need for the majority of comments, and most companies will have the associated ticket numbers or design discussions attached to the MR/PR.
I think there will still be rare situations where comments are absolutely needed, but in these rare cases they should probably refer to an external resource (a bug report for a specific library, an incident that required a specific fix, etc.)
Exactly. I used to love writing comments, but they have become for me a last resort. I'd rather put the information I'm trying to convey almost anywhere else. Variable names, method names, improved interfaces, better object relationships, doc strings, test code, test names, commit comments, or my colleagues' heads.
Though I fully admit that automated tests cover nothing related to explanations / things that aren't inherently true or false.
Personally I've wanted a way to link code to comments, not just the reverse, so I can change code here and be notified that it affects comments over there, especially during review time (just show every related comment next to the change). It seems literally essential for reliable documentation, but I haven't yet seen it except maybe in WEB (the literate programming language) or similar.
but ... it's the explanations that are important.
I mean there are plenty of tools to check that a comment matches a function signature or otherwise describes the properties of a bit of code. But who needs that? At least in a strongly typed language, reproducing the signature or doing anything else that reflects existing code within a comment adds very little.
Anyway, I am not arguing against comments. I'm just arguing that they can't somehow magically reduce technical debt. Or that they have anything at all to do with technical debt. Or that the OP made any sense at all.
If your code is separated from comments explaining it so much thag this isn't visibly obvious on review, there’s probabky a bigger problem than “I don’t have a way to link commebts to distant code and vice versa.”
Not true in Rust
I don't want to write a comment, I'd rather write clean code that looks good, but when I run out of time to spend on a problem, and I don't think the code is clear enough, I think then it's acceptable to add a comment.
I just think too many devs have their egos wrapped up into their jobs, so hearing, "Commenting is failure!" evokes an emotional response. What these devs don't realize is you can make no mistakes and still "fail" to write clean code, and that's totally okay.
Uncle Bob is just saying that pulling out a comment before you've tried is premature. Try to avoid it first, if you have time to.
He has been trying to say profound things for a long time now. He was super active in the XP community in early 2k onwards and he was nearly always saying things that I felt were a bit "off". i.e. there was a gem of an idea, but the idea was turned into some principle or rule that lacked nuance and context. Reality is, there isn't any fundamental rules/principles... just ideas, some ideas seem more universal than others, but these ideas are just a bunch of strategies you can use when approaching software development and depending on context they may or may not be good strategies.
In terms of commenting, some of this weird "wisdom" around commenting was fundamentally rooted in the idea you can't fix bad code with comments. People noticed that a lot of times where there was comments in "poor" code it actually was a spot where you could do some kind of refactoring to make the code clearer. Eventually this morphed into "If you need to comment your code you have failed" type sayings. However, there was plenty of people advocating commenting to explain things the code can't tell you, but too many were swayed by "commenting is failure to write good code" that they threw out some of the reason why people like to put comments in. Many in their first 10 years of coding really want guidelines and rules and principles and argue strongly for things they have found effective compared to how they approached coding previously. But these things you learn are almost never universal, even if you can see/argue how you could apply it to all kinds of things, other approaches might actually work better, or might work better in different contexts.
One of such things is "screaming architecture". It is a good idea in theory, but only if you already know what the architecture should be. Most new projects don't know what they need up front, and discovery happens over time. Screaming architecture is bad for this process. It inhibits it, requiring a ton of refactoring because of early assumptions. One thing that is known up front is entry points. (CLI, requests, tests, bg jobs). They're a lot more likely to stay around forever. Custom architecture should emerge underneath them. I guess we can call it whispering architecture.
1. An odd business requirement (share the origin story)
2. It took research (summarize with links)
3. Multiple options were considered (justify decision)
4. Question in a code review (answer in a comment)
Code is writing, would you write a technical book without sections and chapters?
E.g. if the ide can't grok what a $var is you can do :
then when it reindexes things it has no problem tying everything together.For instance, it's great that code reviews have become standard practice at most organizations and for many projects, but the tooling for those reviews almost always rely on showing the few lines above and below a code diff. The reviewer has no convenient way of seeing how the changed code may conflict with any applicable comments unless the comments happen to be within those few nearby lines or the diff happens to include comment changes. Even then, the big picture is out of view and rot is still likely to seep in.
It would be nice if incoming developer-support AI could start tackling this, by surfacing impacted comments and even "linting" them for applicability and accuracy.
That only applies to comments that address what the code is doing or how it does what the comment says. It does absolutely nothing for the most critical type of comments: the ones that say why the developer decided to do it a particular way. Maybe they tried it three other ways and this was the most efficient way. Maybe they chose this way because it matches up with a business requirement that things be done in a particular order (regardless of efficiency). Maybe it must be done that way for consistency with another part of the system that is only obvious from the comment.
It will be a long, long time before AI will be able to reasonably vet such comments for accuracy. Until then, comment your darn code!
Documentation tooling should be able to make a good job of constructing a class/function DAG with scoped commentary. This is kind of a reversal of Literal documentation, but I suspect it may be more maintainable by teams.
Literal docs only seem to go in one direction, that is documentation->code, not the other way around. This I guess is more in-line with scientific hypotheses. Literal tests may be even more tricky as TDD doesn't gel well with Literal hypotheses.
I guess a Doc-driven dev process would be a novel approach here, and probably more usable than AI-supported systems. Copilot has been quite divisive on it's effectiveness.
DDD in that every eg. Class requires a comment and a test even if they are blank, to force at least a thought about them. Having a code manifest at the root of a repo can also be used to configure the envs the code runs in, and the integration tests that it needs to do both local and in-place.
Lastly, as mentioned elsewhere, logs are comments as well, and again would be well to be scoped in the language.
The other thing I wanted to mention: People don't do code review in their IDEs? Really?
Modern languages with type inference are not fun to analyze without an IDE… Also you can't navigate to related code without IDE features. Just looking at a diff can be very misleading!
I only recently started working in a big team again and when I'm doing Github code reviews I often find myself checking out the branch locally and reading the file in my IDE and then going back to the Github interface to write my review comments.
Not only is this often the only way to understand the context of a change but it also makes it much easier to spot refactoring opportunities. But it's cumbersome and slow.
6 months later I wont remember why the "easy" solution wasn't the path that was taken, or some complexity that needed special handling in a single case that was discovered through a few hours of debugging.
Sure you could write perfect code, but writing out your thought process helps tremendously with understanding a thought process and getting up to speed far faster.
My guiding principle is that I don't want someone to read my code years later, exclaim "Who the hell is this alyandon guy?!?!" and be motivated enough to create a time machine so they can go back in time and smash my keyboard to bits before I wrote said code.
Deleted Comment
It is difficult for me to understand why the debate surrounding code comments is so heated. I had some strong opinions about these things when I was very new to engineering but I rarely see anyone senior doubt the effectiveness of code comments. I get the idea of self-documenting code, but very few things are self-documenting to a new person on the team that never worked with your massive proprietary codebase. They need a lot more context.
I would like to see some examples of self-documenting codebases. Sadly, people like Uncle Bob who loudly hate code comments tend to have codebases that are not very self-documenting. Perhaps not writing any code comments is an interesting exercise, but I think it might work much better in small siloed projects than in companies where hundreds of people have to collaborate on the same code and not introduce defects. I wonder if this is where the disagreement about things like code comments comes from - different circumstances of the programmers.
It's an interesting exercise very similar to the infamous Perl one-liners from the 2000s.
>but I think it might work much better in small siloed projects
The problem here is that those "small, siloed" projects frequently get out of their silos and become bigger and more important than originally envisioned. Then all the new people looking at it have no idea what it's doing.
As a kid, I somehow got the impression that Microsoft had a coding standard for 1:1 comments to code. So I thought I'd give it a try. (I had a lot of free time.)
For the 1.x to 2.x version bump of my text editor, I meticulously went thru and commented everything. (I also switched to 1 statement per line guideline.)
The outcome was awesome. By requiring a comment, any comment, for every statement, it evolved into a form of story telling. I wasn't just explaining obvious stuff. It helped tremendously with future maintenance.
Alas, I've never repeated that experience. I'm not entirely sure why.
It's a bit like Knuth style literate programming or TDD. Some kind of Platonic ideal. An esthetic ideal to strive for, but not very practical.
Shouldn't that be expressed in a test? To me, "there's a special case that drives the code in a particular direction" is Exhibit A for "things that belong in tests".
Comments aren’t milk, they don’t just go off, developers let them go out of date.
As others have said, comments should be used to add why, to give context.
We preach endlessly the idea of orthogonality and abstraction, but then we smash together plain English and Python/C++/Erlang/whatever?
Discoverability and context would not be nearly as useful, to start. Why you need to ask the question, as if there is no suitable answer, is suspect of a thoughtless conclusion.
In the late 80s, there was an idea floated that every file could have a sister file with comments, such that they would not need to be parsed/discarded by a parser. This would aid in generating documentation, among other tooling. When I was starting out, I expected this to take hold, but it never did.
> There are so many better ways to document design and implementation decisions that don't involve embedding English into source code files
I don't think that's been demonstrated.