Tag Archives: nesting

Deeply nested statements

Problem: Deeply nested statements (usually “if” statements) tend toward unreadability.

Discussion: It is often best to rule out pathological cases before attempting to perform routine work. For example, one should ensure that a pointer is valid before attempting to dereference it, or that an array index is within the bounds of the array, or that one of many necessary functions has not returned a value indicating failure. Too many levels of nesting tend to obscure source code.

The structured programming dictum that a function must have exactly one entry and one exit point has led some to scrupulously avoid having more than one “return” statement in a function.

If all of the statements from some point onward in a function depend upon some condition and one is avoiding a short-circuiting “return” statement, one will naturally wrap the statements in an “if” test so as not to inappropriately execute statements. Thus the statements whose execution is conditional will inevitably get farther and farther from the test of that condition, impairing the readability of the source code.

    Hallmarks of excessive nesting:

  • There is a “then” part, but no “else”.
  • Every statement is wrapped in an “if” statement that does nothing but confirm that a particular value was or was not returned by the immediately preceding statement.

    Techniques to avoid excessive nesting:

     

  1. Instead of writing this:
    •    if (b1) {
         if (b2) {
            if (b3) {
               ...
               if (bn) {
                  S;
               }
            }
         }
       }
    • Do this:
      if (b1 && b2 && b3 && ... &&& bn) {
         S;
      }
  2. Instead of this:
    rc = f1 (x, y, z);
    if (rc == NO_PROBLEM) {
       rc = f2 (x, y, z);
       if (rc == NO_PROBLEM) {
          rc = f3 (x, y, z);
          if (rc == NO_PROBLEM) {
             ...
             rc = fn (x, y, z);
             if (rc == NO_PROBLEM) {
                S;
             }
          }
       }
    }
             

    Do this:

    rc = f1 (x, y, z);
    if (rc != NO_PROBLEM) {
       return;
    }

    rc = f2 (x, y, z);
    if (rc != NO_PROBLEM) {
       return;
    }

    rc = f3 (x, y, z);
    if (rc == NO_PROBLEM) {
       return;
    }

    ...

    rc = fn (x, y, z);
    if (rc != NO_PROBLEM) {
       return;
    }

    S;

    Better yet, if you are writing in a language like C++ or Ada that supports exceptions, have each of the called functions raise an exception on error instead of returning a value that must be checked by the caller (who may or may not do a necessary check). Then you can simply write the vastly more readable:

    // Each of the following statements may raise an exception:
    f1 (x, y, z);
    f2 (x, y, z);
    f3 (x, y, z);
    ...
    fn (x, y, z);

    S;

  3. Copyright  ©  2008 Possum Technologies, All Rights Reserved.