| CS 535: Object-Oriented Programming & Design |
|
---|
Fall Semester, 1997
Doc 14, Comments on Assignment 1, part 1
To Lecture Notes Index
San Diego State University -- This page last updated 06-Oct-97
Contents of Doc 14, Comments on Assignment 1, part 1
- References
- Meyer's Criteria for Evaluating for Modularity
- Indentation, White space
- Names
- Comments
- Kinds of Comments
- Commenting Efficiently
- Commenting Techniques
- Commenting Data Declarations
- Commenting Routines
- Problem 1 & 2
- Static Version
- The Non-static Static Version
- Mixing IO and the Abstraction
- The One per Program Version
- The No Abstraction Version
- Flag Trouble Ahead
- Positional Data Problem
Various student papers
Code Complete, Steve McConnell, Microsoft Press, 1993, chapters 9 and
19
- Decomposability
- Composability
- Understandability
- Continuity
- Protection
public class Assgn1_Part1
{
public static void main(String args[])
{
Console.println();
// Initialize strings
DataString A=new DataString('A'); // This will prompt
===>the user for a string.
DataString B=new DataString('B'); // This will prompt
===>the user for a string.
DataString C=new DataString('C'); // This will prompt
===>the user for a string.
String D="";
int i=0;
do
{
{
String a;
String b;
int j=0;
// Check each character of A
do
{
a = A.Data.substring(i+j,i+j+1);
b = B.Data.substring(j,j+1);
j++;
}
// If a letter matches, see if the whole string B is contained
while (a.toLowerCase().equals(b.toLowerCase())
&&(j<B.Data.length()))
if (a.toLowerCase().equals(b.toLowerCase())
&&(j<B.Data.length()))
{
// Place C into D
D=D+C.Data;
i+=j;
}
else
{
// Place the letter from A into D
D=D+A.Data.substring(i,i+1);
i++;
}
}
}
// Do until the end of A is too short to contain B
while (i<=(A.Data.length()-B.Data.length()));
Indentation, White space
Use
white space to make program readable
Use indentation to show the program structure
while (a.toLowerCase().equals(b.toLowerCase())
&&(j<B.Data.length()))
if (a.toLowerCase().equals(b.toLowerCase())
&&(j<B.Data.length()))
verses
while ( ( a.toLowerCase().equals( b.toLowerCase() ) ) &&
( j<B.Data.length() )
)
if ( ( a.toLowerCase().equals( b.toLowerCase() ) ) &&
( j<B.Data.length() )
)
{
// Code deleted
}
verses
while ( ( a.toLowerCase().equals( b.toLowerCase() ) ) &&
( j<B.Data.length() )
)
{
// Code deleted
}
Example 1
String s1;
String s2;
String s3;
int index1;
int index2;
verses
String escapeChar;
String charsToEscape;
String unescapedString;
Example 2
Node pre;
public float compute() { stuff }
int len;
float avrg;
float avrge;
String esc_char;
String string;
Node ptr;
verses
Node previous;
public float average() { stuff }
int length;
float average;
String escapeChar;
Example 3
public String escape( String text) {
StringBuffer tmp = new StringBuffer();
verses
public String escape( String unescapedText) {
StringBuffer escapedText = new StringBuffer();
Only Possible Use of Temp
int temp;
temp = a;
a = b;
b = temp;
//temp not used after this
A Better Way?
int swapSpace;
swapSpace = a;
a = b;
b = swapSpace;
Example 4
boolean condition = true;
while ( condition )
{
//blah
}
verses
while ( ! endOfFile )
{
//blah
}
Example 5
How long will these be meaningful?
class p1p1 { //blah }
class p1p2 { //blah }
class project1problem2 { //blah }
Names
"Finding good names is the hardest part of OO Programming"
"Names should fully and accurately describe the entity the variable
represents"
What role does the variable play in the program?
Data Structure | Role, function |
InputRec | EmployeeData |
BitFlag | PrinterReady |
Queue | buffer |
Some Examples of Names, Good and Bad
TrainVelocity | Velt, V, X, Train |
CurrentDate | CD, Current, C, X, Date |
LinesPerPage | LPP, Lines, L, X |
//Declare fields
String s1; //escape character
String s2; //special characters
String s3; //input string
//Prompt user for escape character
s1 = Console.readLine( "Type an escape character" );
//Prompt user for special characters
s2 = Console.readLine( "Type an escape character" );
s2 = s1 + s2 // add s1 to s2
class FooBar
{
//Constructor
public FooBar();
Comments
"Comments are easier to write poorly than well, and comments can be more
damaging than helpful"
What does this do?
for i := 1 to Num do
MeetsCriteria[ i ] := True;
for i := 1 to Num / 2 do begin
j := i + i;
while ( j <= Num ) do begin
MeetsCriteria[ j ] := False;
j := j + i;
end;
for i := 1 to Mun do
if MeetsCriteria[ i ] then
writeln( i, ' meets criteria ' );
How many comments does this need?
for PrimeCandidate:= 1 to Num do
IsPrime[ PrimeCandidate] := True;
for Factor:= 1 to Num / 2 do begin
FactorableNumber := Factor + Factor ;
while ( FactorableNumber <= Num ) do begin
IsPrime[ FactorableNumber ] := False;
FactorableNumber := FactorableNumber + Factor ;
end;
end;
for PrimeCandidate:= 1 to Num do
if IsPrime[ PrimeCandidate] then
writeln( PrimeCandidate, ' is Prime ' );
Good Programming Style is the Foundation of Well Commented Program
X := X + 1 /* add one to X
/* if allocation flag is zero */
if ( AllocFlag == 0 ) ...
- Explanation of how code works
- Used to explain complicated or tricky code
*p++->*c = a
/* first we need to increase p by one, then ..
-
-
- Make code simpler before commenting
(*(p++))->*c = a
ObjectPointerPointer++;
ObjectPointer = *ObjectPointerPointer;
ObjectPointer ->*DataMemberPointer = a;
/* **** Need to add error checking here **** */
- Distills a few lines of code into one or two sentences
-
-
-
- Description of the code's intent
- Explains the purpose of a section of code
/*get current employee information */ intent
/* update EmpRec structure */ what
- Use styles that are easy to maintain
/***********************************
* module: Print *
* *
* author: Roger Whitney *
* date: Sept. 10, 1995 *
* *
* blah blah blah *
* *
***********************************/
/***********************************
module: Print
author: Roger Whitney
date: Sept. 10, 1995
blah blah blah
***********************************/
Commenting Individual Lines
Avoid self-indulgent comments
MOV AX, 723h ; R. I. P. L. V. B.
Endline comments have problems
MemToInit := MemoryAvailable(); { get memory available }
- Not much room for comment
-
- Must work to format the comment
Use endline comments on
- Data declarations
-
- Maintenance notes
-
- Mark ends of blocks
Commenting Paragraphs of Code
Write comments at the level of the code's intent
Comment the why rather than the how
Make every comment count
Document surprises
Avoid abbreviations
How verses Why
How
/* if allocation flag is zero */
if ( AllocFlag == 0 ) ...
Why
/* if allocating a new member */
if ( AllocFlag == 0 ) ...
Even Better
/* if allocating a new member */
if ( AllocFlag == NEW_MEMBER ) ...
Summary comment on How
{ check each character in "InputStr" until a
dollar sign is found or all characters have
been checked }
Done := false;
MaxPos := Length( InputStr );
i := 1;
while ( (not Done) and (i <= MaxLen) ) begin
if ( InputStr[ i ] = '$' ) then
Done := True
else
i := i + 1
end;
Summary comment on Intent
{ find the command-word terminator }
Done := false;
MaxPos := Length( InputStr );
i := 1;
while ( (not Done) and (i <= MaxPos ) ) begin
if ( InputStr[ i ] = '$' ) then
Done := True
else
i := i + 1
end;
Summary comment on Intent with Better Style
{ find the command-word terminator }
FoundTheEnd := false;
MaxCommandLength := Length( InputStr );
Index := 1;
while ((not FoundTheEnd) and
(Index <= MaxCommandLength)) begin
if ( InputStr[ Index ] = '$' ) then
FoundTheEnd := True;
else
Index := Index + 1;
end;
Comment the units of numeric data
Comment the range of allowable numeric values
Comment coded meanings
var
CursorX: 1..MaxCols; { horizontal screen position of cursor }
CursorY: 1..MaxRows;{ vertical position of cursor on screen }
AntennaLength: Real; { length of antenna in meters: >= 2 }
SignalStrength: Integer;
{ strength of signal in kilowatts: >= 1 }
CharCode: 0..255; { ASCII character code }
CharAttib: Integer; { 0=Plain; 1=Italic; 2=Bold }
CharSize: 4..127; { size of character in points }
Comment limitations on input data
Document flags to the bit level
Avoid Kitchen-Sink Routine Prologs
Keep comments close to the code they describe
Describe each routine in one or two sentences at the top of the routine
Document input and output variables where they are declared
Differentiate between input and output data
Document interface assumptions
Keep track of the routine's change history
Comment on the routine's limitation
Document the routine's global effects
Document the source of algorithms that are used
procedure InsertionSort
{
Var Data: SortArray; { sort array elements }
FirstElement: Integer {index of first element to sort}
LastElement: Integer {index of last element to sort}
}
A Solution
class CharEscaper
{
private char escape;
private String charsToEscape;
public CharEscaper( char escapeChar, String specialChars )
{
// The escapeChar must be escaped
charsToEscape = specialChars + escapeChar;
escape = escapeChar;
}
private boolean needsEscaping( char testChar)
{
final int NOT_FOUND = -1;
if ( charsToEscape.indexOf( testChar ) == NOT_FOUND )
return false;
else
return true;
}
public String escape( String unescapedText)
{
StringBuffer escapedText =
new StringBuffer( unescapedText.length() * 2);
for (int index = 0; index < unescapedText.length(); index++ )
{
char unescapedChar = unescapedText.charAt( index );
if ( needsEscaping( unescapedChar ) )
escapedText.append( escape);
escapedText.append( unescapedChar );
}
return escapedText.toString();
}
public String unescape( String escapedText)
{
StringBuffer unescapedText =
new StringBuffer( escapedText.length());
for (int index = 0; index < escapedText.length(); index++ )
{
char nextChar = escapedText.charAt( index );
if ( nextChar == escape )
{
index++;
nextChar = escapedText.charAt( index );
}
unescapedText.append( nextChar );
}
return unescapedText.toString();
}
}
Using CharEscaper
class Test
{
public static void main( String args[] )
{
CharEscaper test = new CharEscaper( 'a', "cd");
System.out.println( test.escape( "cadman" ));
System.out.println( test.escape( "this is a test" ));
String escaped = test.escape( "asadcad" );
System.out.println( test.unescape( escaped ));
CharEscaper normal = new CharEscaper( '\\', "nt");
System.out.println( normal.escape( "this is new" ));
}
}
class CharEscaper
{
public static String escape( char escapeChar,
String specialChars,
String unescapedText
)
{
final String charsToEscape = specialChars + escapeChar;
StringBuffer escapedText =
new StringBuffer( unescapedText.length() * 2);
for (int index = 0; index < unescapedText.length(); index++ )
{
char unescapedChar = unescapedText.charAt( index );
if ( charsToEscape.indexOf( unescapedChar ) > -1 )
escapedText.append( escapeChar);
escapedText.append( unescapedChar );
}
return escapedText.toString();
}
}
Using the Static Version
class Test
{
public static void main( String args[] )
{
System.out.println(
CharEscaper.escape( 'a', "cd", "cadman" ));
}
}
class CharEscaper
{
public String escape( char escapeChar,
String specialChars,
String unescapedText)
{
//Same as last slide
}
}
Using the Non-static Static Version
class Test
{
public static void main( String args[] )
{
CharEscaper test = new CharEscaper();
System.out.println( test .escape( 'a', "cd", "cadman" ));
}
}
class CharEscaper
{
private char escape;
private String specialChars ;
public CharEscaper( )
{
specialChars =
Console.readLine( "Type the special chars");
escape = Console.readChar( "Type the escape char");
}
// etc
}
class CharEscaper
{
private static char escape;
private static String specialChars ;
etc.
class problem1
{
public static void main( String[] arguments )
{
char escapeChar = Console.getTheUserInput();
String specialChars = Console.getMoreUserInput();
String unescapedText = Console.getStillMoreInput();
final String charsToEscape = specialChars + escapeChar;
StringBuffer escapedText =
new StringBuffer( unescapedText.length() * 2);
for (int index = 0; index < unescapedText.length(); index++ )
{
char unescapedChar = unescapedText.charAt( index );
if ( charsToEscape.indexOf( unescapedChar ) > -1 )
escapedText.append( escapeChar);
escapedText.append( unescapedChar );
}
System.out.println( escapedText.toString() );
}
}
class CharEscaper
{
private String escape;
private String charsToEscape;
private String textToEscape
public String getString( int stringType )
{
switch ( stringType )
{
case 1:
return escape;
case 2:
return charsToEscape;
case 3:
return textToEscape;
}
}
This is control coupling, which is not good
Use individual get methods for each string
class problem1
{
public static void main( String[] arguments )
{
String escapeChar = arguments[0];
String specialChars = arguments[1];
String unescapedText = arguments[2];
Use flags!