1. Modularity through top-down design in CSC 175, in 275 we add the tool of modularity using
          objects implemented with classes.
          2. Modifiability
          3. User interface
          4. Fail-safe programming
          5. Style
          6. Debugging

1) MODULARITY: Modular programs have several advantages. Modularity through top-down design.

• Large program are much more difficult for inexperienced programmers to code. With the modular approach
   writing a large program is reduced to writing many small programs.

• Large programs are more difficult to test exhaustively. ( hard to debug) Modularity isolates errors therefore
   simplifies debugging.

• Large programs are more difficult to modify. A small Change in a modular program should only effect a few

• Large program are less likely to be reusable for other related applications.

• Modular programs are easier to read and understand. The objective in the use to modules is to
   control the complexity, to Limit The Extent Of Program Text The Human Eye
   And Mind Need Comprehend At One Moment.

•    Modularity Is The Single Attribute Of Software That Allows A
    Program To Be Intellectually Handled.


Examples of two simple techniques which make programs easier to modify include:

    A. use of subprograms, procedures & functions and

    B. use of user-defined constants.

     2A) Subprograms: Given program application used within a library which represents books using
     the following record statements.

     struct bookRecord
                                                                                         6 Key Programming Issues p. 1
              char Author [MAXNAME];
              string Title
              float CallNumber;

If at several places within this program, a book record information is printed out using code:

        writeln('Call number: ', aBook.callno );
        writeln('Author : ', aBook.Author);
        writeln('Title : ', aBook.Title)

Although this is not a great amount of code, we could still group the code into a procedure as:
void PrintBookRec ( struct bookRecord aBook)
       // fixed point output with two decimal places displayed
      cout.setf (ios::showpoint);
      cout.precision (0);

        cout << "\nBook Record Data Information\n";
        cout << "Call number: " << aBook.CallNumber << endl;
        cout << "Author : " << aBook.Author) << endl;
        cout << "Title : " << aBook.Title) << endl;
      }// PrintBookRec

Not only do we gain the advantage of eliminating REDUNDANT CODE, but it also makes the program easier to

For example, say after running the library program for a year, it is decided to maintain more information with each
book record, with the addition of pages. i.e. bookRecord defined as:
    struct bookRecord
          char Author [MAXNAME];
          string Title
          int   Pages;
          float CallNumber;

When we add another field to the record type declaration, then every time we print out a book record we must
include this new information in the output.

If we had NOT isolated the book output to a procedure, we would have had to search the entire program for
occurrences of code that printed book information, whereas with a PROCEDURE ONE STATEMENT would be
                                                                                          6 Key Programming Issues p. 2
added to the PrintBookRec procedure.
       cout << "Pages: " << aBook.Pages << endl;
2B) User-defined constants:
The restriction that an array be of a predefined, fixed size sometimes causes a difficulty. You must dimension your
program as the largest array you may ever need.

For example, if you were writing a program to perform extended precision arithmetic, you would probably be using
an array of integers. You might define an array of integer digits to hold the largest numbers your program will
process. You could write:
        int digits[50];

and initialize these numbers with code something like this below:
     for     (int I        = 0;      I < 50; I ++)
             digits[I] = 0;

A more general approach would be to define a constant representing the
maximum number of digits.
     const MAXDIGITS = 100;
     int digits[MAXDIGITS];

then reference all elements of the array using MAXDIGITS as the upper limit on the bounds rather than the
number 50. i.e.

       for (int I = 0;                I < MAXDIGITS; I ++)
         digits[I] = 0;


Designing a user friendly interface for interactive programs can be very time consuming but is worth the effort if the
program will be run time and time again. Some obvious points:

     a. Prompt the user for input with a descriptive message, what is valid input data?

     b. Echo the input data appropriate both for interactive input and data from a file. Gives the user a check on data
         entered, checks typos etc. and may help as a debugging tool when your program is not generating the
         correct output. Wrong answer because not reading data correctly.

     c. Output should be well labeled and easy to read.


                                                                                          6 Key Programming Issues p. 3
Fail safe program is one that performs reasonably no matter how anyone uses it. This goal is usually
unattainable. A more realistic goal is to anticipate the ways that people might misuse the program and to
guard carefully against these abuses.

We will consider the example taken from the text beginning on page 24.

This is an example of a program that is not fail-safe. This program computes statistics about the people in
income brackets between 10,000 and 100,000. Brackets are rounded to the nearest thousand dollars:
10,000,11,000 etc. up to 100,000.

(Example Programs Here)

5) STYLE: Eight Issues of Style required of programs written for this class:
                 1) Extensive use of subprograms
                2) Avoidance of global variables in subprograms
                3) Proper use of variable parameters
                4) Proper use of functions
                5) Avoidance of goto
                6) Error handing
                7) Readability
                 8) Documentation

6) DEBUGGING: Programs can and should be a logical and orderly process. Three Classes of Errors:

Syntax Errors, Run-Time Errors & Logic Errors.

    6a) Syntax Error: violation of grammatical rules of the language. ( Usually found by the compiler. Easiest to
         find and correct.)

    6b) Run-time Error: Causes abnormal program behavior during execution. Possible causes:
             a. array subscript out of bounds
             b. subrange variable out of bounds
             c. division by zero
             d. input errors such as attempts to read past end-of-file or reading or writing from file before it is
                   opened e. CASE statement expression not matching case labels.
    Use of DEFENSIVE programming techniques can reduce the possibility of this
    kind of error.

      Defensive programming is anticipating potential trouble spots and guarding against them as we

                                                                                         6 Key Programming Issues p. 4
    illustrated above by validating input data using Relational tests
    in IF statements, for example:

       o    if ((Group        >=    low) and (Group            <= high)        )…..

   Another common problem is using UNINITIALIZED VARIABLES.
            double value;
            double sum;
            ifstream inFile;         // object for handling file input
  "data");          // associate inFile with a file
            if (!inFile.is_open())           // failed to open file
                     cout << "Could not open the file " << filename << endl;
                     cout << "Program terminating.\n";
            int count = 0;                   // number of items read
            inFile >> value;                 // get first value
            while (inFile.good())           // while input good and not at EOF
                 {     ++count;              // one more item read
                       sum += value;        //calculate running total
                       inFile >> value;            // get next value

           Problems with Switch Statement labels- failure to match a case label, or include a break

       int choice;

             cout << endl
                  << "Choose 1 to see the next homework assignment.\n"
                  << "Choose 2 for your grade on the last assignment.\n"
                  << "Choose 3 for assignment hints.\n"
                  << "Choose 4 to exit this program.\n"
                  << "Enter your choice and press Return: ";
             cin >> choice;

             switch (choice)

                                                                                6 Key Programming Issues p. 5
                   case 1:
               //code to display the next assignment on screen would go here.
                   case 2:
               //code to ask for a student number and give the corresponding
               //grade would go here.
                   case 3:
               //code to display a hint for the current assignment would go here
                   case 4:
                       cout << "End of Program.\n";
                         cout << "Not a valid choice.\n"
                            << "Choose again.\n";
           }while (choice != 4);

6c) Logic Errors;
Caused by incorrect translation of the problem or implementation of the algorithm. Most difficult to locate and

You may have to resort to tracing the execution of your program and the values of variables during
execution to locate the error. Two ways of tracing variables:

1. Use interactive debugger available with the compiler, setting WATCHES & BREAK POINTS at
    various locations within your program.

                                                                                     6 Key Programming Issues p. 6
2. Use Global flags to control the printing of output tracing statements, program DEBUGEX;

 const     bool DEBUG = TRUE;

 void exchange( int &PI,int &P2 )
    if (DEBUG) then
        cout << "lnto Exchange with Pl="<< PI<<"                              p2= "<< P2<<endl;
    // procedure code

     if (DEBUG) then
         cout << "lnto Exchange with Pl="<< PI<<"                             p2= "<< P2<<endl;
   } // end exchange


1. Develop and Test your program on a Modular basis using Program Stubs to simulate the procedures not yet
    implemented.(See example program FuncStubsEX.cpp )

2. Always ECHO print the input data, so you know what you are working with.

3. Use DEBUG tracing statements, or the Interactive Debugger to trace variables.

4. If your program is executing but not giving the expected output some places to look might be:

    A. Parameter list, defining parameters inappropriately for the situation: VALUE vs. VAR

    B. Using un-initialized variable, gives inconsistent output, maybe works OK when you first run the program, but
        after first run output is wrong. Later on when we use pointer variables, the first time you run your program
        it might work OK, but the second time you execute the whole computer LOCKS UP. This is a Red Flag to
        me that you are using an un-initialized pointer.

    C. Check BEGIN/END blocks on IF/THEN/ELSE loops or WHILE loops, maybe not executing the instructions
         you intended.

                                                                                       6 Key Programming Issues p. 7

To top