The Art of Code Documentation
You know, one day at work I was handed a program by my boss. He said, "Drew, see if you and Mike can figure out what this does and if it will be of any use to us." I said "Okay" and took it. The program was from two other employees in the small start-up company I work for who had quit a day or two ago. My boss had asked for what they had accomplished so far and the small stack of papers on my desk was the result. I took the main program file printout and started to look through it. After the first page, my heart rate began to quicken. A few more pages and I began to simmer. When I finally reached the last of the 15 pages I wanted to scream.
I walked into my bossís office and asked if the two guys were gone for good. He nodded an affirmative. I showed him the paper and explained to him that this job could take a few weeks of work. He looked at me, puzzled. He hadnít noticed. I handed him the paper and let him look through it. Nothing wrong, he said. I finally pointed it out myself:
"There arenít any comments, Chief."
This is a good example of what happens to team players when the other team members donít do their job correctly. In essence, I was handed a program filled with lines of code that had absolutely no meaning to me at all. This scenario only happened a week ago, but Iím still busy at my desk tracing routines, finding functions, tracking variables Ė and adding in my own comments. Luckily for me, my boss had been a programmer of old and lessened our other task loads so we could better focus on our current project. Can we do this? Yes. It will just take a lot more time than if the code were properly documented.
The purpose of this article is to show programmers, experienced and inexperienced alike, how code should be documented. Itís not just about you; itís about the other members of your team. Itís about being nice to them and letting them be able to understand your code. Itís about keeping them from having to hunt you down so they can kidnap you, strap you to a chair, and have you divulge the secrets to your program. You wouldnít want that, right? Didnít think so.
NOTE: All commenting in this article is done using only C++-style comments (i.e. // and not /* ... */).
Wait a minute, wait a minute Ė what in the world is this documentation stuff? We donít document, we comment. What is this? To me, commenting and documenting are two different things, so allow me to explain.
Commenting code is the simple part. A comment resides near the line of code that you wish to explain. For example:
Of course, the previous code would assume x had a value of zero, but thatís irrelevant for this example. Simply put, you comment to explain a line or two of code, nothing more. Something like this does not help at all:
Whoa. While the first three lines do not need any extra comments thanks to descriptive variable names (covered later), whatís that last line do? Obviously, thanks to the comment, it has to do with filling the structure. But fill it with what? That line, although related to the last comment, still deserves a comment of its own:
Thatís much better! Could we have guessed that? Probably. But why bother take the time to guess when you can be told outright what it does?
Commenting, as shown above, is a term best used when describing single or multiple lines of related code. Again, not too many lines of code should be described by one single comment.
When you document code, you take on a wider view. I refer mainly to documenting in this article because it is a term that assimilates commenting into it. A commentation can be referred to as a documentation, but not vice-versa. Why? Because while the scope of a comment is only a few lines, documentation encompasses a whole function, or list of functions, or list of variables, or even a whole program. Here is an example of documentation and commenting put together:
This is what a documented function should look like. It has a header explaining the purpose of the function as well as what each variable is used for. Inside the function body there are comments telling you what everything does.
Now, look at the function and pick from below what statements describe it correctly:
First, scroll up and reread the definition I gave you on documentation. Then decide. If you chose A and C, then youíre correct. Give yourself a pat on the back. Could you get away with B? Maybe, but then you get the picture of a few measly lines of comments, not a whole header. Throughout the article Iíll change between commenting and documenting. Just remember that anything I say about commenting can be applied to documenting, but donít try to switch that around. Things could get ugly.
Now that we cleared that up, letís move on so I can start to show you how to comment and then expand upon that and document.
Before we really begin, Iíd like to take a moment and tell you why you should comment. As I have seen it, most people think commenting is a waste of time and resources. Iíve heard things like "you should be able to read code like English" or, "I donít want people to know how my program works". Yeah Ė industrial spies are in your high school computer science class. Other people donít even have reasons; theyíre just too lazy to do it in the first place.
Commenting has many pluses. Not only does it let you track your work over a period of months and let you come back and remember what a certain function does; it can help you point out mistakes. For example, hereís a post off of GameDev.net message boards in the thread I started "Do You Comment?":
If that example doesnít give you enough reason to start commenting, then just donít waste your time reading the rest of this article. If you donít want to comment, thatís fine with me. Just donít complain when you have your co-worker knocking on your door every five seconds to ask you yet another question: "What is this supposed to do?"
The basic idea of commenting is to explain little snippets of code. To start, Iím sure you all know how to write a comment:
Things to notice are a space after the two slashes "//" which start a comment, no capitalization is needed and no punctuation is needed. Now, if you had more than one sentence:
Itís generally a good idea to follow normal punctuation up to the end. This is simply for clarity, as it makes it easier to read and understand if you can tell where a sentence stops and another begins. Notice I didnít bother including a period at the end, since you really donít need it.
The next important thing is a little gem known as white space. Because all spaces and comments are wiped out for compilation of the actual executable, white space is an extremely simple way to make your commented code easier to read. Here is a piece of code lacking white space:
Very bundled up, and during late night coding sessions, I can guarantee you the comments and the code will blur together into an unreadable mess J. But add in the magical white space and:
Viola! So much easier on the eyes as well as making individual statements easier to pick out, which is good.
I also like to tell people not to explain more than two unrelated lines of code with one comment. This is a good example.
The problem with this is that by the time youíre done reading the comments, you get hit with the code all at once and say, "Wait Ė what was this for again?" And then you have to look back up and search the comments for the description you want. Yuck. But by commenting each function and throwing in some good Ďol white space:
Now thatís a smooth read. As soon as you finish the comment, you can check out the code, and then move on to the next line. If you ever have a question about the code, the comment is right there. Of course, the opposite would be a few related lines of code. It would be really stupid to do this:
Not only is it a huge waste of time, itís repetitive! Repetitive comments are the worst things you could possibly do. If you find yourself repeatingÖ yourself (errrÖ.) then itís best to just group the lines of code under one general comment like this:
This is allowable because all three variables are counters, and theyíre all doing the same thing, so you only need to say it once.
The last little trick I like to use is the Tab key. Itís great for ordering your code and comments in a legible way. Take, for example, this section of code:
Aw man Ė my fingers were itching to press that Tab key while writing that. What a mess. The declarations flow right into the variables, which flow right into the values, which flow right into the comments. Wonderful if you want to read the code like a book instead of line by line but who has reason to do that? With the Tab key, referencing becomes much easier:
Ta da! Now we can fully distinguish between the definitions, the variables, the values and the comments. Sure, color coding helps but if you ever get blurry vision (late night or anything else) the un-tabbed code will be a pain to read.
When you document code, you take what you know of commenting and apply it on a broader scale. A simple, commented program will have a comment for every other line of code that needs explaining. Thatís good for the developers Ė it doesnít clutter it up and it takes less time to scroll through it and change things. But once you complete a project and go to store it away, rudimentary comments arenít going to cut it. When you document, you explain things in greater detail so that anyone who comes to continue your work in some fashion months or years later can understand what you did.
Weíll start off with program headers. In the program header the person reading the file gets a quick overview on what they program is supposed to do. It is important to get the person in the right mindset so he or she can understand why you coded the way you did. The description should be short, yet detailed. After the description comes the name of the creator and then the date. After that you can add a little section for notes Ė any oddities you may have thrown in at the last minute or any incomplete areas of the program. Hereís an example of a program header I use:
/////////////////////////////////////////////////////////////////////////////////// //-----------------------------------WinSock.cpp---------------------------------// // v 1.2 // // // // This program will initialize WinSock and then attempt to open a socket and // // send info to the other computer. This is the client portion of the client- // // server model. After the data has been sent, the program will close the socket // // and save the data to a file // // // // Created by: Drew Sikora // // Created on: 9.24.00 // // // //--------------------------------------Notes------------------------------------// // // // The file save feature has not yet been implemented in this version. Also, we // // are trying to trace a bug in the send/receive section. Sometimes the packets // // are dropped for no apparent reason (not net congestion). Just re-run the // // program. // // // /////////////////////////////////////////////////////////////////////////////////// ////////////////////// // the program code // ////////////////////// /////////////////////////////////////////////////////////////////////////////////// //------------------------------------WinSock.cpp--------------------------------// //-----------------------------Copyright Drew Sikora, 2000-----------------------// ///////////////////////////////////////////////////////////////////////////////////
With the header (and the footer), we can just read the description and know what the program will do, from start to finish. Again, itís not long, but it manages to tell you everything the program does. A little habit of mine is to keep the sentences from running against the slash marks like this:
Ö. it isnít quite//
Instead, I like to leave a space, even if it means taking out the whole word:
Ö. it isnít //
Of course, this is the best-case scenario:
Ö. it isnít quite //
But that doesnít always happen. Anyway, thatís just me, you may not care. Also notice the header is completely boxed in, to separate it from the rest of the comments in the actual program. This is a good way to document. Another separator I use is the dash (-). They do a good job of breaking up comment groups inside the closed boxes. Finally, look at the footer, which marks the end of the program file.
Another use for a header is at the top of a function. This time, there is a function description, and a variable list. A notes section, as before, is optional depending on whether or not the function has any extreme qualities you canít fully describe through your comments. Hereís an example of a function header.
The function header serves mainly the same purpose as the program header, to let the reader know exactly what the function does, and why it does it. A CreateWindow() function has a lot of parameters that donít change from window to window, so why retype them all? This function will do it for you. The description tells you this. Then you get the variables section so you know what each variable is supposed to do or represent. Notice I make the function declaration a part of the header-bounding box. This makes a nice transition from header to function, making the header seem more a part of the function itself. And then the function is ended with a comment to denote the close bracket. This is especially helpful so you donít need to look back up at the end to see what function it is.
Of course, documenting doesnít end here. The next step is to go back through the code and add in additional comments to explain certain areas in more detail. For example, a few months down the road, this may not cut it:
That might be fine during development, but these things tend to fade from memory in light of other projects. Therefore, when you decide to look it over again, seeing this might be more beneficial:
As you can see, not all the various fields worked as named. The field packinfo could have been named msginfo, but then you could figure it was some message setting. And you could have thought packname was used to ID the packet in the program, not on the server.
Well, this just about wraps up documentation, as well as the article. But I have one more section for you filled with odds and ends I couldnít find a place for.
Odds Ďn Ends
In this section Iíll just mention a few things off the top of my head that really didnít fit in with my other section topics.
There will be times when youíll want to completely separate some sections of code from one another. I touched on this with the bounding box of slashes (/) but not in the actual program. Here are a few ideas:
/////////////////////////////////////////////////////////////////////////////////// // Defines // ///////////////////////////////////////////////////////////////////////////////////
Personally, I prefer the middle option. It looks the nicest. Of course, there are many more ways to do this.
Hereís another idea I got from my thread on GameDev. In a team effort where you have many people operating on the same source code, passing it around, changing it, etc. in the comments add a short tag identifying the programmer. For example:
Yes, it looks like HTML tags, but whatís wrong with that? Now everyone knows who edited which part of the program. Iíve never used this system myself, so I canít recommend it. My only concern is things starting to get mixed up when another programmer modifies the code set in place by the former programmer and you end up with stuff like this:
I make the first iteration, then MM comes along and changes half of it, and then AO changes the second half. If you try this, make sure the system you develop takes into account things getting mixed up.
Self-Control (over commenting)
Yes, in this case, there can be too much of a good thing. I know this wonít be that much of a problem for most of you, since before reading this article you probably never commented at all that much anyway, but I feel impelled to dispense with a warning: Too many comments is bad. Well, maybe.
It ultimately boils down to your commenting style. If you have a clean style, then you can probably comment every single line and it would still look good. But if you get sloppy, too many comments will start to get in the way of the actual code. The purpose of comments is to make code easier to read, but if you use too many comments and donít place them correctly, youíll undermine your efforts by making the code harder to read because you canít tell the difference between the code and the comments. And believe me, color coding will not make a difference.
Descriptive Variable Names
For all the lazy programmers out there (including me), hereís a way to decrease your commenting workload Ė using descriptive variable names. What a concept. For example, instead of using the variable z to hold a number that represents the current amount of money, why not try current_amt, or currentMoney?
The same rule applies to any type of name Ė function, structure, instance, etc. As long as the variable name can describe what itís supposed to do, you donít have to describe it yourself. Ainít life grand?
I hope that this article has helped you decide on how to best comment your code to make other peopleís lives easier. For all those reading this that have never commented before, I hope that you take to heart most (if not all) of what I said in here and get into the habit of commenting (itíll impress the Boss, believe me).
The greatest challenge of writing this article was trying to tailor it to meet the individual needs of everyone who would be reading this article. Unfortunately, there is no sort of generic commenting style I could utilize for my examples, so I simply used my own. Whether or not you like my style is irrelevant Ė there are many other ways to get it done just as nicely. But I hope you at least consider some of what I did with the comments and apply it to your programs; I can guarantee a better look and feel. As a last note, I know some of what I said cannot be applied to everyday problems Ė there may be a time where one line of code does require a few lines of comments. All my "rules" were stated with a "simple case" scenario in mind.
So, if you have any questions or comments, please post them to this thread. Happy commenting.
Special Thanks To: