Document the Why(ianlotinsky.com) |
Document the Why(ianlotinsky.com) |
Now when I write things, I know to comment in what I call the "macro-comment". That is to say instead of writing a comment to describe a single line of code, you write comments to describe a block of code. Since that one project's fail, I haven't had that problem again.
Another point I want to make is that I really feel like my commenting skills are extremely valuable to me as a developer. I I had to have my brain erased, but I could choose one skill to remain, I'd choose keeping my code commenting skills. Its also the one skills that I care about the most in my co-workers. I don't care if you're really good at code golf. I don't care if you know haskell. Can you comment code properly? Whenever I interview for a job, I'm never able to demonstrate this skill. The Fizzbuzz problem doesn't allow me to show off my commenting skills. Writing a binary tree parser doesn't let me show off my documentation skills. I think it's the most important skill I have, but I never get the chance to show it off when interviewing.
Another case is the "reminder note"... e.g. "This function also sets up the next step..." (I know, side effects and whatnot, but sometimes you're stuck with other people's libraries).
A good interview process does let you show off your commenting skills. FizzBuzz is useless to measure ability, but wonderful for screening out those who have literally no ability. For my money one of the most valuable components to a good interview is a code sample, either look at code they've written in the past or give them a small problem to work through.
I might be biased though. I got more job offers from companies that interviewed me that way, including my current position :)
// set the user data
var userData = {
The thing that grates with me is that this is apparently an acceptable stance on the issue. These people don't see this inability to read plain code as a flaw, or something they should work on.You don't always need to "document the why", because often it's obvious enough (with a well-named hierarchy of code, method names, etc.)... but it's essential to get a feel for times when someone else will see your code doing Y and think "ah, this would be easier if we just do X", and comment those carefully.
Related: read other code; get a sense for common programming idioms, and use the common approaches unless you have a really good reason not to.
You may be proud to have mastered a little-used feature in your language of choice that saves you a line of code here and there, but if the cost is that 80% of the people reading your code later are confused, you're not winning.
What if it's a feature little-known within your team, but considered common or even idiomatic in the wider world?
Everyone wins in that scenario.
We are humans and we do communicate with our own language. Our brain is not made to read code. We are not a compiler who thinks in EBNF. Commenting the how is appropriate in many cases especially if you are not working alone but in a team. (1)
I really enjoy comments of people who are smarter than myself. Those comments (especially) helped me a lot to improve my own skills, to understand their code better and my feeling is that those essential comments make our code better - not worse.
(1) "we/our" = the people working in our startup
As a mediocre chess player, I can read the notation for two chess games and appreciate a lot, but I doubt I could tell the difference between a game played by players rated 1800 and one by 2400s. Programming seems the same way: you write comments so that other engineers don't have to be 2400s to understand the hidden implications.
It lives on in CoffeeScript and tools like Docco. The just-released Coffeescript 1.6 supports a mix of markdown and code that looks great: http://ashkenas.com/literate-coffeescript/
Comments explain why you are doing something, your code
should be written in a style that automatically shows the
who, what and how.I ended up firing a guy because he would not stop littering the code with crap like:
// 2 lines added by I. Dee Ott Feb 12, 2005
// increment i
i++;
// 1 line removed by I. Dee Ott, Feb 12, 2005
// i = i + 1;
But also the actor or user role. // this function can only be run by admin
Is only true if enforced in some way.* Who is meant to use this code?
* How is this code supposed to be called?
* How is it organized?
* How does it do its job?
* Where are the dependencies?
* When is it appropriate to call it?
And finally, the What is also extremely important at a macro level:
* What does this block of code do?
* What are the gotchas?
* What special requirements are necessary?
Obviously, commenting isn't typically as useful at the granularity of a single line of code. But the bigger the block of code these questions document, the more important they are. By the time you get to a class or file level, they're essential.
I think that every programmer should take a course in journalism, so that they understand the critical importance of the 5w's + h. But I'd settle for programmers who actually take the time to write comments. An extra 10% of your time saves your team exponential time in the future, because it cuts down on the communication overhead. There's simply no valid excuse for not writing comments -- only laziness.
I'm constantly trying to find a balance. Definitely the "Why" of a code change is most difficult to self-document.
A style I've used for decades, a bit wordy, but useful in merging change sets, keeps a change log at the top of every module / source file naming the person making a change (who), dating the change (when), tagging it with a pseudo-html tag [wrapping an area of code changes in the body of the source file] (what and where), and at the top, a reference to the failure case or test case (why) explaining why it was necessary to make this change.
When one change spans multiple files, I dedicate one source file to contain the detail, and all the others make reference comments to the one source file containing the detail.
Please love your fellow co-workers, document the why!
I find it useful to think of three four questions as a good checklist when reviewing code. Naming often helps in only one of the above.
In my projects (usually building websites or webapps) I therefore add a 'readme.md' to the root of the project and document general choices there.
Not only can you explain the why and demonstrate usage in a logical manner, but you get some consistency checks from your documentation for free.
You put them everywhere that might be relevant, along with cross-references to other relevant code/documentation. Humans aren't robots -- redundancy is a good thing, because it helps our feeble minds more quickly reinforce key concepts.
Obviously, redundant comments scattered across the code are even worse: out of sight, out of mind.
// foo library throws an extra two bytes at the front of the
// array, even though that isn't up to spec, so we have to
// strip them out here.// HAVE to do it this way to meet IEEE 12345, DO NOT CHANGE
Which would make sense, except that it's the code itself said to indicate this. Or, does he mean for that to be documented in the RCS?
Also, a changelog only documents the why of modifications, not the why of existence of a class, function, etc.
In writing VCS commit comments, I'm finding it most useful to compose these major-event commit events beginning with a <what> word written in all caps:
o COPY out to SHELF <name>
o MERGE in fixes for Ticket <id> from <what node>
o RELEASE to TAG <id> as copy from <TRUNK | BRANCH <name>, MERGE back to TRUNK >
o REVERSE MERGE my bad in Commit #<Rev>, detail in Ticket <id>
Daily commits for work in progress don't get the all-caps treatment. My VCS (or perhaps my understanding of it) doesn't allow me line-level or block-level commit comments; those would reduce my inline comment density.
That said, it's worth noting that the code base has been maintained through three VCSs, and independently annotated by two disjoint Ticketing systems, one of which went through an involuntary Ticket renumbering that was self-overlapping and irreversible. That taught me to prefix my Ticket references with a few "character constants" identifying the Ticketing system "du jour". A bare Ticket ID number has an implicit context; a "fixed prefixed" number communicates context whose value takes quantum jumps in value and user gratitude when the Ticketing system gets changed out.
A cumulative top-of-the-file change log, in reverse chrono order. increases in value with age. Some of the judgement errors I made in years past become clear now, many times tripped across while looking for something else. Candor in commenting pays.
o A discovery and progress narrative, useful to regain working context after long interruption, fit neither for inline comments nor VCS commit comments.
o A research and reference document list
o A related Ticket reference list
o A summary recovery plan and record
o A summary integration plan and record
Your first job as a professional programmer is making the rest of your team more productive by reducing the communication burden. Your second job is understanding old code. The amount of code you personally write is a distant third priority.
You're hitting on all the classic lame excuses. Self-documenting code is a myth, invented by lazy coders who would rather crank out code than write documentation, because it's more fun to write code. They're wrong, but they often don't know that they're wrong, because the same people who suck at writing documentation usually suck at reading code.
Clean code is a necessary, but insufficient precondition to understandability. Documentation is essential, because code can only tell you what -- it can't tell you where it should be used, why you should use it, how it should be used, who who should use it or when it's appropriate. And in any case, your code is never as clean or self-documenting as you think it is.
That said, I have no doubt that you're hearing these things from "experienced" coders, because our industry is filled with "experienced" people who suck at what they do. Also, these things are cliches for a reason. They get repeated a lot.
I think treating comments as something that's done in a separate phase is the wrong mindset. Comments should be integral part of code and therefore change whenever the relevant code changes.
You can obviously get away with not documenting code, but you don't know what it's costing you. However well things are working out now, I can guarantee that they'd be working better and faster for your team if you spent the time to write good documentation.
You may think Martin Fowler is one of these "experienced people who suck at what they do", but you're likely to find yourself part of a small minority.