Documentation Standards for Prof. Cole's Classes

High-level Languages (below)  Assembly Code

Part of your program grade is dependent upon documentation, that is, the comments in your program. After going through well over a thousand programs in my last few years at UTD, it occured to me that I was making a bad assumption: that most students have been taught what constitutes good comments in a program. Therefore, below is what I consider to be a standard for your programs. If you follow these guidelines well, you will get full points for that aspect of your assignment. You should always use good naming conventions for your variables and methods, but this is not a substitute for good comments, although some would argue that it is.  I have seen code in which the code itself can explain what is happening, but not why. I have also observed that if you can explain what you're doing in English, you probably understand it well enough to explain it to the computer.

1. Every module must have a block of comments at the beginning that contains the following information: Your name, your Net ID, the date on which you started writing the program, and your purpose in writing it. The purpose will generally be because it is an assignment for a particular class, and you should name the class and section here. This header must also include a general description of what the program or module does.   For example:

  Written by John Cole for CS6326.001, assignment 4, starting April 1, 2017.
    NetID: jxc064000

2. Every method must have a comment above it that describes what the method does, and usually its inputs and outputs. The exception is tiny functions of a few lines where the name adequately describes the functionality and the return value, if any, is obvious.  Get and Set methods fall into this category.

3. Major sections of code within a method must have comments explaining what they do. The beginnings of loops and conditionals are good places for this. Blocks that set up databases, initialize objects, and the like are also good places for a block of explanatory comments. The best comments describe what you're doing, and they also describe why you're doing it.

4. Some of your variables will need a comment next to them that explain what they signify and other useful information. However, good variable naming conventions (see next item) can make this less necessary.

5. Follow good naming conventions. Even temporary variables such as loop counters should have names that mean something and can be found using the text search. For example, you will never see this in my code: for (i=0; i<10; i++). Instead I'll use, at a minimum, something like this: for (ix=0; ix<10; ix++) because I can find the variable "ix".  I know most development environments have a way to find variables and not just text, but I don't always rely upon that.  In any case, i and j are seldom good variable names.  If you're working with the rows and columns of a matrix, for example, why not use iRow and iCol?

6. When I was teaching at IIT I based part of the grade on the grammar and spelling in the comments. However, given the large population of students for whom English is not their first language, I no longer do this. Please do your best to be clear.

7. Don't write the code figuring you'll go back and document it later. Write the description before you write the code. For example, if you decide you need a method to, say, return an average price for a set of items in a database, define the method with its return value and parameters first. Then write the comments describing how the method works. Finally, write the method itself. If you come to office hours with code that contains no comments, you are likely to be sent away to do some writing.

8. I mention above that your comments should explain why you're doing certain things.  Here are some examples of why you should do that.  In one of my programs I had code to clear a buffer to blanks, and the comment said that this was so.  However, it failed to explain that this was being done because characters could be placed at random positions in the buffer, which you can think of as a simple array.  The fact that this could happen required domain knowledge and was not obvious from a cursory examination of the code.  In another program, it was clear that I was putting various information, such as the position in a list and the name of the last thing found in that list, on a stack.  The reason was that the program was emulating recursion in an iterative loop, and this was not at all obvious from the code.

9. Make your comments meaningful.  The following examples are not:
//Close file.
infile.close()

// Dynamic allocation
double *matrix = new double[m, n);

10. Program Structure.  In general, the first executable code the user sees, at the top of your program, should be where execution starts.  For java and C++, this means the main method.  For Android apps, it's the onCreate method.  Use function prototypes in C++ so you don't have to write all of your functions before they're called.  Keep your methods short.  Don't make a method do more than necessary.  For example, a method that does computation should return the result, not display it. 

Here are sample header comments from one of my programs.  You don't need to enclose everything in asterisks; that is simply my style.  However, you should have that level of detail about the program operation.  Someone reading the comments from this program could easily figure out how to use it.

/******************************************************************************
* Attendance Tracking Program.
*
* This program tracks class attendance. It operates in two modes: First, it
* will look up an ID scanned from a Comet card and enter attendance for that
* person. Second, you can edit attendance for any student and date, although
* this is probably better done in Excel.
*
* If the ID is not in the system, you can enter the NetID and the program will
* enter the card ID and attendance for the appropriate date. You can also
* click on a blank Card ID for a student and the program will fill in the
* current ID.
*
* You must have a file called Classes.txt in the same directory as the
* program. This contains the fully-qualified path and file names of Excel
* workbooks (.xlsx files) that are your attendance roster. When the program
* opens, you'll be able to pick one of these for taking attendance.
*
* The workbook must contain a worksheet called Attend. Columns on the
* spreadsheet are in the order downloaded from Coursebook, using only the
* following:
* Card ID -- Not from Coursebook; you'll have to add
* NetID
* First name
* Middle name
* Last name
*
* The program will create new attendance columns with the current date when
* you press the New button. An attendance column can have four possible values:
* blank -- person was absent.
* hh:mm -- Time, based on a 24-hour clock, that the person signed in.
* E -- Excused absence.
*
* Written by John Cole (jxc064000) at The University of Texas at Dallas
* starting August 18, 2016.
******************************************************************************/

Here are the comments over a function:

/**************************************************************************
 * Load all students from the appropriate sheet into a list of Student
 * objects.  The list is an instance variable.
 **************************************************************************/
private void loadStudents()
{}

Back to John Cole's main pageBack to Notes for Students page.

Assembly Code

Assembler is different.  It requires far better documentation than high-level language. See the examples below for what good code and documentation look like. Here are some rules:

1. Nearly every line should have a comment.  Without this, many assembly language programs are nearly impossible to read and understand, even if you are the one who wrote it.  Make the comments useful, same as for a high-level language.  Not "Add one to $a0" but "Move pointer to next byte."  See the difference?  Keep line comments short and to the point.

2. Since register names are not particularly descriptive, it helps to have comments above a block of code describing the register contents when you enter that block along with what the block accomplishes.  Use margins.  Do not type past column 80 or 90 so I don't have to side-scroll to read your code.

3. Every assembly language has a directive that lets you set a symbol equal to a value.  In MIPS this is the .eqv directive, which sets the symbol, the first argument, equal to the second thing.  (This is very similar to the C/C++ #define directive.)  This can be especially helpful for local variables that are at some offset from the stack pointer.  See the example below.  You can also use this to make your register names mean something.  This helps you avoid what I call "magic numbers," numerical constants whose meaning you will forget within 10 minutes of using them and the meaning of which is completely opaque to anyone else reading your code.

4. Use labels where you need them.  While many of us have a tendency to use short labels and put them on the same line as code, this is not necessary, and a longer, more descriptive label above a section of code may be much better.  Speaking of labels, if you have a function named, for example, strcpy, if you have labels within it, use the name of the function and a number, for example, strcpy5.  You will find that you need many more labels in assembly language because there are no looping constructs, just branch or jump instructions that require a label.  Convention is that labels start in column 1.  Do not use labels that you never reference.

5. Do not indent assembly code the way you would C++ or other high-level languages.  Line up your instruction menemonics in colum 10 or 11, tab to the next column, and align the operands. To clarify: Labels in column 1.  Instructions and pseudo-operations in column 10 or 11.  Operands in column 19 or 20.  Comments in 30 or so.  Line up everything neatly to the extent that this is possible.

6. As you would with a high-level language, modularize.  Put your simple utility functions such as copying strings, searches, and the like into a separately-assembled module.  Once you have those working, you never need to look at them again. Do not use the .include directive for this code.

7. This is not strictly about documentation, but readability.  Unless you have a loop, the control flow in your program should be generally from top to bottom.  Since assembly code has no inherent structure, you must provide one.  For example, testing something and branching if equal to a place further down in the code is fine.  Branching from that place to someplace further up in the code is usually not; the technical term for this is "spaghetti code," because it goes everywhere.  Similarly, don't put your subroutines in the middle and branch around them.  Don't branch to a label that your code would fall through to anyway.  See the bad example below.  See the good example in Fibonacci.asm.

I couldn't get the example code to look right in HTML, so I have linked some useful things here.  They have a .txt extension so you can see them rendered. 
SysCalls.asm
Fibonacci.asm

Bad example:
             bne     $t0, '*', down
back:   sb      $t0, 0($a0)
        ...
        j       over
down:   li      $t0, 'x'
        j       back
over:   b       over2
over2:  ...