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

Coding with Style

void copyString(const char* inSource, char* outDest)

{

int i = 0;

while (outDest[i] = inSource[i++]); outDest[i] = ‘\0’;

}

Another way of writing self-documenting code is to break up, or decompose, your code into smaller pieces. Decomposition is covered in detail in the matierial that follows.

Good code is naturally readable and only requires comments to provide useful additional information.

Comments in This Book

The code examples you will see in this book often use comments to explain complicated code or to point things out to you that may not be evident. We usually omit any prefix comments and fixed-format comments to save space, but we wholeheartedly advocate their inclusion in professional C++ projects.

Decomposition

Decomposition is the practice of breaking up code into smaller pieces. There is nothing more daunting in the world of coding than opening up a file of source code to find 300-line functions and massive nested blocks of code. Ideally, each function or method should accomplish a single task. Any subtasks of significant complexity should be decomposed into separate functions or methods. For example, if somebody asks you what a method does and you answer “First it does A, then it does B; then, if C, it does D; otherwise, it does E,” you should probably have separate helper methods for A, B, C, D, and E.

Decomposition is not an exact science. Some programmers will say that no function should be longer than a page of printed code. That may be a good rule of thumb, but you could certainly find a quarterpage of code that is desperately in need of decomposition. Another rule of thumb is, whether the code is long or short, if you squint your eyes and look at the format of the code without reading the actual content, it shouldn’t appear too dense in any one area. For example, Figures 7-2 and 7-3 show code that has been purposely blurred so that you can’t read the content. It should be obvious that the code in Figure 7-3 has better decomposition than the code in Figure 7-2.

145

Chapter 7

Figure 7-2

Figure 7-3

146

Coding with Style

Decomposition through Refactoring

Sometimes when you’ve had a few sodas and you’re really in the programming zone, you start coding so fast that you end up with code that does exactly what it’s supposed to do, but is far from pretty. All programmers do this from time to time. Short periods of vigorous coding are sometimes the most productive times in the course of a project.

Dense code also arises over the course of time as code is modified. As new requirements and bug fixes emerge, existing code is amended with small modifications. The computing term cruft refers to the gradual accumulation of small amounts of code that eventually turns a once-elegant piece of code into a mess of patches and special cases.

Whether your code starts its life as a dense block of unreadable cruft or it just evolves that way, refactoring is necessary to periodically purge the code of accumulated hacks. Through refactoring, you revisit existing code and rewrite it to make it more readable and maintainable. Refactoring is an opportunity to revisit the decomposition of code. If the purpose of the code has changed or if it was never decomposed in the first place, when you refactor the code, squint at it and determine if it needs to be broken down into smaller parts.

Decomposition by Design

Decomposition is a boon for procrastinators. If you write your code using decomposition from the beginning, you can put off the hard parts until later. This style of coding, often called top-down design, takes a high-level view of the program and subsequently moves into more specific pieces.

For example, using top-down design, you could immediately get the main body of code down for a program that simulates a hurricane. The following code shows a possible implementation of main() for such a program.

int main(int argc, char** argv)

{

cout << “Welcome to the Hurricane Simulator” << endl;

getUserInputs();

performCalculations();

outputResults();

}

By taking a top-down approach, you accomplish two things. First, you can start coding immediately. Even if the program doesn’t turn out the way you initially viewed it at a high level, writing some code might help you organize your thoughts. Second, the program will evolve naturally in a well-decomposed way. If you approach every method or function by considering what pieces of it you can put off until later, your programs will generally be less dense and more organized than if you implemented every feature in its entirety as you coded.

Of course, we still advocate that you do some design of your program before jumping into the code. However, a top-down approach can be helpful when deciding on the specific implementation of a part of your program or when working on small projects.

147