pcb-rnd knowledge pool
Programming tips: commenting the code
prog_tip3 by Tibor 'Igor2' Palinkas on 2018-03-23 | Tags: dev, tips, programming, style, readable, simple, code, comments, documentation |
Abstract: Code commenting can help a lot in understanding the code and the API, but when used the wrong way, it can become noise.
Since pcb-rnd contains many thousand lines of code with a history tracing back over decades, the existing comments in the code are often not consistent. However, we do have a clear goal what comment style we want to achieve, and finding historical counter-examples shall be no excuse for not following the policies described in this document.
1. Script processing doxygen, vi settings
We write code for the compiler and comments for the programmer. We do not write comments:
- for scripts that try to process the source code
- to store editor settings (e.g. vi indentation)
- for doxygen (never write "/*<", "/** /, "/*! ", "\brief" or other doxygen markup)
- to repeat the file name on the top of the file
- to mark the end of the file
We always use the c89 comment syntax, which is /* the long */ syntax. Do not use the c99 short syntax (//), because it is not portable.
2. What the comment should be about
The comment should explain why the code does something, not how it is done. Many of the later parts of this document will be just a practical application of this generic rule.
For example:
code | bad comment | good comment |
---|---|---|
x = cos(180-angle) * r; |
/* calculate x */
(this comment doesn't help understanding the code, it only explains what's already obvious reading the code) | /* angle swap: compensate for the mirroring (the object is on the other side) */ |
3. Less is more: code is readable
When you have nothing to say, don't say anything. Do not write a comment just to have a comment. Place comments carefully: assume the reader knows C (including libc) and has a generic understanding of pcb-rnd and the libs the given part of the code. Do not state the obvious:
- do not explain the API of the library on the caller's side - the reader shall refer to the library's API comments
- do not use excess function banners with pretty formatted tabular parameter lists
- prefer self explaining code: properly chosen function/parameter/variable names can save a lot of comments
- do not write comments that just repeat what's obvious from the code; e.g. do not write about a parameter of a function if all you can write is its name and type
Example on not commenting the trivial:
code | bad comment | good comment |
---|---|---|
free(cat-> name); | /* free cat's name */ | (no comment required at all) |
4. Less is more: language
Be brief. Avoid using words that do not add to the content. Example:
code | bad comment | good comment |
---|---|---|
#define default_color #0055dd | /* Morning ocean's blue with a slight hint of greenish tone */ | /* Blue */ |
5. Less is more: short code
Sometimes code is so short and trivial, that it simply does not need any comment. Do not be afraid of not writing comments. For example the following function simply does not need any explanation and having one would not speed up understanding it but would slow it down suggesting there's something tricky going on that required an extra comment:
static const char *or_empty(const char *s) { if (s == NULL) return ""; return s; }
6. API vs. implementation
Most part of the code comes in pairs of .c/.h files. This typically means the .h is the API and the .c is the implementation. Ideally a fellow programmer would look at the .h file, understand the API, and would use the code without having to look into the .c file. Thus:
- write the API documentation comments in the .h, not in the .c (this includes description of the structs and functions(
- comments that describe design decisions and features that are important for understanding the implementation, but not the API, should go in the .c
- try to keep the .h comments as short as possible so they don't ruin the overview of the file
7. Assume that common conventions are well known
Thus if you have a function pair of struct foo *foo_alloc(void); and void foo_free(struct foo *f);, you probably do not need to explain them in comments. Same for library function wrapping, like int my_fancy_sprintf(char *dst, const char *fmt, ...); - we assume the reader knows libc and will recognize the sprintf() pattern. But if your sprintf() does something differently than libc, comment on that.
8. You don't have to
Do not write a comment just to "fill it in". If there are 4 variables defined in a block and 3 needed a comment, do not write a comment for the 4th just that it's not left there without a comment. If your functions have 5 arugments from which 3 need explanation, do not write comments about the other 2, just "for the sake of completeness".
If you find a source file that has zero comments and you decide to explore the code and write comments to help your fellow programmers: do not write a comment about that you did not understand something or you did not have info about something. No comment means no info, this doesn't need to become more explicit.
9. TODO, FIXME, XXX
Do not use comments to mark them. Use #warning.
10. High level doc
In-line code comments serve two purposes:
- quick, short info next to the code (e.g. short API description in the .h file)
- a note about a trick or a side effect in the implementation in the .c file, right where the magic happens
For design decisions, deeper insight on the topic, algorithms, etc. there should be separate, high level documentation in the doc/ dir (the comment may reference to that, and the doc may reference to the code). Do not use code comments to write the high level document - use it to write the low level document.