COMMENTS & STYLE

 

You must include documentation on the code that you write, specifically file headers, struct/class headers, function/method headers and inline comments. This file contains some examples to guide you.

Don't underestimate using good styles and comments. It's very practical for upper division classes and also for your career.

If the comment has good clarity and contains all the essential information needed, it is a good comment. Style is more defined, but there is still room for flexibility. These are merely suggestions to having good comment/style.

You have much flexibility on the format of these headers. If you have a format that acceptably conveys the required information in a way that you are used to using, feel free to continue to use that format. The assignments throughout the class will have varying format examples which are all acceptable.

1. File Header

Each file must have a header with your login, name, filename, and file contents description. You can format it any way you like, but the filename and file contents should be there (login and name just makes it easier for us).

Example File Header:

/****************************************************************************

                                                Tracker Wonderdog
                                                CSE 12, Current Quarter
                                                Due Date
                                                cs12xzz
                              Assignment XXX

File Name:      hw1.c
Description:    This program reads strings and integers from the user,
                processes them, and prints them back to the user.  Program
                terminates when user enters ^D.  At termination, program
                outputs sizes of various types of C/C++ pre defined types.

****************************************************************************/

or....

File Header Example:

//==========================================================================
// cs12xzz                         Homework XXX              Tracker Wonderdog
//--------------------------------------------------------------------------
// File: Tree.c
//
// Description: Contains the Node structure and the member functions of
//              the Tree class.
//==========================================================================

2. Struct/Class Headers

Example Struct/Class Header:

//=========================================================================
// struct Node
//
// Description: Implements the node of the binary search tree data structure.
//     Each node contains two children, the left child which contains
//     data "less than" the data of the current node, and the right child
//     which contains data "greater than" the data of the current node.
//
// Data Fields:
//     data (Base *)  - holds the data stored in the current node
//     left (Node *)  - the left child
//     right (Node *) - the right child
//
// Public functions:
//     delete_AllNodes - deletes all the children of the current node
//     insert - inserts a data into the current node or to one of the
//              children of the current node
//     Write - display the current node
//     Write_AllNodes - display the current node and all its children
//
//==========================================================================

3. Function Headers

Each function header must contain at least the function name, description, the parameters (input), and return value (output). Result and side effects could be part of the description. Example:

/*---------------------------------------------------------------------------
Function Name:                clrbuf
Purpose:                      This function exists to clear "stdin."
Description:                  This function checks to see if "stdin" needs to be
                              cleared.  If so, it calls "getchar" in a loop until
                              "stdin" is empty.
Input:                        character:  the last character received from a
                              previous call to getchar.
Output:                       None.
Result:                       stdin cleared.  Nothing returned.
Side Effects:                 None.
---------------------------------------------------------------------------*/

If you can explain it clearly in a few words, fine, but make sure you describe the function correctly. When in doubt, using a few extra word will be better than not using enough. Your function header should say what the function does, what it needs (params), and what kind of return value it gives. The return value is one of the most important parts of the function header.

4. Inline Comments

Your code should have inline comments to help the reader follow your code. There are many ways to have clear, easy to understand inline comments. If you have a way to write inline comments that's easy to understand, great. If not, here are samples of good inline comments:

Base * Tree :: Insert (Base * element) const {

    // Make sure tree is not empty
    if (!root) return 0;
 
    // Move down the tree and look for insert point
    while (temp) {

        // Found the node, so return the data
        if (*element == temp.data)
            return temp;

        // Didn't find the node, so move to left or right child
        temp = (element < temp) ? temp->left : right;
    }

    // The node wasn't in the tree
    return 0;
}


Base * Tree :: Insert (Base * element) const {

   /*
    * Make sure tree is not empty
    */

    if (!root)
        return 0;
 

   /*
    * Move down the tree and look for insert point
    */

    while (temp) {


       /*
        * Found the node, so return the data
        */

        if (*element == temp.data)
            return temp;


       /*
        * Didn't find the node, so move to left or right child
        */

        temp = (element < temp) ? temp->left : right;
    }


   /*
    * The node wasn't in the tree
    */

    return 0;
}

You do not need to comment every line. Some inline comment for each block should suffice.

These are equivalent:

        /* This is a comment */
        if (0==0) { }

        // This is a comment
        if (0==0) { }

And these are equivalent:

        /*
         * This is a block comment
         */
        if (0==0) { } 

        //
        // This is a block comment
        //
        if (0==0) { }

Some people prefer the first way, others prefer the second way. Either way is fine. They're both used very commonly in real companies. What's not acceptable is:

        if (!root) // make sure root is not null
                return 0; // return 0

        while (temp) { // while loop
                if (*element == temp.data) // if the two elements
           // are the same then
                        return data; // return the data
               // move
                temp = (element < data) ? left : temp->right;
        }

        return 0; // couldn't find it

Notice first of all that comments are everywhere, making the code and comments hard to read. Also, don't echo the code. You're not teaching the reader how to program in C/C++/Java--assume he/she knows it. Don't tell the user when it's a while loop, but rather, tell what the loop does. Try not to use one word comments like "move". Although it might be meaningful to some people, others might not get the hint. It doesn't hurt to add a few more words.

5. Indentation

Indent what's inside blocks. Here are samples of when you indent:

void right_garbage(void)
{
    while (1) {
        doSomething();
        doSomething();
    }

    for (;;) {
        doSomething();
        doSomething();
    }

    do {
        doSomething();
        doSomething();
    } while (1);
}

Indent if-then statements:

void right_garbage(void)
{
    if (1) {
        doSomething();
        doSomething();
    } else {
        doSomethingElse();
        doSomethingElse();
    }

    if (1) {
        doSomething();
        doSomething();
    }
    else {
        doSomethingElse();
        doSomethingElse();
    }

    if (1)
        doSomething();
    else
        doSomethingElse();
}

What's not acceptable:

void wrong_garbage(void)
{
if (1) {                        // should indent function body
    doSomething();
        doSomething();          // line up statements in same block
} else {
            doSomethingElse();  // too much indention, gets confused
            doSomethingElse();  // with code in another loop
    if (1) {
    doThis();                   // indent true part of the statement
    }
else {                          // else should match with the if
        doThat();
}                              

}                               // When you see two } lined at at the same
                                // level, you know something's wrong with
                                // your loop or indention

}                               // This is an extra }.  Of course, you
                                // can't catch it with this indention.

        return 0;               // why is this floating out here?

}

I've actually seen code worse than that... Indentation is a big part of style. Compare that with:

void wrong_garbage(void)
{
    if (1) {
        doSomething();
        doSomething();
    } else {
        doSomethingElse();
        doSomethingElse();
        if (1) {
            doThis();
        } else {
            doThat();
        }

    }
    }                    // this extra } is easy to find
    return 0;
}

6. Meaningful identifiers

Some people might debate on this topic, but there's no question that this code:

        unsigned mn(int ho, int mn)
        {
            int rn=ho*60+mn;
            return rn;
        }

is harder to understand than:

        unsigned giveMinutes(int hours, int minutes)
        {
            int return_val = hours * 60 + minutes;
    
            return return_val;
        }

7. Use of Constants

Consider this:

        int class[40];

        ... 100 lines of code ...

        for (index=0;index<40;index++) {
            if (buffer[index] >= 40) {
                 ... blah ...
                 ... blah ...
            }
            if (index==39) printf("Last student.\n");
        }

        ... 500 lines of code ...

        jargon=40;

        ... 400 lines of code ...

        for (index=0;index<=39;index++) {
            ... blah ...
            ... blah ...
        }

How much better can we understand the code and modify it if we were to use constants:

        #define CLASS_SIZE      40
        #define DISCOUNT_AGE    40

        int class[CLASS_SIZE];

        ... 100 lines of code ...

        for (index=0; index= DISCOUNT_AGE) {
                 ... blah ...
                 ... blah ...
            }
            if (index == CLASS_SIZE-1) printf("Last student.\n");
        }

        ... 500 lines of code ...

        jargon=DISCOUNT_AGE;

        ... 400 lines of code ...

        for (index=0;index<=CLASS_SIZE-1;index++) {
            ... blah ...
            ... blah ...
        }

Then changing one instance of CLASS_SIZE on top will be enough if the class size does change, instead of the first example, where the programmer has to manually go through the entire program looking for 40, etc. which is especially hard if 40 is used for more than one thing.

8. Efficiency

Don't write in 15 lines what you can write in 1. Consider this:

    int hexValue(char character)
    {
        int value;

        switch (character) {
            case '0': value = 0;
                      break;
            case '1': value = 1;
                      break;
            case '2': value = 2;
                      break;
                ... etc ...
            case '9': value = 9;
                      break;
            case 'A': value = 10;
                      break;
            case 'B': value = 11;
                      break;
                ... etc ...
            case 'F': value = 15;
                      break;
        }
 
        return value;
    }

Why do that when you do this just as easily:

    int hexValue(char character)
    {
        return (character<='9') ? character - '0' : character - 'A' + 10;
    }        

Or even if you aren't familiar with the ? : notation...

    int hexValue(char character)
    {
        if (character<='9')
            return character - '0';
        else
            return character - 'A' + 10;
    }        

And avoid repeating code. Code like this:

    void garbage(int stuff)
    {
        if (stuff) {
            doSomething();
            doSomething();
            doSomethingElse(stuff);
            doSomethingElse2(stuff);
            doSomethingElse3(stuff);
            doSomethingElse4(stuff);
        } else {
            doNothing();
            doNothing();
            doSomethingElse(stuff+1);
            doSomethingElse2(stuff+1);
            doSomethingElse3(stuff+1);
            doSomethingElse4(stuff+1);
        }
    }

can be simplified to:

    void garbage(int stuff)
    {
        if (stuff) {
            doSomething();
            doSomething();
        } else {
            doNothing();
            doNothing();
            stuff++;
        }
        doSomethingElse(stuff);
        doSomethingElse2(stuff);
        doSomethingElse3(stuff);
        doSomethingElse4(stuff);
    }

If you follow those guidelines, you should do well in upper division CS programming classes, and in the real world. CSE 100 demands it, and even more (you're required to write manuals for your program, on top of the style and comments).

Okay, enough on the practical values of good comments and styles. In the mean time, if you want good scores for comments and styles, try to follow those guidelines. No, there's no one RIGHT way to write comments/styles, but try to find one that's easy for everyone to understand.