Laying Out Classes

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 Commenting Techniques. For a discussion of the differences between good and bad classes, see Chapter 6.

  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 Example 31-66:

Example 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 ] != '';                           |
}       <-- 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 Example 31-67:

Example 31-67. C++ example of overformatting a class

//**********************************************************************
//**********************************************************************
// MATHEMATICAL FUNCTIONS
//
// This class contains the program's mathematical functions.
//**********************************************************************
//**********************************************************************

//**********************************************************************
// find the arithmetic minimum 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 Example 31-68:

Example 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 Commenting Techniques.

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.

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 Example 31-69:

Example 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

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.247.53