|
Fall, 1999
Contents
Why is program
documentation important?
1) The main purpose of program documentation is to
describe the design of your program. The
documentation also provides the framework in which to
place the code. as coding progresses, the code is
inserted into the framework already created by the
program documentation.
2) Documentation is important to tell other
programmers what the program does and how it works.
In the "real world" and in some classes
here at BGSU, programmers often work in teams to
develop code. Documentation helps others on the team
to understand your work.
3) Maintenance and debugging are needed sooner or
later for most programs and these are frequently done
by someone other than the original programmer.
Documentation can help the programmer who is making
the modifications understand your code.
4) Documenting your program during development
helps you to maintain your sanity.
When should
program documentation be done?
When designing your program, you must spend time
thinking about how to structure your program, what
modules are needed, and the algorithms and processes
you will use in the modules. You must think about
what sort of data structures and objects (e.g.,
arrays, files or linked lists) are needed. This
thinking must be done before you start coding, or you
will find yourself wasting time writing useless code
that is full of errors. It is very important to
record this creative process so that the programmers
that follow you do not duplicate work that you have
already done.
Before writing the code, you should write the
documentation to describe the design of each
component of your program. Writing documentation for
the modules before writing the code helps you define
exactly what each module should do and how it will
interact with other modules. Focusing on the design
and the steps needed to solve the problem can help
prevent errors in the completed program.
What
information should be in the program
documentation?
For an individual module, it is important to
record (1) who has written the module, (2) when the
module was written or modified, (3) why the module
was written or modified, (4) how the module interacts
with other modules, (5) what special algorithms were
used, if any, and (6) acknowledge outside sources for
ideas and algorithms. For data structures, it is
important to record (1) what data structure is used,
(2) why a particular structure was used, (3) what
data is contained in the structure, and (4) how the
data structure is implemented.
How should
program documentation be done?
The following sections contain guidelines for
documentation that should appear in a C++ program
file containing a main program and some functions.
Documentation or comment lines begin with a double
slash ( // ) and all text to the end of the line is
considered a comment. Documentation should appear
• before the main program (program header)
• before each function (function header)
• before or next to lines of code within a
function (line comments)
To help you get started, fill-in-the-blank
framework files can be found on bgunix in
/home/cs/documentation.
An
example for CS 2020 students
Here is an example of a typical programming
assignment in CS 2020.
CS 2020
Lab Assignment 3
Due: 5 pm, October 10
A small university needs help keeping track of
enrollment in each of their ten courses. They have
asked you to write a program to help with this
task. The first thing that they want is a list of
the enrollment data in order by id number. Write a
program that will read in the data, sort it by the
id number and print the sorted list. They would
also like to see the total enrollment in all
courses.
Input: The user should be prompted for the id
number and enrollment in each course.
Method: Your program should contain 2 parallel
arrays to contain the data. Use separate functions
to read in, sort and print the data in the arrays.
You should use the bubble sort to sort the
data.
Output: Should be neatly labeled and easy to
read. It should include the id number of each
course and the enrollment in that course. Print the
output in table form.
A sample solution is presented below. The comments
in this solution are representative of the type of
documentation that you should put in your programming
assignments. The code has also been entered in a
style which has been effective for students learning
the C++ language.
As you are reading through the example, please
note the following points (referred to using these
numbers).
- Function prototypes require that only the data
types of the arguments be given. However, by
including parameter names, your code becomes easier
to read and self-documenting by stating what each
of the parameters are.
- There are many styles for the braces in a C++
program. In this example, we have placed them on a
separate line with matching braces at the same
indentation level. Studies have shown that this is
easier for beginning programmers.
- Pseudocode is used to describe the method of
this function.
- Statements that take more than one line to
enter are usually indented after the first
line.
- The braces in this statement are optional
because there is only one statement in the body of
the loop. However, it is good programming practice
to always include the braces. Making changes to the
program later is easier, because the next
programmer doesn't have to check if the braces
need to be inserted.
- Some functions are generic and can be reused in
similar circumstances. For this reason, more
generic names are used for the parameters.
- This section of documentation represents a
typical execution of the program. It is helpful in
understanding what the program is expected to
do.
// FILE: enroll.cpp
// TITLE: Course Enrollments
// SUBMITTED BY: Ima Student
// All code is my own except where credited to others.
// FOR COURSE: CS 2020
// DUE DATE: March 30, 1999
//
// PURPOSE:
// This program will keep track of enrollments in courses at a small
// university. It will read, from the user, the course id number and
// enrollment for each course offered. The data will then be sorted
// from smallest to largest id number. The sorted list will then be
// printed along with the total enrollments for all courses.
//
// OVERALL METHOD:
// The list of general tasks is:
// 1. Input course data from the user and store in parallel one-
// dimensional arrays.
// 2. Sort the parallel arrays by id number. A bubble sort will
// be used.
// 3. Print sorted course data stored in arrays.
// 4. Print total enrollment at university.
//
// FUNCTIONS:
//
// getCourseData
// will read data from the user into arrays and, upon exit,
// return the total enrollment for all courses
//
// bubbleSort
// will sort the arrays of id numbers and enrollments from
// smallest to largest id numbers
//
// printCourseData
// will print the data contained in the arrays and, after
// that, the total enrollment
//
// swap
// is called by bubbleSort to exchange two array values
//
// INCLUDED FILES:
// iostream.h
// iomanip.h
//
// DATA FILES:
// none
#include <iostream.h>
#include <iomanip.h>
int getCourseData( int nCourses, int courseids[], int enrollments[] ); ** note 1 **
void printCourseData( int total, int nCourses, int courseids[], int enrollments[] );
void bubbleSort( int n, int keys[], int values[] );
void swap( int & item1, int & item2 );
int main( )
{ ** note 2 **
const int nCourses = 3; // Program inefficient if nCourses is large!
int courseids[ nCourses ], enrollments[ nCourses ];
int total = getCourseData( nCourses, courseids, enrollments );
bubbleSort( nCourses, courseids, enrollments );
printCourseData( total, nCourses, courseids, enrollments );
return 0; // Error level of 0 means normal termination
} ** note 2 **
// name OF FUNCTION: getCourseData
// CREDIT:
// PURPOSE:
// The function will read, from the user, the course id and the
// enrollment in the course. These values will be stored in a set of
// parallel arrays named "ids" and "totals". The function will return
// the total enrollment.
//
// PARAMETERS:
// name type value/reference description
// ---------------------------------------------------------------------
// n int value number of values in the array
// ids[] int reference the array of id numbers
// totals[] int reference the array of enrollment totals
// for each course
//
// RETURN VALUE:
// name type description
// ---------------------------------------------------------------------
// grandtotal int the overall total enrollment for the university
//
// CALLS TO: none
//
// CALLED FROM: main
//
// METHOD: The following is pseudocode describing how the function works.
// 1. Initialize the grand total to zero. ** note 3 **
// 2. Prompt user for data expected.
// 3. Loop and execute n times.
// Use loop counter as subscript of arrays
// 3.1 Prompt user for specific course data.
// 3.2 Read in id.
// 3.3 Read in enrollment.
// 3.4 Add to enrollment to the grand total.
// 4. Return the grand total.
int getCourseData( int n, int ids[], int totals[] )
{
int grandTotal = 0;
cout << endl ** note 4 **
<< "For each of " << n << " courses," << endl
<< " enter the course id and the number of students in that course."
<< endl
<< " Enter these two values on one line, separated by a space."
<< endl
<< endl;
for ( int i = 0; i < n; i++ )
{
cout << "Course " << i + 1 << " -- id and number of students: ";
cin >> ids[i] >> totals[i];
grandTotal += totals[i];
}
return grandTotal;
}
// name OF FUNCTION: printCourseData
// CREDIT:
// PURPOSE:
// The function will loop through parallel data arrays named "ids" and
// "totals", and will print out the course id and enrollment for each
// course. Finally, it will print out the total enrollment. Formatting
// is applied to make the output readable by humans.
//
// PARAMETERS:
// name type value/reference description
// ---------------------------------------------------------------------
// gTot int value the overall total enrollment
// n int value number of values in the array
// ids[] int reference the array of id numbers
// totals[] int reference the array of enrollment totals
// for each course
//
// RETURN VALUE: none
//
// CALLS TO: none
//
// CALLED FROM: main
//
// METHOD: The following is pseudocode describing how the function works.
// 1. Print titles for the columns of data.
// 2. Print a separator.
// 3. Loop and execute n times. Use the loop counter to index the arrays.
// 3.1 Print the course id.
// 3.2 Print the enrollment in that course.
// 4. Print a separator.
// 5. Print the enrollment for the entire university.
void printCourseData( int gTot, int n, int ids[], int totals[] )
{
cout << endl
<< setw(10) << "Class id"
<< setw(12) << "Enrollment" << endl
<< "----------------------" << endl;
for ( int i = 0; i < n; i++ )
{ ** note 5 **
cout << setw(10) << ids[i]
<< setw(12) << totals[i] << endl;
} ** note 5 **
cout << "----------------------" << endl
<< setw(10) << "Total" << setw(12) << gTot << endl;
}
// name OF FUNCTION: bubbleSort
// CREDIT: Adapted from Robert Sedgewick, ALGORITHMS (1992), page 1010.
// PURPOSE:
// This generic function will sort parallel data arrays, one containing
// keys, the other containing values associated 1-to-1 with those keys.
//
// PARAMETERS:
// name type value/reference description
// ---------------------------------------------------------------------
// n int value number of values in the array
// keys[] int reference the array of keys
// values[] int reference the array of values for each course
//
// RETURN VALUE: none
//
// CALLS TO: swap
//
// CALLED FROM: main
//
// METHOD: The following is pseudocode describing how the function works
// 1. Do the following n-1 times.
// 1.1 Point to the first element of the array containing keys.
// 1.2 Do the following n-1 times.
// 1.2.1 Compare the element pointed to with the next element.
// 1.2.2 If the compared elements are in the wrong order ...
// 1.2.2.1 Swap the keys.
// 1.2.2.2 Swap the values associated with those keys.
// 1.2.3 Point to the next element.
//
// NOTE:
// This method is extremely inefficient except for small arrays.
void bubbleSort( int n, int keys[], int values[] ) ** note 6 **
{
int last, next;
for ( int i = 1; i < n; i++ )
{
last = n - i;
for ( int j = 0; j < last; j++ )
{
next = j + 1;
if ( keys[j] > keys[next] )
{
swap( keys[j], keys[next] );
swap( values[j], values[next] );
}
}
}
}
// name OF FUNCTION: swap
// CREDIT:
// PURPOSE:
// This utility function exchanges the values of its two parameters.
//
// PARAMETERS:
// name type value/reference description
// ---------------------------------------------------------------------
// item1 int reference item to be swapped with item2
// item2 int reference item to be swapped with item1
//
// RETURN VALUE: none
//
// CALLS TO: none
//
// CALLED FROM: bubbleSort
//
// METHOD: The following is pseudocode describing how the function works.
// 1. Save a reference to item1's content.
// 2. Store in item1 a reference to item2's content.
// 3. Using the saved reference, store in item2 a reference to
// item1's original content.
void swap( int & item1, int & item2 )
{
int temp = item1;
item1 = item2;
item2 = temp;
}
// EXAMPLE INPUT AND OUTPUT ** note 7 **
//
// For each of 3 courses,
// enter the course id and the number of students in that course.
// Enter these two values on one line, separated by a space.
//
// Course 1 -- id and number of students: 8402 21
// Course 2 -- id and number of students: 3589 35
// Course 3 -- id and number of students: 4521 59
//
// Class id Enrollment
// ----------------------
// 3589 35
// 4521 59
// 8402 21
// ----------------------
// Total 1150
Additional documentation
guidelines
Keep functions
simple!
Functions of 5 to 25 lines, not counting comments,
are recommended. In practice, this means that if you
can't see the entire block on the terminal screen
at one time, it probably needs to be broken into
components which do fit on the screen. C++ main()
functions often tend to be too long. It is
recommended that they not exceed 25 lines or 20% of
the total program length, whichever is less.
Whitespace
The format of the source code is important in the
readability of a program. The term "format"
refers to both horizontal and vertical white space.
In higher level languages, blank lines can be used
for vertical spacing and, for horizontal spacing,
blocks of code can be indented.
identifiers
The identifiers (function, variable and constant
names) which are used also affect the readability of
a program. Make identifiers more self-documenting by
carefully and creatively choosing names which are
close to English but long enough to be meaningful in
terms of the task being performed. For example,
testScores is a much better name for an array than
intArray, and computeAverage is a better name for a
function than doCalculations.
Include
files
All include files used in a program file should be
put at the beginning of the file. Put system-defined
include files (<…>) before user-defined
include files ("…"), as in the
following short example:
#include <iomanip.h>
#include <iostream.h>
#include "date1.h"
#include "myobject.h"
Spelling and
grammar
Correct spelling and good grammar should be used
throughout the comments. Be prepared to be evaluated
both as a programmer and as a technical writer.
Statement
formats
The following table shows how to format and indent
various C++ features.
| C++ function |
void main(int argc, char *argv[])
{
// Body of function indented within { }
}
|
| if statement |
if (condition)
// one statement indented
else
// one statement indented
|
| if statement with blocks |
if (condition)
{ // multiple
// statements
// indented
}
else
{ // multiple
// statements
// indented
}
|
| if statement with else if |
if (condition1)
{ // multiple statements indented
}
else if (condition2)
{ // multiple statements indented
}
else if (condition3)
{ // multiple statements indented
}
else
{ // multiple statements indented
}
|
| while loop |
while (condition)
{ // multiple statements indented
}
|
| for loop |
for (int i = 0; i <= 20; ++i)
{ // multiple statements indented
}
|
| do/while |
do
{ // multiple statements indented
} while (condition);
|
| switch statement |
switch (value)
{ case value1: case value2:
// multiple statements indented
break;
case value3:
// multiple statements indented
break;
default:
// multiple statements indented
break;
}
|
Documenting
user-defined classes
When using an object oriented programming
language, such as C++, programmers often create their
own classes and then declare objects of these class
types. These programs are frequently composed of
several files - one or more header files containing
class definitions, implementation files containing
class functions, and a file containing the main
program. The following describes what documentation
should appear in each of these files.
Header
files
Documentation in the header file must clearly
describe the class interface. That is, the task
performed by each member function should be described
so that a client program which has declared objects
of this class type will know exactly what this class
can do. This documentation should be written so even
a non-programmer can understand it. Header file
documentation should appear before the class
declaration statement and contain the following.
Class name: Use a descriptive name beginning with a capital letter. Other words
within the name should have the first letter capitalized, like Circle or
RationalNumber.
Written by: Your name. list all programmers and sources.
For: Course name Course time Project id
Purpose: Tell what the user program can expect from this class. Describe what
the class represents. This should be implied by the class name, but be
more specific.
Member functions: list and describe briefly the tasks performed by each class function.
list constructors and public and protected functions first, private
functions last. Parameter lists should be described so the client
program will know how to call this function.
Member data: list each data variable and briefly describe its purpose.
Here is an example:
// Class name: Date
// Written by: programmer name
// For: CS 2020 1:30 MWF Project #3
// Purpose: Objects of this class type will keep track of the
// month, day and year of a Date value. The program
// which uses this class can declare and initialize
// Date objects, change a date or print a Date in
// the form m/d/y.
// Member functions:
// Date(int = 1, int = 1, int = 1999)
// This constructor function will accept from the
// calling program initial values for month, day,
// year, in this order. Or it will assign the default
// date of 1/1/95. Will check for valid values.
// setdate(int, int, int)
// This function will assign new integer values of
// the month, day and year of the date. The
// parameters represent the new values to be
// assigned in order of month, day, year. Will
// check for valid values.
// printdate()
// This function will display the date in format
// of m/d/y when called from a client program.
// Member data:
// month
// integer variable representing month value 1-12
// day
// integer variable representing day value 1-31
// year
// integer variable representing year value
// (4-digit number)
//
Implementation files
This file should begin with the class name that
the functions belong to and the programmer's
name, the class, time and project. For example,
#include <iostream.h>
#include "date.h"
// Class: Functions for class Date
// Written by: Programmer's name
// For: CS 2020 1:30 MWF Project #3
Each function in the file should then be
documented as shown in the function headers for the
CS 2020 example.
Main program
file
This file should be documented as shown in the
main program for the CS 2020 example.
|