Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Professional C++ [eng].pdf
Скачиваний:
1715
Добавлен:
16.08.2013
Размер:
11.09 Mб
Скачать

Chapter 7

functions? When you’re writing code, imagine that somebody new will have to maintain it in the future. Will you even remember how it works? What if you’re not available to help? Well-written code avoids these problems because it is easy to read and understand.

Keeping It Clear

Present concerns are another reason to write good code. Unless you’re working alone on a project and always will be, other programmers are going to look at, and possibly modify, your code. By writing code that your team can actually read and understand, you free yourself from constant questions and complaints.

Elements of Good Style

It is difficult to enumerate the characteristics of code that make it “stylistically good.” Over time, you’ll find styles that you like and notice useful techniques in code that others wrote. Perhaps more importantly, you’ll encounter horrible code that teaches you what to avoid. However, good code shares several universal tenets that will be explored in this chapter.

Documentation

Decomposition

Naming

Use of the Language

Formatting

Documenting Your Code

In the programming context, documentation usually refers to comments that are contained in the source files. Comments are your opportunity to tell the world what was going through your head when you wrote the accompanying code. They are a place to say anything that isn’t obvious from looking at the code itself.

Reasons to Write Comments

It may seem obvious that writing comments is a good idea, but have you ever stopped to think about why you need to comment your code? Sometimes programmers recognize the importance of commenting without fully understanding why comments are important. There are several reasons, explored next.

Commenting to Explain Usage

One reason to use comments is to explain how clients should interact with the code. As you read in Chapter 5, each publicly accessible function or method in a header file should have a comment explaining what it does. Some organizations prefer to formalize these comments by explicitly listing the purpose of each method, what each of its arguments are, what values it returns, and possible exceptions it can throw.

136

Coding with Style

Providing a comment with public methods accomplishes two things. First, you are given the opportunity to state, in English, anything that you can’t state in code. For example, there’s really no way in C++ code to indicate that the adjustVolume() method of a media player object can only be called after the initialize() method is called. A comment, however, can be the perfect place to note this restriction, as follows.

/*

*adjustVolume()

*Sets the player volume based on the user’s

*preferences

*

*This method will throw an “UninitializedPlayerException”

*if the initialize() method has not yet been called.

*/

The second effect of a comment on a public method can be to state usage information. The C++ language forces you to specify the return type of a method, but it does not provide a way for you to say what the returned value actually represents. For example, the declaration of the adjustVolume() method may indicate that it returns an int, but the client reading that declaration wouldn’t know what the int means. Other ancillary data can be included in a comment as well, as shown here:

/*

*adjustVolume()

*Sets the player volume based on the user’s

*preferences

*

*Parameters:

*none

*Returns:

*an int, which represents the new volume setting.

*Throws:

*UninitializedPlayerException if the initialize() method has not

*yet been called.

*

Commenting to Explain Complicated Code

Good comments are also important inside the actual source code. In a simple program that processes input from the user and writes a result to the console, it is probably easy to read through and understand all of the code. In the professional world, however, you will often need to write code that is algorithmically complex or too esoteric to understand simply by inspection.

Consider the code that follows. It is well written, but it may not be immediately apparent what it is doing. You might recognize the algorithm if you have seen it before, but a newcomer probably wouldn’t understand the way the code works.

137

Chapter 7

void sort(int inArray[], int inSize)

{

for (int i = 1; i < inSize; i++) { int element = inArray[i];

int j = i – 1;

while (j >= 0 && inArray[j] > element) { inArray[j+1] = inArray[j];

j--;

}

inArray[j+1] = element;

}

}

A better approach would be to include comments that describe the algorithm that is being used. In the modified function that follows, a thorough comment at the top explains the algorithm at a high level, and inline comments explain specific lines that may be confusing.

/*

*Implements the “insertion sort” algorithm. The algorithm separates the array

*into two parts--the sorted part and the unsorted part. Each element, starting

*at position 1, is examined. Everything earlier in the array is in the sorted

*part, so the algorithm shifts each element over until the correct position is

*found for the current element. When the algorithm finishes with the last

*element, the entire array is sorted.

*/

void sort(int inArray[], int inSize)

{

// Start at position 1 and examine each element. for (int i = 1; i < inSize; i++) {

int element = inArray[i];

//j marks the position in the sorted part of the array. int j = i – 1;

//As long as the current slot in the sorted array is higher than

//the element, shift the slot over and move backwards.

while (j >= 0 && inArray[j] > element) { inArray[j+1] = inArray[j];

j--;

}

//At this point the current position in the sorted array

//is *not* greater than the element, so this is its new position. inArray[j+1] = element;

}

The new code is certainly more verbose, but a reader unfamiliar with sorting algorithms would be much more likely to understand it with the comments included. In some organizations, inline comments are frowned upon. In such cases, writing clean code and having good comments at the top of the function becomes vital.

138

Coding with Style

Commenting to Convey Metainformation

Another reason to use comments is to provide information at a higher level than the code itself. This metainformation provides details about the creation of the code without addressing the specifics of its behavior. For example, your organization may want to keep track of the original author of each method. You can also use metainformation to cite external documents or refer to other code.

The example below shows several instances of metainformation, including the author of the file, the date it was created, and the specific feature it addresses. It also includes inline comments expressing metadata, such as the bug number that corresponds to a line of code and a reminder to revisit a possible problem in the code later.

/*

*Author: klep

*Date: 040324

*Feature: PRD version 3, Feature 5.10

*/

int adjustVolume()

{

if (fUninitialized) {

throw UninitializedPlayerException();

}

int newVol = getPlayer()->getOwner()->getPreferredVolume();

if (newVol == -1) return -1; // Added to address bug #142 – jsmith 040330

setVolume(newVol);

// TODO: What if setVolume() throws an exception? – akshayr 040401

return newVol;

}

It’s easy to go overboard with comments. A good approach is to discuss which types of comments are most useful with your group and form a policy. For example, if one member of the group uses a “TODO” comment to indicate code that still needs work, but nobody else knows about this convention, the code in need could be overlooked.

If your group decides to use metainformation comments, make sure that you all include the same information or your files will be inconsistent!

139