Code Complete

Steve McConnell

Software Construction

Software construction is the central activity in software development; construction is the only activity that’s guaranteed to happen on every project.

The main activities in construction are detailed design, coding, debugging, integration, and developer testing (unit testing and integration testing).

Measures Twice, Cut Once: Upstream Prerequisites

  • The overarching goal of preparing for construction is risk reduction. Be sure your preparation activities are reducing risks, not increasing them.
  • Attention to quality must be part of the software-development process from the beginning to the end.
  • Part of a programmer’s job is to educate bosses and coworkers about the software-development process, including the importance of adequate preparation before programming begins.
  • If a good problem definition hasn’t been specified, you might be solving the wrong problem during construction.

Designs in Construction

  • Software’s Primary Technical Imperative is managing complexity. This is greatly aided by a design focus on simplicity.

Abstract Factory: Supports creation of sets of related objects by specifying the kind of set but not the kinds of each specific object.
Adapter: Converts the interface of a class to a different interface.
Bridge: Builds an interface and an implementation in such a way that either can vary without the other varying.
Composite: Consists of an object that contains additional objects of its own type so that client code can interact with the top-level object and not concern itself with all the detailed objects.
Decorator: Attaches responsibilities to an object dynamically, without creating specific subclasses for each possible configuration of responsibilities.
Facade: Provides a consistent interface to code that wouldn’t otherwise offer a consistent interface.
Factory Method: Instantiates classes derived from a specific base class without needing to keep track of the individual derived classes anywhere but the Factory Method.
Iterator: A server object that provides access to each element in a set sequentially.
Observer: Keeps multiple objects in synch with one another by making an object responsible for notifying the set of related objects about changes to any member of the set.
Singleton: Provides global access to a class that has one and only one instance.
Strategy: Defines a set of algorithms or behaviors that are dynamically interchangeable with each other.
Template: Method Defines the structure of an algorithm but leaves some of the detailed implementation to subclasses.

High Quality Routines

  • Sequence of code that is intended to be called and used repeatedly during the executable of a program. This makes the program shorter and easier to write/read.
  • Reduce complexity
  • Introduce an intermediate, understandable abstraction
  • Avoid duplicate code
  • Support sub classing
  • Hide sequences
  • Improve portability
  • Simplify complicated Boolean tests
  • Improve performance

Valid reasons for creating a routine

Tips for routine names

  • Describe everything the routine does
  • Avoid meaningless, vague, or wishy-washy verbs
  • Don’t differentiate routine names solely by number
  • Make names of routines as long as necessary (between 9 and 15 characters)
  • To name a function, use a description of the return value
  • To name a procedure, use a strong verb followed by an object
  • Use opposites precisely (Ex: add/remove , begin/end, get/set, insert/delete)
  • The main idea is that if a routine is passed bad data, it won’t be hurt, even if the bad data is another routine’s fault.
  • It’s the recognition that programs will have problems and modifications, and that a smart programmer will develop code accordingly.

  • Proper steps in defensive programming:

    1- what should I do?

    2- how many ways can it fail?

    3- how do I know when it fails?

    4- how do I prevent it from failing?

    5- write code accordingly

Defensive Programming

  • Exceptions are a specific means by which code can pass along errors or exceptional events to the code that called it. If code in one routine encounters an unexpected condition that it doesn’t know how to handle, it throws an exception.

Exceptions

Suggestions for exceptions

  • Use exceptions to notify other parts of the program about errors that should not be Ignored
  • Throw an exception only for conditions that are truly exceptional
  • Avoid throwing exceptions in constructors and destructors unless you catch them in the same place
  • Avoid empty catch blocks
  • Know the exceptions your library code throws
  • Consider building a centralized exception reporter
  • Standardize your project’s use of exceptions

Using Variables

  • Turn off implicit declarations
  • Declare all variables
  • Use naming conventions
  • Check variables names
  • Initialize each variable as It’s declared
  • Initialize each variable close to where it’s first used
  • Ideally, declare and define each variable close to where it’s first used
  • Initialize a class’s member data in its constructor
  • Avoid misleading names or abbreviations
  • Avoid numerals in names
  • Check input parameters for validity

If statements

  • Write the nominal path through the code first; then write the unusual cases
  • Make sure that you branch correctly on equality
  • Put the normal case after the if rather than after the else
  • Follow the if clause with a meaningful statement
  • Consider the else clause
  • Test the else clause for correctness
  • Check for reversal of the if and else clauses

Case statements

  • Order cases alphabetically or numerically
  • Put the normal case first
  • Order cases by frequency
  • Keep the actions of each case simple
  • Don’t make up phony variables to be able to use the case statement
  • Use the default clause only to detect legitimate defaults
  • Use the default clause to detect errors

Conditionals

Entering the loop

  • Enter the loop from one location only
  • Put initialization code directly before the loop
  • Use while( true ) for infinite loops
  • Prefer for loops when they’re appropriate
  • Don’t use a for loop when a while loop is more appropriate

Controlling Loops

Processing the loop

  • Use { and } to enclose the statements in a loop
  • Avoid empty loops
  • Make each loop perform only one function

Exiting the loop

  • Assure yourself that the loop ends
  • Make loop-termination conditions obvious
  • Don’t monkey with the loop index of a for loop to make the loop terminate

Code Complete

By Jean Paul Demorizi

Code Complete

Code Complete

  • 977