What does style look like, part 5

Continuing the discussion of "style"..

The other day, I talked a bit about how comments affect the "style" of a piece of code.

Today, I want to talk  about the headers that accompany each routine and file.

And yes, every routine and file needs to have a block comment header around it.  If you don't , then the next person who gets to maintain the file curses you.

At a minimum, the file header should have a brief summary of what the code in the file does, and probably a copyright notice.

For subroutines, the name of the routine and a brief (or maybe not-so-brief) description of what it does.

Beyond that, anything goes.  I've seen literally dozens of variants of styles.  Some of my oldest code has the following for routine headers (written in Bliss36, so ! is a comment character):

! Copyright (C) 1982, Lawrence Osterman ! CHANGE LOG!------------------------------------------------------------------- ! 9 Nov 82 OSTERMAN Added a check to see if you are watching !                   a user when you auto add them.

Each routine had: !++! Get_Accounts_JFN : ! ! Input: !    None! Output: !    None ! Side effects: !    None! !--  

Not the cleanest, but... 

Unfortunately, I don't have any good examples of a module header, typically one looks like:

/*++ *        <Copyright Notice> * *  Module Name: *        <Name of module filename> * *  Abstract: *        <Brief abstract for module> * *  Author: *        <Authors name and email> * *  Environment: *        <intended environment for this module (optional)> * *  Notes: *        <optional notes> * *  Revision History: * *    <Author> <Change Date> <Change Description> --*/ 

The "Author" field can be controversial - Since modules can change owners, it's not clear if there's long-term value for the owner field.  Similarly, the revision history is controversial.  It can be extraordinarily useful, but only if maintained diligently.

My earliest copy of Microsoft documentation (from 1984) has the following example of a subroutine header:

/***    name - very brief description * *     <description> * *     name    (parm1, parm2, parm3, ..., parmn) * *     ENTRY   parm1 - description *             parm2 - description *     EXIT    parm3 - description *             . *             parmn - description * *     <discussion of internals, one or more paragraphs> * *     WARNING:    <discussion of limitations, gotchas, etc.> * *     EFFECTS:    <'none', or discussion of global effects> * */

Again, this was 1984, but in general, the concepts involved are the same.  This block has all of the requirements for the routine header included.  Beyond that, it's all esthetics.

Here are some styles I've seen (building on the early coding standard above).

/*++    name - very brief description * *     <description> * *     name    (parm1, parm2, parm3, ..., parmn) * *     ENTRY   parm1 - description *             parm2 - description *     EXIT    parm3 - description *             . *             parmn - description * *     <discussion of internals, one or more paragraphs> * *     WARNING:    <discussion of limitations, gotchas, etc.> * *     EFFECTS:    <'none', or discussion of global effects> * --*/

As I said, this is all about esthetics, so everyone has their own favorites.

/********************************************************************\*                                                                    **    name - very brief description                                   **                                                                    **     <description>                                                  **                                                                    **     name    (parm1, parm2, parm3, ..., parmn)                      **                                                                    **     ENTRY   parm1 - description                                    **             parm2 - description                                    **     EXIT    parm3 - description                                    **             .                                                      **             parmn - description                                    **                                                                    **     <discussion of internals, one or more paragraphs>              **                                                                    **     WARNING:    <discussion of limitations, gotchas, etc.>         **                                                                    **     EFFECTS:    <'none', or discussion of global effects>          **                                                                    *\********************************************************************/

This one's hard to maintain, because of the trailing *'s, but it is pretty.  It might do for a file header.

And of course, there's the version with just C++ comments:

//-----------------//    name - very brief description////     <description>////     name    (parm1, parm2, parm3, ..., parmn)////     ENTRY   parm1 - description//             parm2 - description//     EXIT    parm3 - description//             .//             parmn - description////     <discussion of internals, one or more paragraphs>////     WARNING:    <discussion of limitations, gotchas, etc.>////     EFFECTS:    <'none', or discussion of global effects>////---

In general, if I had to come up with rules for what makes subroutine headers work, I'd say that they had to be descriptive, they had to include documentation for all the parameters, they had to have some consistent style to differentiate them from normal code.

One other thing that effects subroutine headers is the existance of tools like AutoDOC.  If you choose to use an auto-documentation tool like autodoc (and there are dozens of them), then your subroutine headers can form the basis of the internal documentation for your module.  It doesn't change the fact that you've got to have design specifications, but it does provide an external reference tool.

So lets go back to the commented code and add some header and routine comments:

/*++ *        <Copyright Notice> * *  Module Name: *        MyProgram.c * *  Abstract: *        This program implements a solution to the Josephus problem.   *        Code taken from Robert Sedgewick's "Algorithms in C, Third Edition", *        Program 3.13, on Page 103. * *  Author: *        Robert Sedgewick * *  Revision History: * *    LarryO             11/12/2004     Restructured for weblog posts. *    Robert Sedgewick   <Unknown>      Created.   --*/#include "list.h"/*++    main - Implements the Josephus problem and prints the result. * * *     main (cArg, rgszArg) * *     ENTRY   cArg - number of arguments. *             rgszArg - array of cArg null terminated strings *     EXIT    None. * *     <discussion of internals, one or more paragraphs> * * --*/main(C cArg, SZ rgszArg[]) {    I iNode;    I cNodes = atoi(rgszArg[1]);    I cNodesToSkip = atoi(rgszArg[2]);    PNODE pnodeT;    PNODE pnodeCur;    InitNodes(cNodes);    //    // Create a list of cNodes nodes.      //     for (iNode = 2, pnodeCur = PnodeNew(1); iNode <= cNodes ; iNode++)     {        pnodeT = PnodeNew(iNode);        InsertNext(pnodeCur, pnodeT);         pnodeCur = pnodeT;     }    //    // Walk the list of nodes, freeing the node that occurs at every cNodesToSkip nodes in the list.    //    while (pnodeCur != PnodeNext(x))     {        for (iNode = 1; iNode < cNodesToSkip ; iNode++)         {            pnodeCur = PnodeNext(pnodeCur);        }        FreeNode(PnodeDeleteNext(pnodeCur));    }    //    // Print out the value of the current node.    //    printf("%d\n", Item(nodeCur));}

That's quite different.  Tomorrow, we start looking at naming conventions.