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:

/**
 * Name:           Tracker Wonderdog
 * PID:            A12345678
 * USER:           cs12fa21zz
 * File name:      hwxxx.java
 * 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 varios types of Java pre defined types.
 */

2. Class Headers

Example Class Header:

/**
 * Class:            Node
 * Description:      Implements the node of the binary search tree data 
 *                   structure.Each node containts 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.
 *
 * Fields:           data  - holds the data stored in the current node
 *                   left  - the left child
 *                   right - the right child
 *
 * Public functions: jettisonAllTNodes - jettisons all the children of the 
 *                                       current node.
 *                   insert            - inserts a data into the current node
 *                                       or to one of its children.
 *                   write             - display the current node.
 */

3. Method Headers

Each function header must contain at least the, description, the parameters (input), and return value (output). Method name, result and side effects should be part of the description. Here is an example for the clrbuf method:

/**
 * The <code>clrbuf</code> method checks to see if standard in needs to be cleared.  
 * If so, it calls <code>fgetc</code> in a loop until standard in is empty.
 * The standard in is cleared after this method call.
 * @param character   the last character received 
 *                    the from a previous call to <code>fgetc</code>
 * @return None
*/

If you can explain it clearly in a few words, fine, but make sure you describe the method correctly. When in doubt, using a few extra word will be better than not using enough. Your method header should say what the method 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 method 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:

public int  insert (Base element) {

    // Make sure tree is not empty
    if (root == null ) 
        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) ? left : right;
    }

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


public int insert (Base element) {

   /*
    * Make sure tree is not empty
    */

    if (root == null)
        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) ? 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 == null) // 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 : 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:

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

is harder to understand than:

        int 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:

        public static final int CLASS_SIZE = 40;
        public static final int DISCOUNT_AGE = 40;

        int class[CLASS_SIZE];

        ... 100 lines of code ...

        for (index = 0; index < CLASS_SIZE; index++) {
            if (class[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);
    }

9. Use of the this keyword

Be sure not to make use of the this keyword unless absolutely necessary. There is no need to refer to the field of a calling object with this.fieldName, unless fieldName is also the name of a local variable or parameter. Redundant use of this will cost you points in later projects, so be careful!

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.