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.
But that's the point; if it's a "why" doc, it shouldn't be specific to the code, so by virtue of the fact that you feel the need to place it there anyway, it's not really a "why" doc at all, and instead should be resolved by writing clearer code.
We agree code should be split into multiple files, why do we suddenly not agree that English should be split as well? Nobody would try to write a file with 30% JS, 50% C++, and 20% Python.
Code is very formal and limited in what it can express. The real world tends to be much more chaotic. It is impossible by definition to express some reasons just in code, that's why comments are sometimes necessary.
> if it's a "why" doc, it shouldn't be specific to the code
Sometimes the "why" is directly connected to that specific part of the code and doesn't concern anything else, or anyone not working on that part of the code. Separating & moving the explanation to another place just makes it less visible exactly where it matters.
If the explanation is directly connected to specific parts of the code, it's not "why", it's "how". "Why" will be true regardless of implementation, "how" won't be.
Comments should be less visible, as they distract the coder from understanding what the code actually does with potential lies about what the code ought to do, according to the flawed human who wrote the code.
Put the comments elsewhere. We don't put all our code in one file to solve "it needs to be visible!" problems, we shouldn't do it with our docs either, it is not consistent nor is it helpful.
> We don't put all our code in one file to solve "it needs to be visible!" problems, we shouldn't do it with our docs either
You make comparisons without considering the reasons.
We split code up into multiple files because we cannot have 100% of the code on screen either way and huge files tend to be cumbersome. Whole IDE components are built just to show API docs and other parts of the code exactly where and when we need them. With that in mind it makes no sense to have important comments not be visible where and when we need them.
And even if those comments were in a separate file like you suggest you'd still need a comment in the code to make developers aware of the fact an important explanation of some obscure detail exists. If you don't then any change of that code might invalidate the documentation without anyone knowing, and then you're back at square one with lying comments/docs. Comment visibility also means it's visible when it needs to be updated.
I think you’re trapped in this “comments must exist” mindset that’s simply not true or necessary. Every single thing you like about comments can be accomplished with self documenting code and accompanying “why” docs.
There’s simply no need for inline comments anymore, and continuing to use them is admitting you’re not putting the kind of effort you’re capable of into building software.
> Every single thing you like about comments can be accomplished with self documenting code and accompanying “why” docs.
Except being exactly where and when it's needed, with any modern editor being able to hide it for people who don't want it.
You seem to base everything on the assumption that comments are always the worst choice, and that people don't behave like people but always document things the right way no matter how cumbersome or complex that is compared to the obvious way. Seeing things in black and white is usually not the best solution.
> continuing to use them is admitting you’re not putting the kind of effort you’re capable of into building software.
No, and I hope that kind of thinking won't mislead you into believing you are at your peak because you don't write comments.
And all I’ve said is comments are a last resort. Nothing black/white about that, just tired of egos getting in the way of seeing how there are a million ways in practice to avoid comments that people who “like” comments refuse to learn about.
You're treating comments like a pariah because they might be wrong (i.e. not accurately describe what the code is doing) but that's just as true for the code itself: it may not be doing what it is actually intended to do.
In fact, there may be cases where the comment is correct (i.e. it describes what the code should do) but the code is wrong and doesn't actually do it correctly. Why should the comments take a back seat in that case?
In reality, comments and code are part of the whole system. There's nothing wrong with being suspicious of a comment's accuracy, but that doesn't mean comments aren't helpful. Part of development is keeping code and comments in sync. Yes, programming is hard.
This is a bad take, as the code is actually executed, whereas comments are not.
As the code is, definitionally, the way the program works, it must be correct, necessarily. This is not true of the comments.
This is why comments are dangerous and bad, only to be used when you've run out of time and/or aren't smart enough to figure a problem out (happens to everyone).
I respectfully disagree with your assertion that because the code is how the program works, it is by definition correct. Wouldn't you define a bug as incorrect code?
In any case, even if the code is perfectly correct, comments can and should be used to describe why certain decisions were made, when they are not otherwise obvious from looking at the code. E.g. "You might think a bitfield would be more efficient for storing this data but we choose an array of long ints because in the near future we plan to update the code to pass this as an argument to foo() which assumes an array of long ints."
Comments are not limited to instances when you run out of time or are not smart enough to figure out a problem. The whole idea of comments is to save a future developer from the headache of figuring out the things you're writing comments about.
> 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
>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.
This sounds a lot like the director's commentary tracks on DVDs. No one ever watched those, and the sister-comment-file would flop the same way if anyone really tried it. A separate file is fine for documenting overall design, but for detailing sections of code, the commentary needs to be close to it, where people will see it.
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.
Sure, but throw it in a README.md, not in the code itself.
Besides, if you foster a culture of writing "why" docs, the problem of where to place these docs is one you solved early on, so people will know where to go.
Absolutely. If you were to survey, I would fall much more closely on the "don't comment code" side of things. But if you have documentation for your project, keep it close to the project. That's all.
You know, I find your point of view insane and crazy, but I’m willing to consider that some people really see code as a different language like let’s say Chinese and would find it crazy to mix english and chinese together. I don’t see any other explanation
Comments intermingled with code help me navigate as I'm trying to accomplish my task.
A simple comment every "paragraph" of code or so helps me narrow down the amount of code I need to mentally parse to get to the part that's actually relevant to what I'm trying to do.
So since we're supposed to be on the same team, explicitly saying "go fuck yourself, load a mental model of the entire codebase to find the part that's relevant to your task, I'm not going to help you" does indeed seem insane and crazy.
I feel like you're missing the entire point of abstraction. When you're looking at code, you should be able to understand what it does by way of how it's structured, and you shouldn't have to load the entire codebase in your brain to do that.
You see a function called, "getCustomer" you shouldn't have to dive into that function to understand what you're getting back. It's a customer, no need to figure out how it got the customer or what the format is, etc.
Whether or not you realize it, you've gotten to the point of arguing against a lot of really common and proven out design concepts (abstraction layers, orthogonality and the LoD, data types, etc.) without even realizing.
"How can I know how the program works without comments unless I load the entire thing into my brain all at once?" is not a question you ask if you understand these principles, because you know you won't need to.
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.
> They usually have no information why code works this way
They need to if the the way it works is significant. If it is not significant then the value of a comment becomes somewhat dubious anyway as the code is expendable and doesn't really matter. It is not necessary to understand the program and if it is flawed you're going to rewrite it. Comments can add a lot of value, but there is a line where the value quickly diminishes.
Perhaps a more concrete example would be useful? Nobody cares why you used a given algorithm over another in the general case.
If the observation of a unit prompted a need for a specific algorithm – to reduce time complexity, for example – then you have something quite testable to document the choice, so it’s not clear what you are asserting.
How do you know when it's not "the general case"? Where is this documented?
How does a unit test distinguish different algorithm (with of course same big-O characteristics, as obviously otherwise this example would not make any sense in the first place)?
Again, I think we need a concrete example to really understand what you are trying to say.
If two algorithms are functionally identical (same results, same space/time complexity, etc.), who cares why? What are you going to gain from knowing more about the choice?
I'll give an example. Let's say you need to add 1 to each integer in an array. You could use a for loop, a map function, etc. We'll assume the compiler optimizes each choice to the exact same machine code. What would you like to have documented about the choice?
> We'll assume the compiler optimizes each choice to the exact same machine code.
Where is this—possibly wrong—assumption documented? Or do you think it makes no sense to document random assumptions, which may or may not hold in the future?
Another simple example: Almost all usable sorting algorithm have the same space / time complexity on paper. But as everybody knows they behave quite different in reality (otherwise we wouldn't have so many of them to choose form). Do you really think it makes no sense to document such design choice where it matters?
Also in this case unit tests won't help you. (But you given up already on this line of argumentation anyway, I see ;-))
> Where is this—possibly wrong—assumption documented?
Presumably in the compiler documentation. Although the assumption was made merely to ensure that we understood that each algorithm choice was functionally equivalent, to continue in the theme of discussion.
> which may or may not hold in the future?
Totally fair. Let's say your choice, which was fine at the time of choosing, with a later compiler update does get optimized in a new way that that longer satisfy your application's requirements. How do you plan to keep up with that if you don't have automated tests to prove whether or not your code still operates within your expectations?
> But you given up already on this line of argumentation anyway, I see ;-)
No, but I was still working on getting a concrete example in which we can build a test or two for to provide a demonstration. Unfortunately, the vague sorting suggestion still isn't concrete. What are you sorting? Which algorithm did you choose and why? I had hoped that if I rephrased the question you would feel more comfortable coming out of your shell, but I can see your worry remains. Back in my day education was something to get excited about so I struggle to understand, but recognizing your uncomfortableness now I'll not needle you further and apologize for not seeing it sooner.
> How does a test inform you why a function was implemented using algorithm A and not algorithm B which would also do the same?
You made up than a straw man saying something something that you assume that both algos get optimized to the same machine code. Which is completely irrelevant to the actual question.
I've only mentioned that both algos need to have the same big-O characteristic obviously as otherwise they wouldn't be interchangeable in the first place.
> What are you sorting? Which algorithm did you choose and why?
LOL, that's exactly the question a good code comments should answer.
Because code can't do that!
The example here is: Big-O is one thing, but "what are you sorting" matters, and some algo may be better suited for the task than the other.
If this isn't obvious it needs to be documented.
The best place to do that is right where the code is. As only this will make sure it will be read together with the code. (Otherwise someone could for example rewrite the code to something "more standard" and it's not a given that the people reviewing the change would know about the reasoning behind the original implementation; a comment would have prevented bugs and regressions in such a case).
An attempt to measure say 5% difference in a tests would likely produce a flaky test which frequent failures would waste team's time. I'm not even starting that to measure this difference in a test one would have to maintain two implementations - slow and faster one and run in a test suite both to have two times to compare. Looks like unnecessary work to me. Enough to run benchmark manually when a decision is being made.
If the difference is so small it's hard to measure, then that sounds like something that's not worth testing to me. Meaning that it's also ok if somebody changes the implementation later on.
On the other hand, if it's performance critical code in a way that's important to the project, then running a manual benchmark once and hoping that nobody accidentally breaks it strikes me as poor practice.
Exactly. I wonder people don't recognize that upfront.
I'm getting the impression, like it was stated by some people here, that this whole "no comments" / "everything should be a unit test" idea comes form inexperienced but idealistic developers mostly.
People with more experience seem to know already OTOH that good comments can save your ass in the middle of the night.
> this whole "no comments" / "everything should be a unit test" idea
Nothing in this thread says "no comments" or "everything should be a unit test". But the reality is that most code doesn't matter. It is just a means to an end and if it no longer serves that means it's expendable. Explaining why something was chosen doesn't tell you anything meaningful most of the time. In fact, I expect the "why" 99% of the time is "I felt like it and it worked".
When a specific approach is essential in meeting certain application requirements, absolutely you need to comment that. But you also need tests, else how are you going to ensure that you stay within those requirements? Of an application of any meaningful size, you're going to have a hard time manually ensuring that some externality didn't break your assumption on every deploy. Even if it weren't hard, why put in the man hours when a machine can do it for you?
> In fact, I expect the "why" 99% of the time is "I felt like it and it worked".
Erm, we're talking about professional software development here.
What someone is tinkering together in his hobby cellar is of no interest to me.
Code created by the principle "I felt like that" is garbage by definition. It makes no sense to even discuss such stuff.
> When a specific approach is essential in meeting certain application requirements, absolutely you need to comment that. But you also need tests, else how are you going to ensure that you stay within those requirements? Of an application of any meaningful size, you're going to have a hard time manually ensuring that some externality didn't break your assumption on every deploy. Even if it weren't hard, why put in the man hours when a machine can do it for you?
Here I actually agree fully.
What can be tested by the machine should be.
That's for example a reason to use statically languages, as in contrast to such thing as Ruby, the machine can give much better correctness guaranties with static type checking.
But the point is: Not everything can be expressed as meaningful test.
For example you proposed something that would result in a flaky test case…
Some other things can't be expressed as test either. And the experience shows that's this things are almost always related to the why question. In the end you put exactly this question front while discussing some imaginary implementation of something, which shows my point nicely. :-)
> Code created by the principle "I felt like that" is garbage by definition. It makes no sense to even discuss such stuff.
I think you are vastly overestimating not only how much people do work rationally, but how much it's even possible. E.g., System 2 thinking is just much more expensive. And programmers usually work in environments that are pretty data-poor with respect to important factors. And that's before we even get to both project-level and individual path-dependence.
One, I didn't say that. And two, I write under my real name. It's pretty easy to find out how much experience I have.
As a person with "more" experience, I went through a phase of writing lots of comments. Obviously, given how much I comment here, I like writing. But as I said elsewhere in this discussion, comments 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.
If you can't consistently measure a 5% difference in a tightly controlled environment, how are your real world users going to notice? If your users don't notice, who cares?
Furthermore, if that 5% optimization is truly critical to the application (despite not being measurable?), how are you going to ensure that some future change doesn't break that? Something as simple as a compiler update could change some optimization that breaks your assumptions. What do you do in the absence of tests to ensure that doesn't slip through?
Even if user would not notice 5% difference in CPU usage can mean reduction in AWS bill significant enough to care about (but not significant enough to spend days to avoid adding a few lines of comments by embedding all knowledge into tests).
> 5% difference in a tightly controlled environment,
A test suite usually doesn't run in tightly controlled environment. To get meaningful performance testing results you'll need to run it on dedicated hardware (no noisy neighbors) and don't run different tests in parallel (so one test will not be a noisy neighbor for another test). It is something not hard to do once in a while manually but would be quite expensive to do as part of a test suite which typically is running on each change.
> Even if user would not notice 5% difference in CPU usage can mean reduction in AWS bill significant enough to care about
Users won't notice, but they will notice...?
> A test suite usually doesn't run in tightly controlled environment.
What don't you have control over?
> but not significant enough to spend days to avoid adding a few lines of comments by embedding all knowledge into tests
Why would you avoid comments? Why would your tests have to take longer to write than your comments? Days to write a test or two to clarify your intent?
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.