class CrappyApiWrapper
{
CrappyApi _crappyApi;
void DoSomethingNice() {
crappyApi.DoSomethingCrap();
}
}A comment can be very valuable to answer the question "why the heck is this being done here?"
It's valuable because it represents hard-earned knowledge.
That thing that is being done there wasn't being done there before, and it took weeks to figure out that it had to be done there, for the sake of such and such a race condition that can occur, when the interrupt goes off just when we are doing such and such elsewhere in the driver. It was hard to reproduce the ensuing problem and trace it to this.
The comment explains how the system will fall down if not for those lines of code.
Systems that have a lot of (or not even a lot of) concurrency going on can be very hard to understand from the static view. Our aim is to produce the dynamic view: to bring to life the collaboration or sequence diagram that we had on the whiteboard. But it's not obvious how (or whether) the code actually does that (and only that, ruling out unwanted scenarios).
"Why" comments can also make the code more navigable, because they mention other identifiers elsewhere in the code which are related to this code here in ways which are not obvious. The text editor can jump from these mentions to their definitions, which is a big time saver for someone trying to understand that situation.
For example in our current project w'ere working on a front-end piece that connects to a CRM application where no rules or constraints have been set up or enforced for a long time. We're talking stuff like zip code fields having values like "I don't know" or "XXXXX". So for every function that receives such values from a lookup, we have to clearly document those edge-cases in the comments and explain how the function deals with them.
ZipCode GetZipCode()
{
var result = _crm.GetZip();
return isValidZip(result) ? new ValidZip(result) : new InvalidZip(result);
}
class ValidZipCode : ZipCode { ... }
class InvalidZipCode : ZipCode { ... }
No edge cases, perfectly 'documented'.Why do you return a different class for invalid zips? Is it OK to use invalid zips in all cases? If not, why not throw an error? If so, what benefit does the separate class give you?
Because that code doesn't handle bad data - something in the objects or some other function must handle it, and this code doesn't really tell us what is going to happen with a bad zip. It just tells us that the code noticed it.
This is exactly why comments can help.
Feel free to add some code that explains your use case and where you think such comments are required...
In short, we make sure that a coder can read the code and understand not just the code, but how it fits into the larger business.
var browserOddityHandlers = [
{ browser: "IE", date: "2001-08-27", version: 6, odditiesHandlers: [ ... ] },
... ];
Code is rarely an arbitrary design choice. Such design choice decisions as you mentioned belong in your source repository message IMO, rarely in the code.In the case of the CEO mandated approach, write a test that explains it. Why comment something that can be tested.
[Fact]
void FooReturnsBazBecauseJoeMadeUsDoThisInsteadOfBar()
{
var actual = _someObject.Foo();
Assert("baz", actual);
}
This way, if that code ever is changed, the comments and the code don't get out of whack with each other. Instead, you'll have a broken test. At that point it becomes obvious to reach for understanding as to why that test is there. The first step is read the commit history. If your commit history is useless, you talk to the dev that implemented it, or go back to the spec that drove it. These solutions are still 100x more useful than a comment. // Optimized this code as it's a hotspot. Does <x> but quickly. void DoActionOptimized() {
...
}I broke it into 3 lines and commented each.
So the first thought when writing code that isn't obvious should not be to comment it, but to figure out if there is a way to write it clearer.
But of course, sometimes we need to write code that isn't obvious, and then a few well thought through comments will save the day.
Can you point to an open source repo somewhere that demonstrates your point that comments are preferable to writing clear code without comments?
I'm sure you can point to repos where poorly written code requires comments in order to be properly explained. This is not really what I'm after, as I'd contend it's likely that writing the code better would be more useful to that project.
And if you have to do something unusual due to limitations (say, a bug in a 3rd-party library) in your code I don't want to know about that when reading the method's documentation (what you refer to as "summary") to be able to use your code. I want to be bothered with it when I have to read its implementation because I have to fix some bug in it.