Leaning towards commenting "why" not "what" is another good general rule. "Self-documenting code" with sensible function and variables names and logical flow already cover the "what" fairly well.
# Some countries have sales tax rules dependent on the day of the week
return nil if country_code==KERPLAKISTAN and day_of_week==MONDAY
The exact comment here could probably be more specific (e.g. where do you find these rules), but it also most likely shouldn't repeat the code (and the code should make clear what it represents).But I agree with your statement that there should be a pointer to the business rules somewhere. Otherwise it's difficult to have a meeting with the business side and ask, "Has anything here changed?" I think that's the biggest thing people miss out -- It's not that hard to find the thing in the code if things change. It's super hard to make sure you are on top of all the business requirement changes.
country_code==FIFTY_FIVE and day_of_week==ONE
string url = HTTP + COLON + SLASH + SLASH + WWW + DOT ...
I swear I'm not making this up....> "There is a famously bad comment style: ...
Don't laugh now, wait until you see it in real life."
But in the trade-off in code readability was probably the cause of many other mistakes, so probably ended up further behind.
[NB 30 isn't an exaggeration - I think the vast team who wrote it were paid by the abstraction or something].
return nil if country_code==KERPLAKISTAN and day_of_week==MONDAY
Hmm.. Well that's strange. I don't have a background in Kerplakistan monetary policy so I don't know why we aren't assessing sales tax on Monday. Perhaps Kerplakistan is a special case. Is that being handled somewhere downstream? Then 1-2 hours later, after shuffling through source and eventually just Googling Kerplakistan sales taxes, you discover what someone found out 2 years ago when they wrote that line. Now you resolve the ticket and move on with your day but you just wasted a couple man-hours on a non-issue that could have been resolved instantly from a code comment.Comments are as much for the next guy as they are for you.
Code smell doesn't mean you should never do it, just that often there's a better way.
I worked on an enterprisey line of business app that assigned sales leads to salespeople.
The algorithm to do this was a multi-step process that was (1) rather complex (2) constantly being tweaked (3) very successful (4) contained a number of weighting factors that were utterly arbitrary even to veterans of this app.
It was full of many `if country_code==KERPLAKISTAN && day_of_week==MONDAY` -style weighting factors. Each represented some hard-won experience And when I say "hard-won" I mean "expensive" -- generating leads is expensive business.
We had a strong culture of informative commit messages, but this file had hundreds if not thousands of commits over the years.
It was the kind of code that resisted serious refactoring or a more streamlined design because it was a recipient of frequent change requests.
A few human-readable comments here and there went a loooong way toward taming the insanity and allowing that module to be worked on by developers besides the original author.
Knowing the why for many of these rules made it much easier to work with, and also allowed developers to be educated about the business itself.
I'm not at all convinced that this is unpopular, but I think it's a whole lot harder than you're letting on. Unless you have a constant stream of new people coming in and you can convince them to give honest feedback, you don't actually know what's not obvious.
return nil if country_code==KERPLAKISTAN and day_of_week==MONDAY
Then you don't need comments and the sync problem goes away?Is this a quick thing somebody hacked in for a special, one-off, tax-free month in Kerplakistan as the country celebrates the birth of a princess?
Is this a permanent thing? Will there eventually be more weirdo tax rules for this country? Will there be others for other countries?
Knowing the "why" would help a developer understand the business, and reason about how best to work with this bit of code... should we just leave this ugly little special case in place? Should we have a more robust, extracted tax code module, etc.?
Commit messages help to accomplish this too, and can offer richer context than inline comments. Each has their place. Sifting through hundreds of commit messages in a frequently-updated module is not a great way to learn about the current state of the module, as the majority of those commit messages may well be utterly stale.
Ultimately the cost of having some concise inline comments is rather low, and the potential payoff is very large.
Remember that the longer term goal (besides the success of the business) of software is to have your developers gain institutional knowledge so that they can make more informed engineering decisions in the future.
Generally, this falls into two categories.
1. Hacks/kludges to get around bugs in hardware, external services, or included libraries. These manifest in code as incomprehensible, ugly bits of code that are difficult to distinguish from code that is simply "sloppy" or uninformed. More importantly, they represent hard-won knowledge. It often takes many programmer-hours to discover that knowledge, and therefore many dollars. Why throw it away? (Tip: include the version of the dependency in the comment, ie)
...so that future programmers (including you) can more easily judge whether the kludge is still needed in the future.2. Business logic. This too is difficult/impossible to discern from looking at code. Often, one's git commit history is sufficient. But there are any number of scenarios where version control history can become divorced from the code, or require a fair bit of git/hg/svn/whatever spelunking to access. And this of course becomes increasingly onerous as a module grows. If there are 200 lines of code in a given module, it is a significant time investment to go git spelunking for the origins of all 200 lines of code. Some concise internal documentation in the form of code comments can save an order of magnitude or two of effort.
This is pretty easy to enforce at code review time, prior to merging.In the first place, only a true maniac would intentionally update
...without updating the associated comment. If they do neglect to update it, that's an easy catch at review time.