Straight-Line Code
Creating High-Quality Straight-line Code
Organizing straight-line code is usually simple and straight-forward, but
attention must be paid to the nuances of organization that can affect code
quality, accuracy, readability, and maintainability.
There are two main categories of straight-line code:
-
Statements where order matters
-
Statements where order does not matter
Sample programs:
-
C++ Register Program-register.cpp
-
How To Run register.cpp
-
JAVA Register Program-java_register.java
-
How To Run java_register.java
1. Statements where order matters
If order counts, one type of concern is eliminated. The statements
must be in this order. It is still important, however, to ensure
that dependencies are obvious. Make the dependencies obvious by:
-
Using whitespace to delineate sections of related code.
-
Ensure that called routines have a single purpose.
-
Name routines so that the purpose of called routines is obvious.
-
Use similar routine parameters where similar data is worked upon.
-
Document unclear dependencies.
Organize your code so that dependencies are obvious.
In the C++ Register Program it is obvious that
initializeProduct
should
come before
printProduct
or sumProduct because initialization
must occur before either printing or summing the product.
billObject.initializeProduct(1.23, 3.05, 2.15);
billObject.printProduct();
billObject.sumProduct();
The dependencies would not be obvious if your routines tried to do too much.
If printProduct read the items it was going to initialize off of
the screen and then printed them out it would be unclear which of printProduct
or sumProductshould be called first.
billObject.printProduct();
billObject.sumProduct();
Name your routines so that dependencies are obvious.
In the C++ Register Program only the name of the welcomeMessage
routine indicates that it should come before the byeMessage routine.
billObject.welcomeMessage();
...
billObject.byeMessage();
The dependencies would not be obvious if the routines were named #Message
or &Message.
billObject.&Message(); //what is it saying
...
billObject.#Message(); //how can you tell it follows
Use routine parameters to make the dependencies obvious.
It is possible to show that order dependencies exist by indicating that
they all work on the same data. This can be done by sending all routines
the same data package.
billObject.initializeProduct(item1, item2, item3);
billObject.printProduct(item1, item2, item3);
billObject.sumProduct(item1, item2, item3);
If you are not sending the same data package it can be assumed that the
parts are not dependent on each other.
billObject.welcomeMessage();
billObject.initializeProduct(item1, item2, item3);
billObject.printProduct(item1, item2, item3);
billObject.sumProduct(item1, item2, item3);
billObject.byeMessage();
Document any unclear dependencies.
In the C++ Register Program it may be unclear to someone who does not know
the desired format of the bill which comes first printProduct or
sumProduct
so you include a comment indicating that you list the separate items
before you display their total amount.
//desired format was to have the items listed then their total sum
billObject.printProduct();
billObject.sumProduct();
Otherwise you may end up with something that looks like this:
WELCOME!
-------------------------------
Total Product Value:
$6.43
item1
$1.23
item2
$3.05
item3
$2.15
Total Tax Value:
$0.8359
-------------------------------
Amount Owed:
$7.2659
THANK-YOU, COME AGAIN!
2. Statements where order does not matter
If order doesn't count, one might be tempted to think that organization
doesn't count. This is not true, of course. Organization affects
readability and maintainability. Where there isn't an "execution-order
dependency", you should apply the following rules:
-
Make Code Read from Top to Bottom. Another way of putting this is
"don't jump around". If you mix together different sets of related
code, you'll make an unreadable mess. The example below shows a modest
improvement, and you can be assured that if the intermingled code snippets
are longer the improvement made by this reorganization will grow exponentially.
BAD:
InitTaxData( TaxData );
InitUtilityData( UtilityData );
if TaxData.Available()
{
PrintTaxData( TaxData );
}
if UtilityData.Available()
{
PrintUtilityData( UtilityData );
}
StoreTaxData( TaxData );
StoreUtilityData( UtilityData );
GOOD:
InitTaxData( TaxData );
if TaxData.Available()
{
PrintTaxData( TaxData );
}
StoreTaxData( TaxData );
InitUtilityData( UtilityData );
if UtilityData.Available()
{
PrintUtilityData( UtilityData );
}
StoreUtilityData( UtilityData );
-
Localize References to Variables. The farther apart references to
a variable are, the more likely something can go wrong. Keep variable
span (the number of lines between references) to an absolute minimum!
BAD:
int a = 0;
int b = 0;
int c = 0;
int d = 0;
a = d + c;
GOOD:
int d = 0;
int c = 0;
int a = 0;
a = d + c;
int b = 0;
-
Minimize Variable Lifetime. The distance between the very first and
very last reference to a variable should be kept to a minimum. This
reduces the chance of initialization errors, and makes it more likely that
all references are visible at a glance, or at list visible with little
hunting.
BAD:
int a = 0;
int b = 0;
int c = 0;
int d = 0;
a = d + c;
for (b=0;b==10;b++)
{
\\ Do something
}
GOOD:
int d = 0;
int c = 0;
int a = 0;
a = d + c;
for (int b=0;b==10;b++)
{
\\ Do something
}
-
Group Logically Related Statements. If statements are related by
data or purpose, keep them close together. This is similar to the
idea of writing code so that it reads from top to bottom.
McConnell, Steve. Code Complete, A Practical
Handbook of Software Construction. Microsoft Press (1993).
This page was created by Vince Sorensen and Mandy
Aldcorn : Monday, 19-Jun-2000 12:05:00 CST.
Copyright
2000 Department of Computer Science, University of Regina.
[CS Dept Home Page]