129

In languages that distinguish between a "source" and "header" file (mainly C and C++), is it better to document functions in the header file:

(pilfered from CCAN)

/**
 * time_now - return the current time
 *
 * Example:
 *  printf("Now is %lu seconds since epoch\n", (long)time_now().tv_sec);
 */
struct timeval time_now(void);

or in the source file?

(pilfered from PostgreSQL)

/*
 * Convert a UTF-8 character to a Unicode code point.
 * This is a one-character version of pg_utf2wchar_with_len.
 *
 * No error checks here, c must point to a long-enough string.
 */
pg_wchar
utf8_to_unicode(const unsigned char *c)
{
...

Note that some things are defined in the header only, such as structs, macros, and static inline functions. I'm only talking about things that are declared in a header file and defined in a source file.

Here are some arguments I can think of. I am leaning toward documenting in the source file, so my "Pro-header" arguments may be somewhat weak.

Pro-header:

  • The user doesn't need the source code to see the documentation.
    • The source may be inconvenient, or even impossible, to acquire.
    • This keeps interface and implementation further apart.

Pro-source:

  • It makes the header a lot shorter, giving the reader a birds-eye view of the module as a whole.
  • It pairs the documentation of a function with its implementation, making it easier to see that a function does what it says it does.

When answering, please be wary of arguments based on what tools and "modern IDEs" can do. Examples:

  • Pro-header: Code folding can help make commented headers more navigable by hiding the comments.
  • Pro-source: cscope's Find this global definition feature takes you to the source file (where the definition is) rather than the header file (where the declaration is).

I'm not saying don't make such arguments, but bear in mind that not everyone is as comfortable with the tools you use as you are.

2

8 Answers 8

133

My view...

  • Document how to use the function in the header file, or more accurately close to the declaration.

  • Document how the function works (if it's not obvious from the code) in the source file, or more accurately, close to the definition.

For the birds-eye thing in the header, you don't necessarily need the documentation that close - you can document groups of declarations at once.

Broadly speaking, the caller should be interested in errors and exceptions (if only so they can be translated as they propogate through the layers of abstraction) so these should be documented close to the relevant declarations.

8
  • 13
    +1 - ie document the interface in the header. The Gory details of the how and why in the source. Jun 15, 2011 at 12:30
  • 2
    For library headers where there is no source available maybe add pre and post conditions, etc... to help with testing. Plus add O(n) performance if it makes sense, so library users can choose wisely. Oct 13, 2015 at 0:57
  • Naturally, sometimes declaration and definition are one and the same. Dec 19, 2018 at 14:59
  • @Deduplicator - when the same rules still lead to the right thing even in the special case, why echo those rules for every special case? Surely a deduplicator shouldn't want that?
    – user8709
    Dec 20, 2018 at 2:28
  • 1
    @Deduplicator - of course that's a massively overthought rationale for not following your advice, but I'm sticking with it.
    – user8709
    Dec 20, 2018 at 5:23
50

If you're going to use a tool such as Doxygen (note in the first example, that really looks like a Doxygen comment because it starts with /**) then it doesn't really matter - Doxygen will look through your header and source files and find all the comments to generate the documentation.

However, I'd be more inclined to put the documentation comments in the headers, where the declarations are. Your clients are going to deal with the headers to interface with your software, the headers are what they will be including in their own source files and that's where they will be looking first to see what your API looks like.

If you look at most Linux libraries for example, your Linux package management system often has a package that contains only the binaries of the library (for "normal" users who have programs that need the library) and you have a "dev" package that contains the headers for the library. The source code is not normally supplied directly in a package. It would be really cumbersome if you would have to get the source code of a library somewhere to get the documentation of the API.

3
  • 6
    +1 - with a provise that even if you use Doxygen, that doesn't mean you're never going to read directly from the source. Doxygen annotations are even sometimes useful as standard patterns to grep for, and it's handy if the annotation you find is close to the code it describes.
    – user8709
    Jun 15, 2011 at 7:38
  • 1
    @Steve314 ofcourse I didn't say that you'd never want to look at the source code of some library - but that wouldn't be the first place you'd look for what the API looks like and how to use it.
    – Jesper
    Jun 15, 2011 at 7:41
  • I would also advocate to keep everything related to the API in the header (or at least in either the header or the source), since it would avoid potential incoherence when updating the documentation in one place and not the other.
    – jopasserat
    Dec 10, 2014 at 12:21
18

Assuming this is code within a larger project (where developers will be moving between source and headers often), and providing this isn't a library/middle-ware, where others may not have access to the source, I've found this works best...

  • Headers:
    Terse 1-2 line comments, only if they're needed.
    Sometimes comments above a group of related functions is helpful too.
  • Source:
    Documentation on API directly above the function (plain-text or doxygen if you prefer).
  • Keep implementation details, only relevant to a developer modifying the code in the body of the function.

The main reason for this is to keep the comments close to the code, I've noticed docs in headers tend to get out of sync with changes to the code more often (of course they shouldn't, but they did in our project at least). Also developers may add documentation at the top of functions when they make some change, even when there are docs in the header, causing double-ups or useful info only to be in one of the doc-strings.

Of course you can pick a convention and ensure all devs follow, I just found the convention above the most natural-fit and causes least trouble to maintain.


Last of all, for large projects - there is an inclination not to make small corrections in a header when you know its going to cause potentially 100's or 1000's of files to re-compile when others update version control - slowing down bisecting errors too.

1
  • thanks for giving your reasoning for the decision. comments getting out of sync is a concern I share and I definitely also see the header changing being annoying. Feb 16 at 10:49
16

We solved this problem (about 25 years ago) by creating a bunch of #defines (e.g. public, private, etc., that resolved to <nothing>) that could be used in the source file and were scanned by an awk script (horrors!) to auto-generate the .h files. This mean that all of the comments lived in the source and were copied (when appropriate) into the generated .h file. I know that it's pretty Old School, but it vastly simplified this kind of inline documentation.

6
  • 3
    hmm i know this style of thing can be useful, but from my standpoint I always found that kind of documentation to be downright annoying... Apr 23, 2015 at 9:42
  • 2
    To paraphrase Donald Rumsfeld (a man I did not like), "You program with the tools you have, not with the tools you wish you had." Every language I've worked with in the last 40+ years has had at least one major wart (if not more). Our solution a) worked, b) used tools that existed at the time, c) let us spend our time getting revenue-generating code out the door. Apr 23, 2015 at 21:56
  • Even though I probably wouldn't opt for this, its an interesting way to handle comments in headers. Would the generated headers be in version control? or is this some release process for making redistributable source? (but not used by the developers)
    – ideasman42
    Oct 12, 2015 at 13:24
  • Oh, I've seen the same pattern recently in a project started in ≥ 2000 and they were so proud of their clever invention…
    – 5gon12eder
    Oct 12, 2015 at 22:41
  • 3
    In our case we did not keep any of the generated files under version control since they were easily and directly (re-)derived from tracked files. Oct 13, 2015 at 15:22
8

Comments are not documentation. The documentation for a function might typically be 2K of text, possibly with diagrams - see for example the documentation for functions in the Windows SDK. Even if your comment-to-doc allows such a thing, you will be making the code that contains the comment unreadable. If you want to produce documentation, use a word-processor.

3
  • 2
    update, it is alot easier to document these days (with stuff like Qt creator out there) to just document the doxygen (or clone) way, for example, in qtc you just hit the / key a few times before the comment and half the work is done for you. Because of things like this, i doubt people will want to jump to a word processor just to document their code. I used to do this, granted, back in 2005, but I would never do that now. Even using an html editor seems to be quite archaic now. Apr 23, 2015 at 9:47
  • 1
    @osirisgothra Doxygen-"documentation" may be easy to do, and certainly produces a lot of quickly written LOCs, but the value of the produced "documentation" remains disputable in the vast majority of cases. Doxygen comments are neither good documentation (almost all the crucial details are genarlly missing), nor are they good comments (they tend to repeat what's already obvious from the signature). I think nbt is right in saying that real documentation is best not mixed with code because it's detrimental to code readability. It'll get out of sync anyway, there's no silver bullet for that. Oct 12, 2015 at 13:41
  • 1
    A few years ago I was upset that Wolfram Mathematica didn't have any docstring-like facility. I just did it in a Markdown document. Turned out to be the best documented project I've ever worked on. It was so much fun to write about high-level stuff, include graphics and so on. So although I didn't realize at the time, having the documentation separate can yield much more readable documentation. Mar 2, 2021 at 14:29
7

In my (rather limited and biased) opinion, I am pro-source code way of thinking. When I do bits and pieces in C++, I usually edit the header file once and then I never really go back to look at it.

When I place documentation in the source file, I am always seeing it when I'm editing or reading codes. I guess it's a thing of habit.

But that's just me...

2
  • 1
    Does not work very well if all you have is a compiled library and the header file. In that case, more info in header is a good thing because its the only interface documentation you have. Jun 15, 2011 at 12:31
  • 1
    you could generate documentation with doxygen - it takes it from .c files as well. Thus you could distribute documentation easily with compiled libraries. But the trouble would be with IDE that can parse header files and give you documentation while using the function... But perhaps it could solve some deploy script which would copy function comments frm .c into .h... Jan 17, 2017 at 10:51
4

If the stakeholders of your source code (say, a small library) consists of "users" (fellow developers who will use your library's functionality without getting involved in its implementation) and "developers" (you and other developers who will implement the library), then put the "users' information" in the header and "implementation note" in the source.

With regard to the desire to not change the header files more than is absolutely necessary - I suppose if your library is not "in a crazy flux of changes", that the "interface" and the "functionarity" will not change much, and neither should the header comments change too frequently. On the other hand, source code comments will have to be kept synchronized ("fresh") with the source code.

0

The whole point of using doxygen is that you generate documentation and make it accessible somewhere else. Now all that documentation in the headers is just garbage which makes it more difficult to quickly spot the required funciton declaration, and maybe its overloads. One liner comment is maximum which should go there, but even that is bad practice. Cause if you change documentation in the source you recompile that source and relink. But if you put docs in the header you really do not want to change a slightest thing in there, cause it is going to trigger significant part of project rebuild.

2
  • 1
    this doesn't seem to offer anything substantial over points made and explained in prior 7 answers
    – gnat
    Jul 5, 2017 at 9:51
  • 2
    @gnat from prior 7 answers only one is in favour of code against headers. And that one is giving totally different argumentation.
    – Slava
    Jul 24, 2017 at 7:34

Not the answer you're looking for? Browse other questions tagged or ask your own question.