Chapter 7. High-Quality Routines

 < Free Open Study > 

cc2e.com/0778

Contents

  • Valid Reasons to Create a Routine page 164

  • Design at the Routine Level page 168

  • Good Routine Names page 171

  • How Long Can a Routine Be? page 173

  • How to Use Routine Parameters page 174

  • Special Considerations in the Use of Functions page 181

  • Macro Routines and Inline Routines page 182

Related Topics

  • Steps in routine construction: Section 9.3

  • Working classes: Chapter 6

  • General design techniques: Chapter 5

  • Software architecture: Section 3.5

Chapter 6 described the details of creating classes. This chapter zooms in on routines, on the characteristics that make the difference between a good routine and a bad one. If you'd rather read about issues that affect the design of routines before wading into the nitty-gritty details, be sure to read Chapter 5, "Design in Construction," first and come back to this chapter later. Some important attributes of high-quality routines are also discussed in Chapter 8, "Defensive Programming." If you're more interested in reading about steps to create routines and classes, Chapter 9, "The Pseudocode Programming Process," might be a better place to start.

Before jumping into the details of high-quality routines, it will be useful to nail down two basic terms. What is a "routine"? A routine is an individual method or procedure invocable for a single purpose. Examples include a function in C++, a method in Java, a function or sub procedure in Microsoft Visual Basic. For some uses, macros in C and C++ can also be thought of as routines. You can apply many of the techniques for creating a high-quality routine to these variants.

What is a high-quality routine? That's a harder question. Perhaps the easiest answer is to show what a high-quality routine is not. Here's an example of a low-quality routine:

C++ Example of a Low-Quality Routine

 void HandleStuff( CORP_DATA & inputRec, int crntQtr, EMP_DATA empRec,    double & estimRevenue, double ytdRevenue, int screenX, int  screenY,    COLOR_TYPE & newColor, COLOR_TYPE & prevColor, StatusType &  status,    int expenseType ) { int i; for ( i = 0; i < 100; i++ ) {    inputRec.revenue[i] = 0;    inputRec.expense[i] = corpExpense[ crntQtr ][ i ];    } UpdateCorpDatabase( empRec ); estimRevenue = ytdRevenue * 4.0 / (double) crntQtr; newColor = prevColor; status = SUCCESS; if ( expenseType == 1 ) {      for ( i = 0; i < 12; i++ )            profit[i] = revenue[i] - expense.type1[i];      } else if ( expenseType == 2 ) {           profit[i] = revenue[i] - expense.type2[i];           } else if ( expenseType == 3 )           profit[i] = revenue[i] - expense.type3[i];           }


What's wrong with this routine? Here's a hint: you should be able to find at least 10 different problems with it. Once you've come up with your own list, look at the following list:

  • The routine has a bad name. HandleStuff() tells you nothing about what the routine does.

  • The routine isn't documented. (The subject of documentation extends beyond the boundaries of individual routines and is discussed in Chapter 32, "Self-Documenting Code.")

  • The routine has a bad layout. The physical organization of the code on the page gives few hints about its logical organization. Layout strategies are used haphazardly, with different styles in different parts of the routine. Compare the styles where expenseType == 2 and expenseType == 3. (Layout is discussed in Chapter 31, "Layout and Style.")

  • The routine's input variable, inputRec, is changed. If it's an input variable, its value should not be modified (and in C++ it should be declared const). If the value of the variable is supposed to be modified, the variable should not be called inputRec.

  • The routine reads and writes global variables it reads from corpExpense and writes to profit. It should communicate with other routines more directly than by reading and writing global variables.

  • The routine doesn't have a single purpose. It initializes some variables, writes to a database, does some calculations none of which seem to be related to each other in any way. A routine should have a single, clearly defined purpose.

  • The routine doesn't defend itself against bad data. If crntQtr equals 0, the expression ytdRevenue * 4.0 / (double) crntQtr causes a divide-by-zero error.

  • The routine uses several magic numbers: 100, 4.0, 12, 2, and 3. Magic numbers are discussed in Section 12.1, "Numbers in General."

  • Some of the routine's parameters are unused: screenX and screenY are not referenced within the routine.

  • One of the routine's parameters is passed incorrectly: prevColor is labeled as a reference parameter (&) even though it isn't assigned a value within the routine.

  • The routine has too many parameters. The upper limit for an understandable number of parameters is about 7; this routine has 11. The parameters are laid out in such an unreadable way that most people wouldn't try to examine them closely or even count them.

  • The routine's parameters are poorly ordered and are not documented. (Parameter ordering is discussed in this chapter. Documentation is discussed in Chapter 32.)

cc2e.com/0799

Aside from the computer itself, the routine is the single greatest invention in computer science. The routine makes programs easier to read and easier to understand than any other feature of any programming language, and it's a crime to abuse this senior statesman of computer science with code like that in the example just shown.

Cross-Reference

The class is also a good contender for the single greatest invention in computer science. For details on how to use classes effectively, see Chapter 6, "Working Classes."


The routine is also the greatest technique ever invented for saving space and improving performance. Imagine how much larger your code would be if you had to repeat the code for every call to a routine instead of branching to the routine. Imagine how hard it would be to make performance improvements in the same code used in a dozen places instead of making them all in one routine. The routine makes modern programming possible.

"OK," you say, "I already know that routines are great, and I program with them all the time. This discussion seems kind of remedial, so what do you want me to do about it?"

I want you to understand that many valid reasons to create a routine exist and that there are right ways and wrong ways to go about it. As an undergraduate computer-science student, I thought that the main reason to create a routine was to avoid duplicate code. The introductory textbook I used said that routines were good because the avoidance of duplication made a program easier to develop, debug, document, and maintain. Period. Aside from syntactic details about how to use parameters and local variables, that was the extent of the textbook's coverage. It was not a good or complete explanation of the theory and practice of routines. The following sections contain a much better explanation.

 < Free Open Study > 


Code Complete
Code Complete: A Practical Handbook of Software Construction, Second Edition
ISBN: 0735619670
EAN: 2147483647
Year: 2003
Pages: 334

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net