Sie sind auf Seite 1von 9

Chapter Seven

7
Debugging and Defensive Programming

After this chapter you should

be able to distinguish between the different


types of errors and how to deal with them

understand what is meant with the term


debugging and how to apply it in Visual Studio

understand what is meant with defensive


programming and how to make provision for
user errors

Key concepts
Syntax errors, Run-time errors
& Logic errors
Debugging
Representative test data
Exceptions and Exception
handlers
Chapter 7 2 Debugging

Errors

Programmers are human and may make mistakes. We will discuss the categories of errors at
the hand of the example of Chapter 3, AverageAge:

Syntax errors occur when the programmer do not obey the rules of the language. For
example, he can omit a semicolon, add variables of different types, forget to enter the
appropriate parameters in a method, have mismatched curly braces or brackets, make a
spelling mistake with a variable name, object, class or method, etc.

This type of error is the easiest to detect since the compiler picks it up and presents an
error message. Change the Click() event handler of the Calculate average button as in
the screen print below. Run the program and look what happens.

Offending code

Error message

The offending code is underlined with a blue wavy line. You can also view the error
message by pausing the mouse over the wavy underline. Read the message carefully – it
speaks for itself: The Text property of a text box contains data of type string. You cannot
assign string data to a variable that has been declared as int.

Run-time errors are not picked up in design mode and the program compiles perfectly.
During run-time, however, the program might crash. If, for example, the user types an
invalid number in the txtAge1 text box of the example above (after you corrected the
syntax error), he will get a run-time error with a message as in the example below:
Chapter 7 3 Debugging

Of course, a good programmer should make provision for this kind of error as users are
also human and would be very annoyed if a program does not inform them of the error
politely and allow them to correct it. We will return to this later. For now, just press Shift-
F5 to exit the program and run it again.

Logic errors are the most difficult to pick up. The program compiles, it does not give any
run-time errors but the output is wrong. Sometimes you will realise it, but it may also
happen that you do not pick it up since the computations are too complex to check
manually. See if you can pick up the error in the following code. What is the easiest way
to correct it?

int iAge1 = int.Parse(txtAge1.Text);


int iAge2 = int.Parse(txtAge2.Text);
double dAverageAge = iAge1 + iAge2 / 2.0;
MessageBox.Show("The average age is " + dAverageAge.ToString());

It is extremely important to test a program with representative test data that is simple
enough to check. If your program gives the correct output for a variety of input data,
chances are good that it will also provide the correct output for complex data.

"In our profession, precision and perfection are not a dispensable luxury,
but a simple necessity." (Niklaus Wirth)
Chapter 7 4 Debugging

Debugging
Debugging refers to the process of finding and correcting all logical errors in a program.

Something to forget

Rear Admiral Grace Murray Hopper (1906 – 1992) was an


American computer scientist and United States Naval officer. A
pioneer in the field, she was one of the first programmers of the
Harvard Mark I computer, and she developed the first compiler for a
computer programming language (COBOL).

While she was working on a Mark II Computer at Harvard University


(somewhere in the 1940's), her associates discovered a moth stuck
in a relay and thereby impeding operation, whereupon she
remarked that they were "debugging" the system. However, the
term "bug" in the meaning of technical error dates back at least to
1878 and Thomas Edison. Debugging seems to have been used as
a term in aeronautics before entering the world of computers. Indeed, Grace Hopper
acknowledged herself that she was not coining the term. The moth fit the already existing
terminology, so she saved it.
(Source: Wikipedia)

Something to do

Click on Debug / Windows/ Locals to display the Locals window at the bottom of the screen.
Note that this window is only available while the program is running.
Click in the margin next to the line of code to create a breakpoint. You can also press F9
for the same effect.

Run the program normally. Program execution will stop at the breakpoint.

Hover the mouse over a variable name. A pop-up message will appear that will indicate
the value of the parameter at the moment.
Press F10 repeatedly to step through the program line by line. You can at any time press
F5 again to stop debugging and continue with program execution normally.

Inspect the changes in the values of the variables as you progress through the program.
Chapter 7 5 Debugging

Something to understand

Debugging allows you to follow the logic of a program step-by-step so that you can identify
the place where a program goes off the track.

Use representative test data that is simple enough that you will be able to identify errors in
the values when they occur.
The Locals window shows all variables in the current scope with their values.

You can also add one or more variables to one of four Watch windows. While the Locals
window shows all variables in the current scope, you can selectively inspect the values of
variables or expressions in the Watch windows.

Defensive programming
As mentioned above, a good programmer should make provision for invalid input by users.
Users should be informed politely about their mistakes and allowed the opportunity to correct
them. Run-time errors are unforgiveable. If they occur, users cannot blame the computer and
programmers cannot blame users for being "stupid". Programmers should anticipate any kind
of error and make provision for it.

Something to do

Consider the following scenario: You want to calculate the fuel consumption of your car in
kilometre per litre as well as litre per 100 km. The distance travelled and the amount of
fuel will be available as inputs to the program.
Start with a new project, Fuel Consumption.
Design a form as in the example below.
Write the code for the Close button.

Enter the following code for the Consumption: km/l button:

private void btnKmPerLitre_Click(object sender, EventArgs e)


{
int iKm = int.Parse(txtDistance.Text);
double dLitre = double.Parse(txtFuel.Text);
double dConsumption = iKm / dLitre;
MessageBox.Show(dConsumption.ToString("0.0") + " km/l", "Fuel consumption");
}
Chapter 7 6 Debugging

Run the program with the following sets of test data:

Distance Fuel Expected output Actual output


(km) (l) (km/l) (km/l)
600 50 12 12.0
600 0 Message: Invalid input Run-time error
600 -50 Message: Invalid input -12.0
Note the
50 600 Message: Unrealistic input 0.1
difference
6oo 50 Message: Invalid input Run-time error
between 600
595.8 50 11.9 Run-time error
and 6oo
600 50.6 11.9 11.9

Things to understand

Five of the seven combinations provide output that is different from what is expected. It is
very important that a programmer tests a program with test data that is representative of
all possible scenarios, even if they seem to be highly unlikely.

Changing the code to the following would solve the first two of the five problems:

int iKm = int.Parse(txtDistance.Text);


double dLitre = double.Parse(txtFuel.Text);

if (dLitre > 0)
{
double dConsumption = iKm / dLitre;
MessageBox.Show(dConsumption.ToString("0.0") + " km/l",
"Fuel consumption");
}
else
MessageBox.Show("Invalid input.", "Fuel consumption",
MessageBoxButtons.OK, MessageBoxIcon.Error);

Changing the if statement to the following would cater for the third problem:

if ((dLitre > 0) && (iKm > dLitre))

This leaves us with the problem of invalid numeric input.

Something to do

Change the Click() event handler of the Consumption: km/l button as follows:

“For a long time it puzzled me how something so expensive, so leading


edge, could be so useless. And then it occurred to me that a computer
is a stupid machine with the ability to do incredibly smart things, while
computer programmers are smart people with the ability to do
incredibly stupid things. They are, in short, a perfect match.”
(Bill Bryson)
Chapter 7 7 Debugging

try
{
int iKm = int.Parse(txtDistance.Text);
double dLitre = double.Parse(txtFuel.Text);

if ((dLitre > 0) && (iKm > dLitre))


{
double dConsumption = iKm / dLitre;
MessageBox.Show(dConsumption.ToString("0.0") + " km/l",
"Fuel consumption",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
MessageBox.Show("Invalid input.", "Fuel consumption",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch
{
MessageBox.Show("Invalid input.", "Fuel consumption",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}

Run the program with the same sets of test data as above. Make sure that you get the
expected output for all combinations.

Things to understand

An exception occurs because of invalid user actions or circumstances during run-time. An


exception handler is a block of code that is executed when an exception occurs.

Some exceptions can be handled by a normal if statement.

The try … catch structure will catch occurrences where input values cannot be parsed into
the expected numeric data type.

- The program attempts to execute the code in the try block. If it succeeds, the code in
the catch block is skipped. If it encounters a problem, execution is immediately
transferred to the catch block.
- Put a breakpoint on the first line inside the try block. Then run the program and enter
invalid data for the distance that was travelled. Watch how all subsequent code in the
try block is skipped.
- Make sure that you don't have any code in the catch block that could cause an error.
- The braces are not optional if there is only one statement as was the case for if or
else.

Understand the MessageBox.Show() method

The MessageBox.Show() method has 21 overloaded versions. The version that we used
here takes four parameters. The first two parameters are the standard ones for the
prompt and caption.
Chapter 7 8 Debugging

The third parameter allows the programmer to decide which buttons must be displayed. If
it is omitted, only the OK button is displayed by default. Thanks to IntelliSense, we don't
have to remember the exact naming of the class or the buttons.
- Type 'M' and select MessageBoxButtons from the dropdown list.

- Type period ('.') and select OK from the dropdown list.

The fourth parameter allows the programmer to select an icon to be displayed in the
message box. If it is omitted, no icon is displayed.
- Type 'M' again and select MessageBoxIcon from the dropdown list.

- Type period ('.') and select Information from the dropdown list.

Something to do

Change the catch block as follows and run the program with invalid data.

catch (Exception exception)


{
MessageBox.Show(exception.Message, "Fuel consumption",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}

Things to understand

The catch statement can take an optional parameter that should be an object of an
exception class. There are several exception classes available, e.g. Exception,
FormatException, DivideByZeroException, ArithmeticException.

- The generic exception class is Exception which does not always provide specific
information about the exception that occurred.

- See also http://msdn.microsoft.com/en-us/library/aa664610(VS.71).aspx

The exception object has a property Message, that contains a system generated message
about the error that occurred. You can decide to display this message with or instead of
your own.

The try … catch structure has another block, finally, which is optional and will become
of value when we start to work with files.
Chapter 7 9 Debugging

Keywords
You should make sure that you know what each of these items mean or where they are used.

ArithmeticException Exception Run-time error


Breakpoints Exception Syntax error
catch Exception handler Test
Debugging finally Test data
Defensive programming FormatException try
DivideByZeroException Locals window Watch windows
Error Logic error
Error message Message

Key:

Concepts : Normal
Classes and Controls : Green, e.g. Color
Properties : Bold, e.g. Message
Reserved words : Blue, e.g. new

Exercises
Do the following exercises again while making provision for all types of errors. Under no
circumstances should a user be able to break your program.

You can in many cases replace text boxes with NumericUpDown controls. This will force the
user to enter numeric values in a specified range. It has a Value property that returns a
decimal value that can be cast to double or int or whatever is applicable for the application.

Chapter 3, Number 1 (Use NumericUpDown)


Chapter 3, Number 2
Chapter 3, Number 3
Chapter 3, Number 4 (Make also sure that the user cannot enter a negative exchange rate or dollar
value)
Chapter 3, Number 6 (Use NumericUpDown. Make provision for any realistic Fahrenheit temperature.
Allow one decimal digit.)
Chapter 3, Number 7 (Make sure that the amount and periods are larger than 0. The rate must be
between 0 and 100 inclusive)
Chapter 3, Number 8 (The radius may not be less than 0)
Chapter 3, Number 9
Chapter 4, Number 3
Chapter 4, Number 4 (Radius and length must be larger than 0)
Chapter 4, Number 5 (Prices must be larger than 0. Amount offered must be larger or equal than
total owed.)
Chapter 4, Number 6 (Sales must not be less than 0.)
Chapter 4, Number 7 (It is not possible to obtain the square root of a negative number.)
Chapter 4, Number 8
Chapter 5, Number 1 (All marks must be larger or equal than 0 and less or equal than 100.)
Chapter 6, Number 2 (Use NumericUpDown)
Chapter 6, Number 7
Chapter 6, Number 8 (Sides must be larger than 0)
Chapter 6, Number 9
Chapter 6, Number 11
Chapter 6, Number 12
Chapter 6, Number 13 (Salry must be larger than 0)

Das könnte Ihnen auch gefallen