What does it do?
This is the most important question. What does the program do? If I'm trying to fix a bug report that says "it doesn't foo the bar," I need to know if the bar is supposed to be fooed.
Write at least a sentence for each function, a paragraph or more for each module or group of functions, and at least a paragraph for the program itself. In these, explain what the code is supposed to do.
Add a comment after every few lines of code stating what those lines are intended to do, put these in every time you move to a new step of the algorithm.
How does it work
This is only slightly less important than "what does it do?" Admittedly, it's often possible to answer this one by reading the code -- but only if the code isn't buggy.
If you have a loop counting from 1 to 20, I can't tell if you're accidentally or deliberately ignoring element zero. The only way I can know for sure is if you commented the code.
Any code where you can expect an error should have a comment stating your intention. I suggest commenting places where an off-by-one error is possible, anywhere that uses pointers; and anywhere that you have complicated logic, regular expressions, or elegant code that another person might not understand.
Why was it written this way?
Why a stack, not a list? Why in C not in Python? Why repeat-until not while? Good coding, like good gaming, is a series of interesting choices.
Record your choices, and record the reasons for them. Later maintainers (or you!) can then make informed decisions about updating and modifying the code. Circumstances change, and people forget why decisions were made the way they were. The only certain way to remember your reasons is to document them.
Also record bugfixes. Later on, someone will (not might!) be tempted to pull out an apparently useless bit of code that you put in to prevent baz problems in quux machines. And it took you a week to get it right.
"Why this way" comments are essential anywhere you choose to break programming guidelines, lest someone try to "fix" the code to fit the guideline. Besides, you might teach someone something.
Which part does what?
Back to our fooed bar. We have determined that fooing is, in fact, a feature of our program, and that the bug reporter is correct and fooing is failing. How do we fix it? Where do we find the foo module?
The most effective way from the maintainer's point of view is to have some sort of document with the source code which describes the overall structure of the code and explains which code modules support which user-view features.
This doesn't have to be a long document, and can be a simple list like:
Use the same terminology in the features list as the users see, and include at least the main module for that feature in the code list.
Where do I find each part?
You've been thorough documenting your code, and carefully written an index of features and modules. Your maintainer knows he's after foo.c. So where is it?
Include your installation guide, your "make install," or some similar guide in your technical document. Include the location of your makefile -- once the maintainer has fixed your code, she will need to build it!
If your feature index lists functions rather than files, you will need to list which file each function is in. You can list the functions as "foo() in foo.c" in the feature index.
Who wrote it?
Always add this. You never know when you'll get a call from a headhunter offering you a lucrative contract because of a piece of code they saw. Or for more mundane reasons -- someone might need to ask you about the code.
When was it written?
Add this, too. It might be useful to the headhunter -- and it also gives a guideline for what sort of machine you wrote it for. And it may give a clue as to why you put in that apparently useless delay loop.
Final words
This is only one approach to documentation -- most professional technical writers use much more structured and detailed approaches.
If you clearly answer each of these questions, the people who maintain your code will be much, much happier. And technical writers will be able to go through your code for their material, rather than making you explain it all.
Example program
/*
* greet.cc
*
* A 'Hello World' program written to demonstrate code commenting.
*
* Written by Jenn Vesperman
* March 2002
*/
/*
* 'Hello World' was chosen because almost everyone is familiar with it
* in some form or other, so the reader can almost ignore the code
* and concentrate on the commenting.
*
* C++ is chosen partly because it has two styles of comment. Where a language
* offers two comment styles, one can be used for extensive blocks of comment
* like this, for function and program descriptions, and for important
* 'pay attention to this' comments.
* This lets the other style be used for small, embedded comments that are
* used simply to clarify code.
*/
/*
* This program, having only one function, is too small for supplementary
* documentation. It should just compile and run.
* Compile with: g++ -ogreet greet.cc
*/
#include <iostream>
#include <cstring>
#include <string>
/*
* This function finds out who to greet, greets them, and exits if
* the input is the string "quit".
*/
int main()
{
std::string name;
start: // label to use with goto
// Finding out who to greet
std::cout << "Enter a name (one word only), or 'quit' to exit" << std::endl;
std::cout << "> "; // prompt
/*
* Warning: While buffer overflow isn't a problem here, there's
* not actually any protection against, say, getting a gigabyte of
* input with no whitespace in sight. That alone could DoS
* a machine.
*/
std::cin >> name;
/*
* strcmp returns 0 (false) if the two strings are the same.
* Therefore we use a comparison with 0, rather than simply
* using 'if !strcmp'.
* We're using strcmp() for a reason, here: As an example.
* As such, we're making a point of mentioning the choice, for those readers
* who are wondering 'why?'
*/
// is it quit? If not, greet then return to start
if (!(std::strcmp(name.c_str(),"quit")==0)) {
std::cout << "Hello " << name << std::endl;
/*
* We use the 'goto' construct rather than a while or do-while
* because we need to demonstrate commenting when we break the
* rules. There's no other reason for it.
*/
goto start;
// if it is quit, exit with the return value 'true'.
} else {
return 1;
}
// Should never get here. Return false if we do.
return 0;
}
Jenn Vesperman is an Open Source coder and coordinator of Linuxchix.
Note: Comments are owned by the poster. We are not responsible for their content.
Show me your flowcharts and conceal your tables, and I shall continue to be mystified. Show me your tables, and I won't usually need your flowcharts; they'll be obvious.
Give me that, and a bit of a roadmap about where code lives, and I've got a fighting chance. Otherwise I'm going to spend a lot of time and effort figuring out the basics, and I'm a heck of a lot more likely to break things if I have to make changes.
OT: Actually provide an architecture and user doc!
Posted by: Anonymous Coward on April 03, 2002 02:11 AMare a couple of very important points:
1) As a user, I might not care (that much) about the code documentation. Quite often, the implementation details are beyond my horizon anyway, documented or not. What I really need
is a) user doc, b) FAQ, c) mailing list in order
to get started, not get stuck and resolve remaining issues. As an example, I consider
Linux quite awkwardly documented internally,
yet with sufficient external user documentation
available (not always provided by the kernel hackers themselves).
2) As an interested developer, I am looking for
an architecture. Most of the time, there ain't any. Often the 'architecture' goes no further than a few ramblings and the original napkin everything fits on. Nowadays there's no excuse for not providing the basic goals, the essential features, the underlying third-party pieces etc.
I'd also expect a (set of) good UML diagram(s),
and prefer that over the well-documented code.
The main reason is that the body of code is often
too large to digest in a limited amount of time.
This is hampered by most UML tools being proprietary and expensive. But check out ArgoUML for a free one.
3) I suspect two reasons for badly documented code: a) 'hacker' attitude (if you're dumb, this code ain't for you) and b) someone else could steal it, if they only understand it, for competing or proprietary purposes.
To the coders: Try to be honest about your motivation not documenting things properly.
Then try to understand why a) and b) are quite shortsighted arguments.
Last but not least, I can assure you that your project can only grow so much unless it is well
documented. Even if you consider it a pain in the ass, it may be the most valuable asset of your project.
Many developers get some revenue from writing
articles ro books on they creations.
As another example, check out what the JBoss project does with user documentation. They are actually pay-for items.
Depending on where you stand on this policy, you will either:
A) Say that this attitude is the undoing of the project since people will avoid it, or
B) Consider it a serious business model.
But by feeling strongly about the issue, you will
discover how important the documentation is for you.
Consider documentation promotional material.
Based on your project and its documentation, you might be the first to be asked for professional services around it.
#