15.2. case Statements

 < Free Open Study > 

15.2. case Statements

The case or switch statement is a construct that varies a great deal from language to language. C++ and Java support case only for ordinal types taken one value at a time. Visual Basic supports case for ordinal types and has powerful shorthand notations for expressing ranges and combinations of values. Many scripting languages don't support case statements at all.

The following sections present guidelines for using case statements effectively:

Choosing the Most Effective Ordering of Cases

You can choose from among a variety of ways to organize the cases in a case statement. If you have a small case statement with three options and three corresponding lines of code, the order you use doesn't matter much. If you have a long case statement for example, a case statement that handles dozens of events in an event-driven program order is significant. Following are some ordering possibilities:

Order cases alphabetically or numerically If cases are equally important, putting them in A-B-C order improves readability. That way a specific case is easy to pick out of the group.

Put the normal case first If you have one normal case and several exceptions, put the normal case first. Indicate with comments that it's the normal case and that the others are unusual.

Order cases by frequency Put the most frequently executed cases first and the least frequently executed last. This approach has two advantages. First, human readers can find the most common cases easily. Readers scanning the list for a specific case are likely to be interested in one of the most common cases, and putting the common ones at the top of the code makes the search quicker.

Tips for Using case Statements

Here are several tips for using case statements:

Keep the actions of each case simple Keep the code associated with each case short. Short code following each case helps make the structure of the case statement clear. If the actions performed for a case are complicated, write a routine and call the routine from the case rather than putting the code into the case itself.

Cross-Reference

For other tips on simplifying code, see Chapter 24, "Refactoring."


Don't make up phony variables to be able to use the case statement A case statement should be used for simple data that's easily categorized. If your data isn't simple, use chains of if-then-elses instead. Phony variables are confusing, and you should avoid them. For example, don't do this:

Java Example of Creating a Phony case Variable---Bad Practice

action = userCommand[ 0 ]; switch ( action ) {    case 'c':       Copy();       break;    case 'd':       DeleteCharacter();       break;    case 'f':       Format();       break;    case 'h':       Help();       break;    ...    default:       HandleUserInputError( ErrorType.InvalidUserCommand ); }


The variable that controls the case statement is action. In this case, action is created by peeling off the first character of the userCommand string, a string that was entered by the user.

This troublemaking code is from the wrong side of town and invites problems. In general, when you manufacture a variable to use in a case statement, the real data might not map onto the case statement the way you want it to. In this example, if the user types copy, the case statement peels off the first "c" and correctly calls the Copy() routine. On the other hand, if the user types cement overshoes, clambake, or cellulite, the case statement also peels off the "c" and calls Copy(). The test for an erroneous command in the case statement's else clause won't work very well because it will miss only erroneous first letters rather than erroneous commands.

Cross-Reference

In contrast to this advice, sometimes you can improve readability by assigning a complicated expression to a well-named boolean variable or function. For details, see "Making Complicated Expressions Simple" in Section 19.1.


Rather than making up a phony variable, this code should use a chain of if-then-else-if tests to check the whole string. A virtuous rewrite of the code looks like this:

Java Example of Using if-then-elses Instead of a Phony case Variable---Good Practice
if ( UserCommand.equals( COMMAND_STRING_COPY ) ) {    Copy(); } else if ( UserCommand.equals( COMMAND_STRING_DELETE ) ) {    DeleteCharacter(); } else if ( UserCommand.equals( COMMAND_STRING_FORMAT ) ) {    Format(); } else if ( UserCommand.equals( COMMAND_STRING_HELP ) ) {    Help(); } ... else {    HandleUserInputError( ErrorType_InvalidCommandInput ); }

Use the default clause only to detect legitimate defaults You might sometimes have only one case remaining and decide to code that case as the default clause. Though sometimes tempting, that's dumb. You lose the automatic documentation provided by case-statement labels, and you lose the ability to detect errors with the default clause.

Such case statements break down under modification. If you use a legitimate default, adding a new case is trivial you just add the case and the corresponding code. If you use a phony default, the modification is more difficult. You have to add the new case, possibly making it the new default, and then change the case previously used as the default so that it's a legitimate case. Use a legitimate default in the first place.

Use the default clause to detect errors If the default clause in a case statement isn't being used for other processing and isn't supposed to occur, put a diagnostic message in it:

Java Example of Using the Default Case to Detect Errors---Good Practice
switch ( commandShortcutLetter ) {    case 'a':       PrintAnnualReport();       break;    case 'p':       // no action required, but case was considered       break;    case 'q':       PrintQuarterlyReport();       break;    case 's':       PrintSummaryReport();       break;    default:       DisplayInternalError( "Internal Error 905: Call customer support." ); }

Messages like this are useful in both debugging and production code. Most users prefer a message like "Internal Error: Please call customer support" to a system crash or, worse, subtly incorrect results that look right until the user's boss checks them.

If the default clause is used for some purpose other than error detection, the implication is that every case selector is correct. Double-check to be sure that every value that could possibly enter the case statement would be legitimate. If you come up with some that wouldn't be legitimate, rewrite the statements so that the default clause will check for errors.

In C++ and Java, avoid dropping through the end of a case statement C-like languages (C, C++, and Java) don't automatically break out of each case. Instead, you have to code the end of each case explicitly. If you don't code the end of a case, the program drops through the end and executes the code for the next case. This can lead to some particularly egregious coding practices, including the following horrible example:

C++ Example of Abusing the case Statement

switch ( InputVar ) {    case 'A': if ( test ) {                    // statement 1                    // statement 2    case 'B':       // statement 3                    // statement 4                    ...                    }                ...             break;    ... }


Cross-Reference

This code's formatting makes it look better than it is. For details on how to use formatting to make good code look good and bad code look bad, see "Endline Layout" in Section 31.3 and the rest of Chapter 31, "Layout and Style."


This practice is bad because it intermingles control constructs. Nested control constructs are hard enough to understand; overlapping constructs are all but impossible. Modifications of case 'A' or case 'B' will be harder than brain surgery, and it's likely that the cases will need to be cleaned up before any modifications will work. You might as well do it right the first time. In general, it's a good idea to avoid dropping through the end of a case statement.

In C++, clearly and unmistakably identify flow-throughs at the end of a case statement If you intentionally write code to drop through the end of a case, clearly comment the place at which it happens and explain why it needs to be coded that way.

C++ Example of Documenting Falling Through the End of a case Statement
switch ( errorDocumentationLevel ) {    case DocumentationLevel_Full:       DisplayErrorDetails( errorNumber );       // FALLTHROUGH -- Full documentation also prints summary comments    case DocumentationLevel_Summary:       DisplayErrorSummary( errorNumber );       // FALLTHROUGH -- Summary documentation also prints error number    case DocumentationLevel_NumberOnly:       DisplayErrorNumber( errorNumber );       break;    default:       DisplayInternalError( "Internal Error 905: Call customer support." ); }

This technique is useful about as often as you find someone who would rather have a used Pontiac Aztek than a new Corvette. Generally, code that falls through from one case to another is an invitation to make mistakes as the code is modified, and it should be avoided.

cc2e.com/1545

Checklist: Using Conditionals if-then Statements

  • Is the nominal path through the code clear?

  • Do if-then tests branch correctly on equality?

  • Is the else clause present and documented?

  • Is the else clause correct?

  • Are the if and else clauses used correctly not reversed?

  • Does the normal case follow the if rather than the else?

if-then-else-if Chains

  • Are complicated tests encapsulated in boolean function calls?

  • Are the most common cases tested first?

  • Are all cases covered?

  • Is the if-then-else-if chain the best implementation better than a case statement?

case Statements

  • Are cases ordered meaningfully?

  • Are the actions for each case simple calling other routines if necessary?

  • Does the case statement test a real variable, not a phony one that's made up solely to use and abuse the case statement?

  • Is the use of the default clause legitimate?

  • Is the default clause used to detect and report unexpected cases?

  • In C, C++, or Java, does the end of each case have a break?


 < 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