- Function Decomposition (20%)
You must decompose your programs
into smaller parts. One mainline won't cut it. This is one of the most
common pitfalls of novice programmers. As a general rule of thumb, no
function should consist of more than 20 lines of code. Yes, it's arbitrary, but
think of it as a learning exercise; by having to fit within such
constraints, you will come to appreciate what modular coding does for you,
and when it is right to use bigger functions.
The decomposition process does not occur at the very end. Some students
bring code to me to look at, promising that they'll split it into smaller
functions, "when they're done". That's not the point--you don't do this
just to make the program look pretty. You want to
decompose the problem (and your solution, i.e. the program) starting at the
design phase. By forcing yourself to design modularly (i.e., use functions) from the
beginning, your program will go together faster, be easier to debug and
easier to read. Think Legos© and Tinker-toys©: lots of small pieces, each
easy to comprehend and debug. Plug them together and you can get great
stuff!
As you write code, if you find a function becoming too large (too many
variables, etc.), it's probably time to split the function into smaller parts.
- Indentation(10%)
Follow the indentation style set forth in the course textbook, or in Foundations. The basic
rule is that whenever you use (or could use) curly brackets, you indent the
code inside the brackets by 3 or 4 spaces (you may use a different amount, but
you should be consistent.) Below is a part of a program, showing proper indentation.
int main()
{
string month;
int days = 31; // default value of 31 days/month
cout << "enter a month (lowercase letters): ";
cin >> month;
// 30 days hath september, april, june, and november
if ("september" == month)
{
days = 30;
cout << "30!!" << endl;
}
else if ("february" == month)
{
days = 28;
}
cout << month << " has " << days << " days" << endl;
return 0;
}
Here's another acceptable style:
int main()
{
string month;
int days = 31; // default value of 31 days/month
cout << "enter a month (lowercase letters): ";
cin >> month;
// 30 days hath september, april, june, and november
if ("september" == month) {
days = 30;
cout << "30!!" << endl;
}
else if ("february" == month) {
days = 28;
}
cout << month << " has " << days << " days" << endl;
return 0;
}
- Identifiers (naming conventions)(10%)
Note that these conventions differ slightly from the textbook's. I've tried to
highlight the differences below.
- Variables and parameters: should be lowercase, except use uppercase letters to
separate words within the identifier. So, if you wanted to name a
variable "size of balloon", you'd use
sizeOfBalloon
.
- Global variables: same as for variables, but capitalize the first
letter. Even better, you can prefix all such names with a "g". For
example:
gSizeOfBalloon
.
- Constants: use all caps, and underbars to separate words. For
example:
SIZE_OF_BALLOON
.
- Functions/Methods: as with variables, but the first letter is capitalized. For
example:
SizeOfBalloon()
.
- Class names: same as functions.
Comments
This is a biggy. There are several types of comments and these are
explained below. Remember that the overall purpose of comments is to make
your code readily understandable to a trained programmer (including
yourself). It may seem wasteful to spend the time putting comments into
your programs: it's not! The more you work with other folks' code, the
more often you go back to work with your own, old code, the more you will
appreciate comments.
- File header comment(10%)
The top of each file should feature a comment that briefly outlines the
Contents and purpose of the file. Also, specify the history of the file:
the date of each modification and the name of the modifier. For example:
#include <iostream.h>
#include <string.h>
// Illustrates cascaded if/else statements. Calculates the number of
// days in a month (specified as a string).
// VERSION HISTORY:
// Modified by Matt Evett, 5/23/1997
// Owen Astrachan 1/2/1996
int main()
{
etc.....
- Header comments of class .h files(20%)
Like the header comments of other files, but more involved. You must
describe the public interface. The header file for the
balloon
class, balloon.h
presents a good example. A part of that file's header comment follows:
#ifndef _BALLOON_H
#define _BALLOON_H
// class for balloon manipulation using simulated auto pilot
// written: 8/29/93 (based on an idea of Dave Reed)
// modified: 8/30/94, 12/29/94, 11/3/95
// modified: 5/23/97 by Matt Evett (changed header comments).
//
// Member function explanation:
//
// Ascend(int height): balloon ascends to height specified by parameter
// in a sequence of burns. Each burn raises the
// altitude by 10 meters
etc....
- Function header comments(20%)
Immediately above the definition of each function, describe what each
function does. Pay particular attention to describing the parameters,
especially if they are reference parameters that could be altered by the
function execution.
Each function header must also contain a PRECONDITION and POSTCONDITION
lines. The PRECONDITION comment specifies the preconditions that must exist for the
function to execute correctly. Usually this is a relation or predicate
that must hold on the parameters and global variables used by the
function. The POSTCONDITION comment must specify what value the function
returns, and any changes that will be made to reference parameters and
global variables.
The following example is taken from /usr/tools/cse.pub/matt/FoundationsCode/craps2.cc:
bool GetPoint(int point)
// precondition: 2 <= point <= 12
// postcondition: returns true if point obtained (winner)
// returns false if 'crapped out'
{
int sum;
do
{
sum = RollTwo();
} while (sum != point && sum != 7);
return (sum == point);
}
- In-function comments(10%)
- Local variables: each local variable should be declared on a
separate line, with an in-line comment describing its purpose.
- Subsection comments: for large functions (which should be rare,
generally) you may want to place an in-line comment at the top of a
subsection, describing what the code there does. Such comments
should be indented with the code.
- In-line comments: Knowing which lines to comment is one of the
trickiest aspect of style. It's really more of an art, than a
science. You should comment those lines of code that are not fairly
self-explanatory. At the least, though, you must comment every
flow-of-control statement (e.g.
if
, do
,
while
, for
, and function call.)
See code below, also taken from craps2.cc for some examples:
int main()
{
int k; // Iteration counter.
int gamesWon = 0; // Number of games won.
int simulations = // Number of games to simulate.
PromptRange("enter # games to simulate",1,1000000);
for(k=0; k < simulations; k++) // For each simulated game....
{
if (WinGame())
{
gamesWon++;
}
}
// After running all the simulations, we output the results....
cout << "# of games = " << simulations;
cout << " # won = " << gamesWon << " = ";
cout << double(gamesWon)/simulations * 100 << "%" << endl;
return 0;
}