CSE 283 Introduction to Object Oriented Design

Barbara Nostrand, Ph.D.


CSE 283 Labs
Welcome to the site for CSE 283 Labs!

 

Lab 5: Controlling Method Behavior

Prev | Next | Lab 5

 

Introduction

Today's lab explores some Java statements that we can use to write more sophisticated methods. The exercise consists of two parts: In the first part, we examine a problem whose solution requires more complicated behaviors than we have seen thus far, and introduce the new statements to elicit that behavior. In the second part, we introduce a new program-development tool called the debugger and use it to study the behavior of the new statements.

 

Part I: The Tax Computation Problem

Our problem today is to write an interactive tax computation program, that the owner of small online business might use to compute the total cost of items being sold to buyers in states with different sales tax. To make the problem more interesting, we will assume that a national luxury tax has been enacted. The one percent luxury tax will be levied against any purchase over one hundred dollars.

Recall that object-centered design involves several stages:

  1. Identify the behavior we wish the program to exhibit in order to solve the problem.
  2. Identify the objects in that behavior.
  3. Identify the operations in that behavior.
  4. Organize the operations and objects into an algorithm.

Now that we know about methods and modules, we must incorporate them into our design scheme. Methods can be thought of as the means of creating our own operations, so the natural place to incorporate them is in step 3:

  1. Identify the behavior we wish the program to exhibit in order to solve the problem.
  2. Identify the objects in that behavior.
  3. Identify the operations in that behavior.
    If there is no predefined way to perform an operation,
      build a method to perform it.
    If a method is reusable, store it in a module.
  4. Organize the operations and objects into an algorithm.

Once we have our design, we can encode it in a programming language, test and debug the resulting program, and then perform any maintenance required over its lifetime.

Today's exercise is to use these stages to develop a program that solves our problem.

Preparing Your Workspace

Begin by creating a project for this exercise (e.g., TaxTotals) in which to store today's work and then save copies of the files TaxTotals.java, Tax.java, and Tax.doc in your project directory. Then open TaxTotals.java, add it to the project, and take a moment to personalize its opening documentation.

 

Design

As always, spending a bit of time planning how to attack our problem will result in a better solution. To do so, we follow the steps of object-centered design.

Behavior. We can begin by visualizing and writing down how we want our program to behave. One approach is to have our program behave something like the following:

   This program computes total costs interactively.

   To begin, enter the number of items: 3

   Enter the item name, cost and tax rate for item 1: kleenex 25 5.25
   kleenex     26.3125

   Enter the item name, cost and tax rate for item 2: eggs 1.50 6.15
   eggs         1.59225

   Enter the item name, cost and tax rate for item 3: tires 350 6.15
   tires      374.375

Put into words, our program should

   display on the screen a greeting, followed by a prompt for the 
   number of items, which it should then read from the keyboard.  
   For each item, our program should then display a prompt for 
   the item name, cost and tax rate.  The program should then
   read these values from the keyboard, and compute and display
   the total item cost, along with the name.

Objects. If we identify the nouns in this behavioral description, we get the following list:

Description

Type

Kind

Name

The screen

Screen

varying

theScreen

A greeting

String

constant

--

A prompt for input

String

constant

--

The number of items

int

varying

numberOfItems

The keyboard

Keyboard

varying

theKeyboard

An item's name

String

varying

name

An item's cost

double

varying

cost

An item's tax rate

double

varying

rate

An item's pay

double

varying

totalCost

From this list, we can build a precise specification of how our program is to behave:

   Input:	The number of items;
		    Each item's name, cost, and tax rate.
   Output:    Each item's name and total cost.

Use this information to complete the specification of TaxTotals.java.

Operations. If we identify the operations in our behavioral description, we get this list:

Description

Predefined?

Name

Library?

display a String (greeting, prompts, labels)

yes

print

ann.easyio

Read an int (numberOfItems) from the keyboard

yes

readInt

ann.easyio

read a string (name) from the keyboard

yes

readWord

ann.easyio

read a double (cost, rate) from the keyboard

yes

readDouble

ann.easyio

compute an item's totalCost, given the cost and rate from the keyboard

no

??

??

display a double (totalCost) on the screen

yes

print

ann.easyio

repeat operations 3-6 once for each item

yes

for

--

As indicated, most of these operations are provided for us by the ann.easyio package. Operations 1-4 and 6 should be familiar by now. There is no predefined Java capability to perform operation 5, and since accounting for luxury tax makes it nontrivial, we will write a method to perform this operation. Since it seems like an operation that might be useful again some day, we will store it in a module. Finally, operation 7 involves a new Java statement that we haven't seen before called the for statement, which provides a convenient way to repeat a group of statements a predetermined number of times.

Algorithm. Even without knowing the details of how we will compute the total cost, we can organize our operations into an algorithm for our problem:

  1. Via theScreen, display a greeting on the screen, plus a prompt for the number of items.
  2. From theKeyboard, read an integer, storing it in numberOfItemses.
  3. For each value itemNum in the range 1 to numberOfItems:
    1. Via theScreen, display a prompt for the name, cost and tax rate of item itemNum.
    2. From theKeyboard, read a String, a double and a double, storing them in name, cost and rate.
    3. Compute totalCost, using cost and rate.
    4. Via theScreen, display name and totalCost.

    End loop.

Coding, Testing and Debugging

Once we have designed an algorithm to solve our problem, we must encode that algorithm in the a high level programming language (i.e., Java). We can begin this process by constructing a minimal Java program, consisting of

  public class TaxTotals 
  {

	public static void main(String args[]) 
     {

	}

  }

(These lines are already present in TaxTotals.java, after its opening documentation.) To make sure that this much is correct before we add to it, take a moment to compile TaxTotals.java.

Given the minimal Java program, we are ready to encode our algorithm using stepwise translation. We therefore begin with the first step:

1. Via theScreen, display a greeting on the screen,
  plus a prompt for the number of items.

Coding: This step can be performed using a Java output statement, which we have seen before:

   theScreen.print( Value1 + Value2 + ... + ValueN );

so add an output statement to TaxTotals.java that displays the following message:

   This program computes total costs interactively.

   To begin, enter the number of items:

Don't forget to import the package ann.easyio.*!

Before proceeding to the next step, check the correctness of what you just wrote by recompiling your program. The compiler will alert you to any syntax errors in your statement. If an error is listed, you can infer that the error(s) lies in the text you just added, since the program was error-free before that. Find your error(s) within those lines and correct them.

When your source program compiles correctly, execute TaxTotals to test that it displays the intended message. If not, the statements you have added contain logic errors. (i.e., the statements you have added are syntactically correct, but they don't accomplish their task correctly.) Compare your program's statements against the output produced by TaxTotals and modify them as needed. When your program is error-free, proceed to the next step of our algorithm.

2. From theKeyboard, read an integer, storing it in numberOfItems.

Coding: We can encode this step in Java using an input statement:

   Var1 = theKeyboard.readInt();

Add an input statement to your source program to perform step 1. Don't forget to declare a variable to store numberOfItems! Check that what you have added is free of syntax errors before continuing.

Note that we could use an Assertion.check() at this point to check that numberOfItems is nonnegative. However, doing so is unnecessary, thanks to our next step.

3. For each value itemNum in the range 1 to numberOfItems:
  a. Via theScreen, display a prompt for the name, cost and tax rate
      of item itemNum.
  b. From theKeyboard, read a String, a double and a double,
      storing them in name, cost and rate.
  c. Handle Preconditions and Error Checking.
  d. Compute totalCost, using cost and rate.
  e. Via theScreen, display name and totalCost.
End loop.

Coding: Let's take this step a piece at a time, starting with the outer part (3) and then doing the inner parts (a-d).

 

3. For each value itemNum in the range 1 to numberOfItems:
  ...
End loop.

The purpose of step 3 is to count from 1 to the number of items, and repeat steps a-d that many times. That is, if there are three items, then steps a-d should be repeated three times.

For situations like this that require repetitive behavior, Java supplies the for statement. The for statement can use its own local variable, called a loop-control variable, to do the counting. A simplified general form of a for statement that counts from firstValue to lastValue is:

   for (Type loopVar = firstValue; loopVar <= lastValue; loopVar++)
   {
      Statements
   }

where loopVar is the loop-control variable, and the Statements between the curley braces are called the body of the loop. The behavior of this statement is as follows:

  1. loopVar is declared and initialized to firstValue.
  2. loopVar is compared against lastValue.
  3. If the comparison evaluates to true:
    1. Statements get executed.
    2. loopVar++ is executed.
    3. Go to 2.

    Otherwise, control proceeds to the next statement.

In our problem, we must count from 1 to the value stored in numberOfEmployees, using empNum as the name of the loop-control variable. To do so, we can write:

   for (int itemNum = 1; itemNum <= numberOfItems; itemNum++)
   {
   }

leaving its Statements empty for the moment.

Note that if the user enters a negative value for numberOfItems, the body of the loop will not be executed, because the loop's body is only executed if the condition controlling the loop evaluates to true, and a negative value for numberOfItems will make this condition false.

Add this to TaxTotals.java and then check its syntax. When the compiler generates no errors, proceed to steps 3a-3d.

3a. Via theScreen, display a prompt for the name, cost and tax rate
  of item itemNum.
This is a normal output statement, like those we have seen before, except that in addition to displaying a string, it displays the value of our loop-control variable to generate an "item number." That is, if numberOfItemss is 3, then our loop will execute three times, so add an output statement to the body of the loop that will generate the following:

   Enter the name, cost and tax rate for item 1:
   Enter the name, cost and tax rate for item 2:
   Enter the name, cost and tax rate for item 3:

Then check the syntax of what you have written using the compiler. When your program translates correctly, run it and enter 3 for the number of items, to verify that what you have written is free of logic errors.

3b. From theKeyboard, read a String, a double and a double,
  storing them in name, cost and rate.

This step can be encoded by adding a normal input statement to the body of the loop, after the output statement, so take a moment to do so.

However, before such a statement will compile correctly, the objects name, cost and rate must be declared. This raises an interesting question: Where should these objects be declared?

If we declare name, cost and rate within the body of the loop, then they will be redeclared anew each execution of the body, wasting time. For the sake of efficiency, they should instead be declared immediately before the for statement. That way, they will still be declared near their first use, but time will not be wasted reprocessing their declarations every time the loop body executes.

Add the necessary statements to your program to (i) declare name, cost and rate(outside the loop), and (ii) fill these objects with values entered from the keyboard (inside the loop).

Then check your code's syntax using the compiler, and continue when it is correct.

3c. Preconditions and Error Checking

Anytime we program an input operation, we should consider the possibility of human error: what could the user do to foul up our program? There are several possibilities here:

  1. The user could enter a negative value for cost.
  2. The user could enter a negative value for rate.

The user could also enter a value for rate greater than the maximum tax rate; however our problem does not specify a maximum tax rate, so we will ignore that potential source of error for the moment.

Since either of these errors will cause our program to generate incorrect pay amounts, our code should safeguard against them. To do so, add an Assertion.check() to the program that only allows the program to continue if cost is nonnegative and rate is nonnegative. Use a single Assertion.check() call to do so.  Since Assertion.check() can throw an AssertionException,  you will need to include this class as well. 

Then check the syntax of what you have written using the compiler, then run your program and test that your Assertion.check () halts the program if either of these two errors occur. When it correctly "catches" these errors, continue.

3d. Compute totalCost, using cost and rate.

This operation is not predefined, and so we will design and build a method to perform it.

Method Analysis. To compute totalCost for an arbitrary item, our method needs the cost and rate. Since these values will differ from item to item, our method should receive these values from its caller.

Method Behavior. Our method should receive the cost and rate from its caller. If cost is less than or equal to the minimum cost for the luxury tax, then our method should compute the total cost as cost plus cost times rate divided by 100 (assume that the rate is given as a percent). Otherwise, it should compute the regular cost as before; the luxury surcharge as one percent of the luxury base (cost minus the minimum for the luxury tax); and then compute the total cost as the sum of the regular cost and the luxury surcharge.

Method Objects. Ignoring nouns like "our method" and "caller", we can identify the following objects in this description:

Description

Type

Kind

Movement

Name

item cost

double

varying

received

cost

tax rate (percent)

double

varying

received

rate

minimum luxury cost

double

constant

local

MIN_LUXURY

total cost

double

varying

returned

totalCost

regualr cost

double

varying

local

regularCost

luxury surcharge

double

varying

local

luxurySurcharge

luxury base

double

varying

local

cost - MIN_LUXURY

luxury tax rate

double

constant

local

LUXURY_RATE

For each received object, we must provide a parameter to store that value. We can thus specify the behavior of our method as follows:

   Receive: cost and rate, both doubles.
   Precondition: 0 <= cost and 0 <= rate.
   Return: the total cost, a double.

These observations allow us to create the following stub for our method:

   public static double computeTotalCost(double cost, double rate)
   {
   }

Each object that is neither received nor returned must be defined as a local object, within the body of our method. For example, MIN_LUXURY will be a local constant double object, defined to have the value 100.0; while regularCost will be a local variable double object.

Since this seems like a method that might be reusable some day, we will store its definition in a module named Tax. Open Tax.java, add it to the project. Create the class Tax and inside that class insert the stub. Since other programs besides TaxTotals.java may be calling this method (and not checking the precondition ahead of time), make the first line in the method an Assertion.check() call that checks the method's precondition. (Copy-and-paste your Assertion.check() from TaxTotals.java.)

Then copy the prototype into Tax.doc. and add the documentation.

Method Operations. From our behavioral description, we have these operations:

Description

Defined?

Name

Module?

1

receive cost and rate from caller

yes

method call
mechanism

built-in

2

compare cost and MIN_LUXURY
in less-than-or-equal relationship

yes

<=

built-in

3

compute totalCost normally
(cost plus cost times rate divided by 100)

yes

*

built-in

4

compute totalCost for luxury item

4a

compute regualarCost

yes

*

built-in

4b

compute luxuryBase
(cost minus MIN_LUXURY)

yes

-

built-in

4c

compute luxurySurcharge
(luxuryBase times LUXURY_RATE divided by 100)

yes

*, /

builtin

4d

compute totalCost
(regularCost plus luxurySurcharge)

yes

+

built-in

5

if (2) is true, perform (3), otherwise perform (4)

yes

if

built-in

6

return totalCost

yes

return

built-in

We have seen each of these operations before, except for operation (5), which introduces a new behavior in which we must select one group of statements or another, but not both. As we shall see shortly, the Java if statement provides this behavior.

Method Algorithm. We can organize our objects and operations as follows:

  1. Receive cost and rate from the caller.
  2. If cost <= MIN_LUXURY
      Compute totalCost = cost + cost * rate/100.
    Otherwise
      a. Compute regularCost = cost + cost * rate/100..
      b. Compute luxuryBase = (cost - MIN_LUXURY).
      c. Compute luxurySurcharge = luxuryBase * LUXURY_RATE/100.
      d. Compute toalCost = regularCost + luxurySurcharge.
  3. Return totalCost.

Given an algorithm, we are ready to encode our method.

Method Coding. To encode this algorithm in our computeTotalCost() stub, we must know the syntax of the Java if statement. The general pattern is as follows:

   if (BooleanExpression)
   {
      Statements1
   }
   else
   {
      Statements2
   }

Here BooleanExpression is any expression that evaluates to true or false, and Statements1 and Statements2 are 1 or more Java statements. Statements1 is sometimes called the true section of the if, and Statements2 is called its false section. The reason for these names is that when execution reaches an if statement, its BooleanExpression is evaluated. If it is true, then the statements in Statements1 run, and those in Statements2 are skipped. Otherwise, the opposite occurs -- the statements in Statements1 are skipped, and those in Statements2 run.

For our problem, we want BooleanExpression to perform the comparison described in operation (2). In the stub for computeTotalCost(), we can add the following if statement that compares cost and MIN_LUXURY using the less-than-or-equal relationship:

   if (cost <= MIN_LUXURY)
   {
   }
   else
   {
   }

As a parameter, object cost is defined for us, but MIN_LUXURY is not a parameter, and so must be declared. Add a statement at the beginning of the method that declares MIN_LUXURY as a constant whose value is 100.

To check this much, compile Tax.java, and you should just get the one error for not providing any return value. Continue if this is the case, otherwise fix the other errors.

Coding operations (3) and (4) is straightforward, so add statements to the if's true section to perform (3), and add statements to its false section to perform (4). Note that each section of the if computes totalCost, however the true section uses the formula appropriate for no luxury tax, while the false section uses the formula appropriate when there is luxury tax. Since each section uses totalCost, it must be declared prior to both sections (i.e., before the if statement).

Finish the method by adding a return statement that returns the value of totalPay. Then recheck the correctness of computeTotalCost(), continuing when it is free of syntax errors.

Now that we have a syntactically correct computeTotalCost() method to perform step 3c of our program's algorithm, we are ready to code that step by calling our method. In the for loop within TaxTotals.java, add an assignment statement with a call to computeTotalCost(). Don't forget to pass it cost and rate as arguments!

To check the correctness of our call, compile TaxTotals.java which will create TaxTotals.class and link it with the class file of Tax.java. When what you have written is free of syntax errors, continue to the final step of our algorithm.

3e. Via theScreen, display name and totalCost.

This step is easily implemented using an output statement. Take a few moments and add an output statement so that if item milk had a total cost of $1.75, the following is displayed:

   milk cost with tax is $1.75

Use whatever symbol is appropriate for your country's currency.

 

Testing

When you are finished, recompile the program. Then test it a few times using sample data, to check that it computes correct results.

 

Maintenance

Recall that program maintenance is the final stage of program development, in which modifications and improvements are added during its lifetime. Some studies have shown that the cost to write a program is only 20% of its total cost -- the rest is consumed by maintenance! One of the goals of object-oriented programming is to reduce this maintenance cost, by writing code that is reusable.

To simulate program maintenance, we can improve TaxTotals by modifying it so that it displays totalCost in monetary format (i.e., with 2 decimal digits instead of the default number). The number of decimal digits in a real number is called the precision of that number. To show only two decimal digits, we must alter the default precision. As we have seen before, this can be done with an method in the ann.easyio package

   printFormatted(DoubleExpression, IntegerExpression ) 

Modify your source program so that pay is displayed with precision 2. Then test the correctness of your modification.

 

Part II: Using the Debugger

While the compiler will inform us of any syntax errors our program contains, it cannot detect logic errors. The simplest way to check for logic errors is to examine the values of the variables in our program as the program executes, and verify that they are what they are supposed to be. Most environments provide a special tool called a debugger. A debugger allows you to execute a program statement-by-statement, and examine the values of variables (or expressions) as the program runs.

 

There are certain common features that most debuggers have.

Breakpoints

When there is a problem with a program, you often have some idea of where the problem lies. You want to run our program until you get to a point close to the suspected trouble spot. By setting a breakpoint, you inform the debugger that it should stop executing the program at a certain point.

Examining Object values

Once you have temporarily halted the execution of our program, you would like to be able to examine the values that are stored in all of your variables and check to see if they match what you expect them to be.

Single Step

Suppose that you haven't found the bug in your program. You would like to be able to execute lines of code one at a time until you find the problem.

Step Into, Over, Out

Because modern methods are composed of many methods, you want to have the ability to decide whether or not to explore a method. If you trust a method, you will want to step over the method call. If you are not sure of a method, you will want to step into the method. Finally, if you are in a method and believe it to be okay, you can step out of the method and return to where it was called from.

   

The simplest way to check for logic errors is to examine the values of the variables in our program as the program executes, and verify that they are what they are supposed to be. emacs and xemacs provide a simple way to check variable values, using a tool named jdb (which stands for Java debugger).

Jdb allows you to run another program statement-by-statement, and examine the values of variables (or expressions) as the program runs.

 

Starting JDB

In the Linux Lab

In the following documentation C- stands for typing the character after the dash while holding down the CTL key, and M- stands for typing the character after the dash while holding down the ALT key. C stands for control while M stands for meta.

First compile all of the components in an ultraminos window. Then, in a linux command window, type:

xemacs TaxTotals.java

Once your source code opens up, type C-x 2 to open a second buffer window in xemacs. You should now have two copies of your program. You can switch between windows by clicking on the window you wish to activate. Use one of the two windows as your source-code bufer and the other as your debug buffer. In our version of x-emacs, the jdb debugger is immediately available from the command bar at the top of each window displaying java source code.

To activate jdb in your non-source-code buffer, click on the jde option in the command bar of your debug buffer and select the appropriate mode. Available modes include:

    run application run applet debug application debug applet
Which mode you use is determined by whether you have written and application or applet and whether you wish to run it with debug features enabled or disabled. In general, the jdb commands described below are available in the linux laboratory.

Outside the Linux Lab

To use jdb, make sure that your xemacs window has two buffers showing, one of which should contain your source program TaxTotals.java. (If you only have one buffer showing, use the xemacs C-x 2 command to split your buffer in two.)

To run jdb in the non-source-code buffer, click in that buffer and type the editor command M-x gdb. In the mini-buffer at the bottom of the window, xemacs will ask

   Debug command: gdb

Since we want to debug Payroll using jdb change it to:

   Debug command: jdb TaxTotals

and hit Return. Xemacs will then replace your non-source-code buffer with one named *jdb-TaxTotals* in which you can enter debugging commands. You can move the cursor back and forth between the two buffers using the keyboard C-x o command, or by clicking the mouse. The final line of the *jdb-TaxTotals* is the jdb prompt:

   (jdb)

jdb uses a command-line environment, in which you interact through entering commands.

 

Running a Program from within JDB

To run your program, you can enter the jdb run command:

   (jdb) run

Your program will then execute from start to finish within jdb. This is not what we want -- we'd rather be able to execute our program one line at a time so that we can inspect the values of variables used on that line.

 

Setting a Breakpoint

To accomplish this, we must set a break point, which is sort of like placing a "stop sign" at a statement so that execution will halt when it reaches that point. Position the cursor in TaxTotals.java on the line containing the output statement for step 1 of our algorithm. Then enter the editor command C-x SPC (where SPC is the spacebar). A message like the following should appear in the *jdd-TaxTotals* buffer:

   Breakpoint 1 at 0x22a: file TaxTotals.java line 16

Now that we have a "stop sign" in place, we can run TaxTotals in a controlled manner, so enter the jdb run command again.

After an introductory message, jdb will tell you that it is stopping at breakpoint 1, and then re-display its prompt. If you look in the TaxTotals.java buffer, you will notice that the line where we set the breakpoint is highlighted, with an "arrow" (=>) to its left. Under xemacs and jdb this "arrow" will always point to the statement that is to be executed next.

 

Executing a Program Statement-by-Statement

Now, we can use jdb commands to execute each statement in turn. For example, enter the jdb next command:

   (jdb) next

and you should see the "arrow" advance to the next executable statement. Since the statement we just executed was an output statement, jdb performs that statement, and then redisplays the jdb prompt:

   This program computes total costs interactively.

   To begin, enter the number of items: (jdb)

The presence of the jdb prompt tells us that jdb is ready for another command, not the number of items. If you enter the jdb next command again, the next statement is an input statement which causes jdb to suspend, waiting for you to type a value. Note that the jdb prompt does NOT appear, because it is waiting for you to enter the number of items, not a jdb command. Enter 3, after which the prompt should reappear, indicating that jdb is ready for another command.

   This program computes total costs interactively.

   To begin, enter the number of items: (jdb) 
   3
   (jdb)

 

Displaying an Object's Value

Whenever the jdb prompt is displayed, you can examine the value of an object (provided the definition of that object has been executed). For example, we can check the value of numberOfItems by by entering the jdb print command:

   (jdb) print numberOfItems

If you entered 3 as the number of items, jdb will respond by displaying:

   $1 = 3

where the 3 indicates the value being printed. (Ignore the $1 for now.)

The jdb print command thus allows us to inspect the value of a variable. Used in conjunction with the jdb next command, we can execute a statement and then see how that statement affected the value of a variable. You can thus use the debugger to display the current value of a variable or expression at any point in your program (following its declaration).

Using the jdb next command, continue executing the program one line at a time, entering an item, and its cost and tax rate following the execution of each input statement within the for loop. What happens when you enter the jdb next command at the end of the loop?

Continue using the jdb next command to run the program, watching the movement of the "arrow" as it runs. This should help you understand the behavior of the Java for loop.

 

Stepping Into a Method

Using the jdb run command, re-run your program. Execution will again stop at your breakpoint. Using the jdb next command, execute your program a line at a time, and enter some value which is below the minimum luxury tax value for the cost and a value for rate. Then continue using the jdb next command until the "arrow" is pointing at the line containing the call to method computeTotalCost().

This time, use the jdb step commmand:

   (jdb) step

You should see execution move through the method call:

   (jdb) step
   computeTotalCost (cost=21, rate=7.65) at Tax.java:12

and then stop at the first line within the method. Where the jdb next command executes the next statement (including any method calls it contains), the jdb step command steps into any method calls

Use Ctrl-x SPC again to set a second breakpoint here in the method. Then continue using the jdb next command, paying particular attention to the flow of control as execution moves through the method's if statement. Note how the code that computes total cost is performed, while the code that computes luxury tax is skipped.

Continue using the jdb next command until the method terminates, noting how execution transfers back to the main function in TaxTotals.java.

 

Continuing to the Next Breakpoint

With execution back in the main function, type the jdb continue command:

   (jdb) cont

This causes jdb to continue execution from the current line until it reaches the next breakpoint, or the end of the program.

When jdb pauses for you to enter input values, enter a value greater than the minimum luxury tax value for cost and a value for rate. Jdb will then continue execution until your second breakpoint (within method computeTotalCost()) is reached.

Using the jdb next command, trace the flow of execution through the if statement again, noting that this time, the "normal" tax computation is skipped, but the luxury tax computation is performed. This should provide a clear illustration of selective behavior.

Use the jdb print command to display the values of regularCost, luxurySurcharge, and totalCost. Note that while totalCost can be displayed anywhere in the method, regularCost and luxurySurcharge can only be displayed when execution is within block of code in which they are defined.

 

Quitting JDB

Whenever you want, you can quit jdb by entering its quit command:

   (jdb) quit

The debugger will display a termination message and then quit. If you want, move the cursor back into the TaxTotals.java buffer and use C-x 1 to make xemacs display a single buffer.

 

Summary

The key points to remember are

  • To invoke jdb, use the editor command M-x gdb.
  • To set a breakpoint, position the cursor in your source code window at the line where you wish execution to stop; then type the editor command M-x SPC.
  • You can run a program using the jdb run command.
  • You can continue execution using the jdb cont command.
  • You can execute the next statement using the jdb next command.
  • You can step into a method call in the next statement using the jdb step command.
  • You can print the value of an expression using the jdb print command).
  • You can quit using the jdb quit command.

From this exercise, you should now know the basics of using jdb, as well as have a better understanding of how if statements and for loops work.

 

Phrases you should now understand:

Object-Centered Design, Algorithm, Coding, Testing, Debugging, Stepwise Translation, Selective Execution, If Statement, Repetitive Execution, For Statement.

 

Prev | Next | Lab 5

 
  Home

Schedule

Help

Lab 0

Lab 1

Lab 2

Lab 3

Lab 4

Lab 5

Lab 6

Lab 7-8

Lab 9

Lab 10

Lab 11

Lab 12

Lab 13






Last modified: 2007 OCT 30
bnostran@syr.edu