31.8. Laying Out Classes

 < Free Open Study > 

This section presents guidelines for laying out code in classes. The first subsection describes how to lay out the class interface. The second subsection describes how to lay out the class implementations. The final subsection discusses laying out files and programs.

Laying Out Class Interfaces

In laying out class interfaces, the convention is to present the class members in the following order:

Cross-Reference

For details on documenting classes, see "Commenting Classes, Files, and Programs" in Section 32.5. For a discussion of the differences between good and bad classes, see Chapter 6, "Working Classes."


  1. Header comment that describes the class and provides any notes about the overall usage of the class

  2. Constructors and destructors

  3. Public routines

  4. Protected routines

  5. Private routines and member data

Laying Out Class Implementations

Class implementations are generally laid out in this order:

  1. Header comment that describes the contents of the file the class is in

  2. Class data

  3. Public routines

  4. Protected routines

  5. Private routines

If you have more than one class in a file, identify each class clearly Routines that are related should be grouped together into classes. A reader scanning your code should be able to tell easily which class is which. Identify each class clearly by using several blank lines between it and the classes next to it. A class is like a chapter in a book. In a book, you start each chapter on a new page and use big print for the chapter title. Emphasize the start of each class similarly. An example of separating classes is shown in Listing 31-66:

Listing 31-66. C++ example of formatting the separation between classes
 // create a string identical to sourceString except that the       <-- 1 // blanks are replaced with underscores.                             | void EditString::ConvertBlanks(                                      |    char *sourceString,                                               |    char *targetString                                                |    ) {                                                               |    Assert( strlen( sourceString ) <= MAX_STRING_LENGTH );            |    Assert( sourceString != NULL );                                   |    Assert( targetString != NULL );                                   |    int charIndex = 0;                                                |    do {                                                              |       if ( sourceString[ charIndex ] == " " ) {                      |          targetString[ charIndex ] = '_';                            |       }                                                              |       else {                                                         |          targetString[ charIndex ] = sourceString[ charIndex ];      |    }                                                                 |    charIndex++;                                                      | } while sourceString[ charIndex ] != '\0';                           | }       <-- 1 //----------------------------------------------------------------------       <-- 2 // MATHEMATICAL FUNCTIONS                                                        | //                                                                               | // This class contains the program's mathematical functions.                     | //----------------------------------------------------------------------       <-- 2 // find the arithmetic maximum of arg1 and arg2       <-- 3 int Math::Max( int arg1, int arg2 ) {                   |    if ( arg1 > arg2 ) {                                 |       return arg1;                                      |    }                                                    |    else {                                               |       return arg2;                                      |    }                                                    | }       <-- 3 // find the arithmetic minimum of arg1 and arg2       <-- 4 int Math::Min( int arg1, int arg2 ) {                   |    if ( arg1 < arg2 ) {                                 |       return arg1;                                      |    }                                                    |    else {                                               |       return arg2;                                      |    }                                                    | }       <-- 4 

(1)This is the last routine in a class.

(2)The beginning of the new class is marked with several blank lines and the name of the class.

(3)This is the first routine in a new class.

(4)This routine is separated from the previous routine by blank lines only.

Avoid overemphasizing comments within classes. If you mark every routine and comment with a row of asterisks instead of blank lines, you'll have a hard time coming up with a device that effectively emphasizes the start of a new class. An example is shown in Listing 31-67:

Listing 31-67. C++ example of overformatting a class
//********************************************************************** //********************************************************************** // MATHEMATICAL FUNCTIONS // // This class contains the program's mathematical functions. //********************************************************************** //********************************************************************** //********************************************************************** // find the arithmetic maximum of arg1 and arg2 //********************************************************************** int Math::Max( int arg1, int arg2 ) { //**********************************************************************    if ( arg1 > arg2 ) {       return arg1;    }    else {       return arg2;    } } //********************************************************************** // find the arithmetic maximum of arg1 and arg2 //********************************************************************** int Math::Min( int arg1, int arg2 ) { //**********************************************************************    if ( arg1 < arg2 ) {       return arg1;    }    else {       return arg2;    } }

In this example, so many things are highlighted with asterisks that nothing is really emphasized. The program becomes a dense forest of asterisks. Although it's more an aesthetic than a technical judgment, in formatting, less is more.

If you must separate parts of a program with long lines of special characters, develop a hierarchy of characters (from densest to lightest) instead of relying exclusively on asterisks. For example, use asterisks for class divisions, dashes for routine divisions, and blank lines for important comments. Refrain from putting two rows of asterisks or dashes together. An example is shown in Listing 31-68:

Listing 31-68. C++ example of good formatting with restraint
 //********************************************************************** // MATHEMATICAL FUNCTIONS // // This class contains the program's mathematical functions. //********************************************************************** //----------------------------------------------------------------------       <-- 1 // find the arithmetic maximum of arg1 and arg2 //---------------------------------------------------------------------- int Math::Max( int arg1, int arg2 ) {    if ( arg1 > arg2 ) {       return arg1;    }    else {       return arg2;    } } //---------------------------------------------------------------------- // find the arithmetic minimum of arg1 and arg2 //---------------------------------------------------------------------- int Math::Min( int arg1, int arg2 ) {    if ( arg1 < arg2 ) {       return arg1;    }    else {       return arg2;    } } 

(1)The lightness of this line compared to the line of asterisks visually reinforces the fact that the routine is subordinate to the class.

This advice about how to identify multiple classes within a single file applies only when your language restricts the number of files you can use in a program. If you're using C++, Java, Visual Basic, or other languages that support multiple source files, put only one class in each file unless you have a compelling reason to do otherwise (such as including a few small classes that make up a single pattern). Within a single class, however, you might still have subgroups of routines, and you can group them using techniques such as the ones shown here.

Laying Out Files and Programs

Beyond the formatting techniques for classes is a larger formatting issue: how do you organize classes and routines within a file, and how do you decide which classes to put in a file in the first place?

Cross-Reference

For documentation details, see "Commenting Classes, Files, and Programs" in Section 32.5.


Put one class in one file A file isn't just a bucket that holds some code. If your language allows it, a file should hold a collection of routines that supports one and only one purpose. A file reinforces the idea that a collection of routines are in the same class.

All the routines within a file make up the class. The class might be one that the program really recognizes as such, or it might be just a logical entity that you've created as part of your design.

Cross-Reference

For details on the differences between classes and routines and how to make a collection of routines into a class, see Chapter 6, "Working Classes."


Classes are a semantic language concept. Files are a physical operating-system concept. The correspondence between classes and files is coincidental and continues to weaken over time as more environments support putting code into databases or otherwise obscuring the relationship between routines, classes, and files.

Give the file a name related to the class name Most projects have a one-to-one correspondence between class names and file names. A class named CustomerAccount would have files named CustomerAccount.cpp and CustomerAccount.h, for example.

Separate routines within a file clearly Separate each routine from other routines with at least two blank lines. The blank lines are as effective as big rows of asterisks or dashes, and they're a lot easier to type and maintain. Use two or three to produce a visual difference between blank lines that are part of a routine and blank lines that separate routines. An example is shown in Listing 31-69:

Listing 31-69. Visual Basic example of using blank lines between routines
 'find the arithmetic maximum of arg1 and arg2 Function Max( arg1 As Integer, arg2 As Integer ) As Integer    If ( arg1 > arg2 ) Then       Max = arg1    Else       Max = arg2    End If End Function        <-- 1          |          |        <-- 1 'find the arithmetic minimum of arg1 and arg2 Function Min( arg1 As Integer, arg2 As Integer ) As Integer    If ( arg1 < arg2 ) Then       Min = arg1    Else       Min = arg2    End If end Function 

(1)At least two blank lines separate the two routines.

Blank lines are easier to type than any other kind of separator and look at least as good. Three blank lines are used in this example so that the separation between routines is more noticeable than the blank lines within each routine.

Sequence routines alphabetically An alternative to grouping related routines in a file is to put them in alphabetical order. If you can't break a program up into classes or if your editor doesn't allow you to find functions easily, the alphabetical approach can save search time.

In C++, order the source file carefully Here's a typical order of source-file contents in C++:

  1. File-description comment

  2. #include files

  3. Constant definitions that apply to more than one class (if more than one class in the file)

  4. Enums that apply to more than one class (if more than one class in the file)

  5. Macro function definitions

  6. Type definitions that apply to more than one class (if more than one class in the file)

  7. Global variables and functions imported

  8. Global variables and functions exported

  9. Variables and functions that are private to the file

  10. Classes, including constant definitions, enums, and type definitions within each class

cc2e.com/3194

Checklist: Layout

General

  • Is formatting done primarily to illuminate the logical structure of the code?

  • Can the formatting scheme be used consistently?

  • Does the formatting scheme result in code that's easy to maintain?

  • Does the formatting scheme improve code readability?

Control Structures

  • Does the code avoid doubly indented begin-end or {} pairs?

  • Are sequential blocks separated from each other with blank lines?

  • Are complicated expressions formatted for readability?

  • Are single-statement blocks formatted consistently?

  • Are case statements formatted in a way that's consistent with the formatting of other control structures?

  • Have gotos been formatted in a way that makes their use obvious?

Individual Statements

  • Is white space used to make logical expressions, array references, and routine arguments readable?

  • Do incomplete statements end the line in a way that's obviously incorrect?

  • Are continuation lines indented the standard indentation amount?

  • Does each line contain at most one statement?

  • Is each statement written without side effects?

  • Is there at most one data declaration per line?

Comments

  • Are the comments indented the same number of spaces as the code they comment?

  • Is the commenting style easy to maintain?

Routines

  • Are the arguments to each routine formatted so that each argument is easy to read, modify, and comment?

  • Are blank lines used to separate parts of a routine?

Classes, Files and Programs

  • Is there a one-to-one relationship between classes and files for most classes and files?

  • If a file does contain multiple classes, are all the routines in each class grouped together and is each class clearly identified?

  • Are routines within a file clearly separated with blank lines?

  • In lieu of a stronger organizing principle, are all routines in alphabetical sequence?


 < 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