The Great Debate
…documentation. One of my pet peeves… It seems these days that there is this big push for “self documenting code” instead of “actual documentation”, the justification being that “it’s totally obvious what this function does and if you don’t see it then you’re a bad person.” It seems that this line of thinking is becoming accepted more and more these days. Or maybe it was always this way. Either way, this ends now. Surely today marks a great change, and centuries from now scholars will remember the day that a true visionary stepped up and ended the madness. Or not. Either way, I would like to make a case for documentation.
Shake That groove_thing *
Take this function:
groove_thing * shake_that(size_t size, groove_thing * to_shake);
So, what does it do? It returns a “shaken” groove_thing pointer, and takes a size_t and groove_thing pointer as arguments. Does it malloc a new groove_thing based on this? Does it return the passed in pointer to avoid a malloc? is the size_t the sizeof(groove_thing)? Is it some amount of bits to shake? Who knows.
/** * performs a bitwise shift of the value of groove_thing * @param size the amount of bits to shift * @param to_shake the groove_thing who's value should be * shaken. This pointer should be pre-allocated. * @return the passed in pointer */ groove_thing * shake_that(size_t size, groove_thing * to_shake);
Much better, right? What’s that? “Of course that function requires documentation, I only omit documentation on obvious functions” you say? About that…
Get That foo *
Now take this function:
foo * get_foo(bar * to_access);
Seems obvious, right? It gets a foo pointer from the passed in bar pointer. Couldn’t be simpler right? Tell me this: what happens if to_access->foo is uninitialized? Once again, some documentation would be nice.
/** * returns to_access->foo. If this pointer has not been * allocated, calls malloc(sizeof(foo)) * @param to_access The bar pointer who's foo should be * retrieved * @return a pointer to to_access's foo. to_access * retains responsibility for this pointer */ foo * get_foo(bar * to_access);
Some totally not useless info in that. Now you know that you don’t have to worry about memory management of the foo pointer. This wouldn’t have been a safe assumption otherwise.
But Comments Lie!
Yes, sometimes they do. You know what else lies? Function names. They also may not be able to tell you if they’re deprecated, or if they only exist to support legacy applications and that you should be using the newer faster more secure version. However, it’s a lot easier to correct a comment because it no longer matches the behavior than it is to rename a function because the name no longer matches the behavior.
It’s Not Even That Hard
Modern IDE’s have built in support for commenting. The examples in this post use the format provided by NetBeans. Just type /** and press enter in front of a function name and it’ll automatically create the comment block and add @param and @return flags. You can even throw in things like @throws, and fancy HTML formatting to make it even better. When you click on a function in code all of this will show up in the documentation pane in your IDE.
It takes all of 1 second to write a halfway decent comment, but the time it will save you researching what dmp_sqp_do_foo_gently() does is priceless.