Code Complete Book Review (part 4 of 7)

As I continue this review of Code Complete by Steve McConnell, we look at how to organize our statements to keep our code readable and maintainable. As I read through, many of these problems are solved in modern programming languages, while others are still very relevant.

  • Statements
    • Organizing Straight Line Code
      • Statements that must be in a specific order- Ideally, the flow of your program will make it obvious that certain calls are required before others (load, calculate, display). If you cannot change your code to make this obvious, be sure to add comments or documentation explaining any hidden dependencies.
      • If your statements don’t rely on any type of order, focus on readability from top to bottom.
      • Checklist for Organizing Straight Line Code
    • Using Conditionals
      • if statement
        • Write your normal case first. Put any exception code in your else blocks. 50-80% of if blocks require an else block, so if you have a "naked if" double check that there isn’t an extra exception case.
        • Be sure that you put the proper logic in the if and else blocks. It’s very common to reverse these.
        • Simplify complicated tests with boolean function calls. If you name your functions properly, this should enhance readability.
      • case statement
        • order cases meaningfully
        • make the case actions simple. Call external routines if necessary
        • Use the default case to catch exceptions
      • Checklist for using conditionals
    • Controlling Loops
      • Selecting the Loop – Loop structures (for, foreach, while) are chosen based on two parameters: flexibility and and test location. Some loops are flexible in how many times they are run, others run a predetermined number of times. You can also structure loops to test at the beginning or end of each loop.
      • Controlling the Loop
      • Creating Loops – Inside Out- The easiest way to write complex looping structures is two write an initial case with hardcoded values, then indent your code and put that in a loop. Repeat as many times as necessary to create a complex nested loop.
      • Correspondence between Loops and Arrays- If you are using a loop to manipulate the items in an array or list, check to see if your language supports bulk operations (or map). This will allow you to escape from looping entirely.
    • Unusual Control Structures
      • Multiple returns from a routine- This happens when you have extensive test cases and you want to jump out of the routine (no data, invalid data, network connection down). In these cases it makes sense to just quit the routine, rather than try to net several test statements.
      • Recursion- This is a favorite of cs types because it creates "elegant" solutions. However, in practice this can be dangerous because you can "smash the stack", or run out of memory quickly by recursing too deep. Be sure to add a "safety counter"to allow you to jump out if things run too long. Also, investigate iteration as opposed to recursion. 
      • Goto statement considered harmful – This article is over 40 years old, so I’ll assume that you’re not jumping around in your code. If you are there are several approaches you can use to keep your code easier to follow, including nested if’s, status variables, and try .. finally blocks.
      • Safety Checklist for Unusual Control Structures
    • Table Driven Methods- A table-driven method is a scheme that allows you to look up information in a table rather than using logic statements (if and case) to figure it out. Virtually anything you can select with logic statements, you can select with tables instead. In simple cases, logic statements are easier and more direct. As the logic chain becomes more complex, tables become increasingly attractive.
      • Direct Access Tables – these are your basic key/value lookups. Remember that you will need a key for every value. If you want to do a lookup on a range (say ages from 0-17, 18-20, 21-65, 66+), you will probably want to transform the value (the age) to a generic key value.
      • Indexed Access Tables- As you build more data fields, you may want to lookup tuples in different ways (age, social security number, name). In this case you would build a table and multiple indices. The strength to this approach is that as the data access evolves, it’s much easier to optimize, drop, change indexes as opposed to the underlying data.
    • General Control Issues
      • Boolean expressions
        • To improve readability, use implicit boolean tests (if (UserIsValid)). This is one less variable that the next programmer has to remember.
        • If your code has complex logic, rewrite these tests as boolean functions.
      • Compound statements (blocks). This is everything between the curly {} braces. 
        • Always write the braces first.
      • Taming Deeply Nested Loops
        • Rewrite extensive logic inside loops as their own routines.
        • Use objects and polymorphic dispatching
        • Use guard cases to protect the routine and keep the nominal case easy to understand
    • Structured Programming – The core thesis of structured programming is that any control flow whatsoever can be created from these three constructs of sequence, selection, and iteration. Programmers sometimes favor language structures that increase convenience, but programming seems to have advanced largely by restricting what we are allowed to do with our programming languages. Prior to structured programming, use of goto provided the ultimate in control-flow convenience, but code written that way turned out to be incomprehensible and unmaintainable. My belief is that use of any control structure other than the three standard structured programming constructs—that is, the use of break, continue, return, throw-catch, and so on—should be viewed with a critical eye.
    • Controlling Complexity- The easiest way to determine if your routines are "too complex" is to calculate the cyclomatic complexity. Many static code analyzers will perform these calculations for you. Any score over ten should be broken into multiple routines.

    This material is copied and/or adapted from the Code Complete 2 Website at cc2e.com. This material is Copyright © 1993-2007 Steven C. McConnell. Permission is hereby given to copy, adapt, and distribute this material as long as this notice is included on all such materials and the materials are not sold, licensed, or otherwise distributed for commercial gain.

  • Leave a Reply

    Name *
    Email *
    Website