8: Designing with Methods and Midterm Q&A

What We Will Cover


Continuations

Homework Questions?

8.1: Designing With Methods

Objectives

At the end of the lesson the student will be able to:

  • Use top down design to create algorithms
  • Write methods following the black-box analogy

8.1.1: Top Down Design

  • Recall that programming is about solving problems using a computer program
  • The first phase of writing a program is the problem solving phase
  • The output of the problem solving phase is an algorithm
  • A good approach for designing algorithms is to break down the task to be accomplished into a few subtasks
  • Then you break down each subtask into smaller subtasks as needed
  • Eventually, the tasks are so trivial that they are easy to implement in Java
  • This technique is called top down design (also stepwise refinement or divide and conquer)

Using Methods in Top Down Design

  • Preserving your top down design in your Java code makes your programs:
    • Easier to understand
    • Easier to write, test and debug
    • Easier to change when needed
  • The way to preserve your top down design is to implement the structure in methods
  • One advantage of using methods to structure your code is that different people can work on different subtasks
  • When producing large programs, this sort of teamwork is important
  • Many people can work together to produce a program faster
  • However, this technique only works if the work is divided in a structured way
  • This design approach provides much of the structure needed to produce large programs

8.1.2: Designing Methods Using the Black Box Analogy

  • A key concept in designing methods is called the black-box analogy
  • A black box is something that we know how to use but not how it operates
  • An example might be a cell phone or an iPod
  • These devices have controls that we know how to operate
  • However, we really do not know how they work

Methods as Black Boxes

  • A method should be designed like a black box
  • The method has a job to do
    • For example: find the square root of a number
  • As a programmer using the method, you need to know what the method's job is so you can use it
  • However, you do not need to know how the method does its job
  • This is known as, "treating the method like a black box"
    • Calling something a black box is a figure of speech
    • It is intended to convey the image of a physical device that we know how to use but not how it operates
  • If a method is well designed, then a programmer can use it as if it were a black box
  • All a programmer needs to know is that if correct arguments are passed to the method then a correct value will come out of the black box
  • Thus, when we call the method Math.sqrt(9.0), we know we will get 3.0 back
  • System.out.println(Math.sqrt(9.0));
  • A programmer should not have to look at a method's code to know what will come back

Method Comment Blocks

8.1.3: Case Study

  • Let's apply top down design and the black box analogy to a case study
  • Adapted from: C++, An Introduction to Problem Solving and Programming, 5/e, Walter Savitch, Addison Wesley, ISBN 0-321-26865-2, pp.120-127

  • Often times the large "economy" size of a product is not always a better buy than the smaller size
  • This is often true when buying pizza
  • Pizza sizes are given in diameters
  • However, the amount of pizza you get is really the area of the pizza
    • Which is proportional to the square of the radius
  • The problem is: which size of pizza gives the lowest cost per square inch?
  • We need to write a program that gives us the price per area of any two pizza sizes

8.1.4: Problem Analysis

  • To better understand the problem we are solving, we ask some questions:
  • What output do we want?
    • A decision on which size is the best buy
    • Based on the cost per square inch for each size of pizza
  • What data do we have to work with?
    • Diameter of two sizes of pizza
    • Cost of the same two sizes of pizza
  • What formulas do we need?
    • area = πr2
    • cost per inch = price / area
  • What if the cost per square inch is the same?
    • The smaller size will be the better buy

8.1.5: Algorithm Design

  • We use top-down design to break down the overall task into steps or subtasks
  • Looking at the tasks, what do you notice?
    1. Subtask 1: Get the input data for each size of pizza
    2. Subtask 2: Compute the price per inch for smaller pizza
    3. Subtask 3: Compute the price per inch for larger pizza
    4. Subtask 4: Determine which size is the better buy
    5. Subtask 5: Output the results
  • Subtask 1 is straightforward
    • Just ask for the input values and store them in variables
  • Similarly subtasks 4 and 5 are easy
    • To determine the best buy in subtask 4, we just compare the cost/inch of the two pizzas using an if statement
    • Subtask 5 just prints the result
  • However, notice subtasks 2 and 3
  • Subtasks 2 and 3 are the same task with the only difference being the data used for the calculation
  • Both of these tasks take the same type of input and return the same type of result
  • Whenever you see a subtask take some values (like numbers) and return a single value, it is easy to make a method out of them
  • Whenever two or more subtasks make the same computation, you should make a method out of them
  • For our program, we make a method named calcUnitPrice()
  • /**
     * Calculates the price per square inch of a pizza
     *
     * @param diameter The diameter of the pizza in inches.
     * @param price The price of the pizza in dollars.
     * @return The price per square inch of a pizza.
     */
    double calcUnitPrice(int diameter, double price);
    
  • Notice that our method is designed so that it can be treated as a black box
  • A programmer knows what values can be sent to the method and what to expect back from the method without needing to see the method code

calcUnitPrice Algorithm Design

  • Now we design the algorithm for calcUnitPrice
  • The hard part of the algorithm is determining the area of the pizza
  • Once we know the area, then we compute the price per inch using the formula: price / area
  • Since a pizza is roughly a circle, we can use the area formula:
    • area = πr2
  • Thus, our algorithm for calcUnitPrice is:
    1. Compute the radius of the pizza
    2. Compute the area of the pizza using πr2
    3. Return the value of: (price / area)
  • To get more detail and precision, we convert the algorithm to pseudocode
  • Pseudocode is a mixture of Java and ordinary English (or any natural language)
  • With pseudocode, you can make your algorithms precise without worrying about the details of Java syntax
  • Our pseudocode is:
  • radius = diameter / 2;
    area = π * radius * radius
    return (price / area)
    
  • With the pseudocode defined, translation to Java is easy

8.1.6: Coding and Testing

  • To start translating our program into Java, we start with our template
1
2
3
4
5
6
7
8
import java.util.*;

public class Template {
    public static void main(String[] args) {
        // Enter code here

    }
}
  • We rename the class and save the file as Pizza.java
  • Then we compile and run it to make certain everything works
  • Next we add the code for subtask 1 to our program
    • After adding each task, we compile and run the program to make sure every still works
    • If we find an error, we correct it before continuing
  • Since we have coded these types of tasks before, I leave this subtask for you to do so we can focus on the new material
  • In main(), we implement subtasks 2 and 3 as calls to calcUnitPrice
  • We save the results of the method calls in two variables as shown:
unitPriceSmall = calcUnitPrice(diameterSmall, priceSmall);
unitPriceLarge = calcUnitPrice(diameterLarge, priceLarge);
  • Next we "stub out" the method and then compile and run the program to make sure every still works
  • Stubs are the outline of a method but without the algorithm implemented
  • Since the method must return a value, we return a "dummy" value
  • double calcUnitPrice (int diameter, double price) {
        return 1; // dummy value
    }
    
  • With our subtasks 2 and 3 in place, we go on to implement subtasks 4 and 5
  • Again, since we have coded these types of tasks before, I leave these subtasks for you to do so we can focus on the new material
  • After we complete our main() method, we come back and implement the algorithm for calcUnitPrice

Coding calcUnitPrice

  • We translate our pseudocode into Java and obtain the following:
  • static double calcUnitPrice(int diameter, double price) {
        const double PI = 3.14159;
        double radius, area;
        radius = diameter / 2;
        area = PI * radius * radius;
        return (price / area);
    }
    
  • What do you notice about the code?
  • The following statement looks right but is a serious mistake
  • radius = diameter / 2;
  • We want the radius to include the fractional part of the size
  • However, integer division truncates the remainder
  • How do we fix the problem?
  • static double calcUnitPrice(int diameter, double price) {
        const double PI = 3.14159;
        double radius, area;
        radius = diameter / 2.0;
        area = PI * radius * radius;
        return (price / area);
    }
    
  • Now radius will include fractional parts
    • This would work as well:
    • radius = diameter / 2.0;
  • Here is a link to our completed program: Pizza.java

Testing

  • Just because a program compiles and runs does not mean that it is correct
  • To verify that you program returns the correct answers, you should test it with known values and compare it with known results
  • You can get known values and results by using pencil and paper or a calculator
  • Once you have checked your program with a few known values, then you can have more confidence that it is correct

8.1.7: Summary

  • Top-down design is a technique for creating algorithms
    • The ideas is to break down the tasks into subtasks
    • Then you break down each subtask into smaller subtasks as needed
    • Eventually, the tasks are so trivial that they are easy to code
  • A black box refers to something that we know how to use, but not how it operates
  • A programmer who uses a method needs to know what the method does, not how it does it
    • You want to write methods so that the method declaration and block comments are all a programmer needs to use the method
  • We applied top-down design to the problem of buying the best size of a pizza
  • Along the way, we made sure to design our methods as black boxes

Check Yourself

  1. What is meant by the term top-down design?
  2. What does it mean to say that a programmer should be able to treat a method as a black box?
  3. What is the purpose of the comment that accompanies a method declaration?
  4. What is the purpose of testing code that compiles?

8.2: Pre-Midterm Q&A

  • Any questions?

Wrap Up

Home | WebCT | Announcements | Schedule | Expectations | Course info
Help | FAQ's | HowTo's | Links

Last Updated: October 16 2005 @22:40:04