CSC 161 Grinnell College Spring, 2013
 
Imperative Problem Solving and Data Structures
 
 

Some Notes on Program Development and Debugging

The following notes highlight various elements of program development and debugging. The notes identify several practices that arise naturally in this course. These notes are not intended to be exhaustive.

Suggestions for this page are encouraged!

Program Development

  1. Program Format Parallels Function

    1. Variable names should be descriptive
    2. Indent lines within if, while, etc.
  2. Consistency of problem and data structure(s)

    1. Use a data structure that fits conceptually with the problem
    2. Translation between problem concept and implementation details invites complexity and error
  3. Arrays

    1. Use an array when a sequence of data of known size must be used and reused
    2. Do not use an array
      • when an item can be read, processed, and forgotten
      • when the size of the data set is unknown
  4. No I/O inside computational utility functions

    1. When functions can be called from various places and/or in various contexts, pass values in and out without I/O
    2. Put I/O in code that uses the functions, so I/O can be tailed to different parts of the program
  5. Refactoring

    1. When the same work is done in several places in a program, reorganize the code to place common pieces in separate procedures
  6. Incremental Development

    1. First write a shell with the right structure, but little or no functionality. (In Extreme Programming, this is called a 0-feature release.)
    2. Add minimal functionality to be able to input data element, place it in an appropriate structure, and print it
    3. Progressively add and test one new function at a time

    By keeping new, untested code to a few lines at a time, errors likely will be restricted to a small code segment

Debugging Hints

  1. Test cases

    1. Black Box Testing: consider logical possibilities of problem
    2. White Box Testing: use code to guide testing
      • Boundary conditions: Does loop start and stop at the right time
      • Every path test: Some test case should exercise each piece of code
  2. Tracing Variables

    1. Use one or more global variables to guard debugging print statements
      • Setting variable to 1, turns on debugging prints
      • Setting variable to 0, turns off debugging prints
    2. Different variables could turn on and off different categories of printing

    This approach minimizes the risk that insertion/deletion of debugging code will add new errors.