chapter8_nn.ppt

advertisement
Chapter 8 – Software Engineering








Coding-Style Conventions
Helper Methods
Encapsulation (with Instance Variables and Local
Variables)
Algorithmic Design with OOP
Top-down Design
Stubs
Merging Driver Method into Driven Class
Accessing Instance Variables Without Using this
1
Coding-Style Conventions
/*********************************************************
* StudentDriver.java
* Dean & Dean
*
* This class acts as a driver for the Student class.
*********************************************************/
public class StudentDriver
{
public static void main(String[] args)
{
Student s1; // first student
Student s2; // second student
s1 = new Student();
s1.setFirst("Adeeb");
s1.setLast("Jarrah");
s2 = new Student("Heejoo", "Chun");
s2.printFullName();
} // end main
} // end class StudentDriver
2
Coding-Style Conventions
/*********************************************************
* Student.java
* Dean & Dean
*
* This class handles processing of a student's name.
*********************************************************/
import java.util.Scanner;
public class Student
{
private String first = ""; // student's first name
private String last = ""; // student's last name
//*******************************************************
public Student()
{ }
// This constructor verifies that each passed-in name starts with
// an uppercase letter and contains lowercase letters thereafter.
public Student(String first, String last)
{
setFirst(first);
setLast(last);
}
3
Coding-Style Conventions
//*******************************************************
// This method verifies that first starts with an uppercase
// letter and contains lowercase letters thereafter.
public void setFirst(String first)
{
// [A-Z][a-z]* is a regular expression.
// See API Pattern class.
if (first.matches("[A-Z][a-z]*"))
{
this.first = first;
}
else
{
System.out.println(first + " is an invalid name.\n" +
"Names must start with an uppercase letter and have" +
" lowercase letters thereafter.");
}
} // end setFirst
4
Coding-Style Conventions
// This method verifies that last starts with an uppercase
// letter and contains lowercase letters thereafter.
public void setLast(String last)
{
// [A-Z][a-z]* is a regular expression. See API Pattern class.
if (last.matches("[A-Z][a-z]*"))
{
this.last = last;
}
else
{
System.out.println(last + " is an invalid name.\n" +
"Names must start with an uppercase letter and have" +
" lowercase letters thereafter.");
}
} // end setLast
//*******************************************************
// Print the student's first and last names.
public void printFullName()
{
System.out.println(this.first + " " + this.last);
} // end printFullName
} // end class Student
5
Helper Methods




As with all examples discussed so far, methods
normally use the public access modifier.
public methods are considered to be part of the
class's interface.
Sometimes, you'll want to create a method that
should not be part of the interface; instead it just
supports the operation of other methods within its
own class.
Those methods are called helper methods and they
should use the private access modifier.
7
Helper Methods

Suppose you're asked to write a program that handles order entries for
sports-uniform shirts. For each shirt order, the program should prompt
the user for a shirt's primary color and its trim color. For each color
selection, the program should perform the same input validation. It
should verify that the entered color is one of three values – w, r, or y,
for white, red, or yellow. That input validation code is non-trivial. It's in
charge of:






Prompting the user for a color entry.
Checking whether the entry is valid.
Repeating the prompt if the entry is invalid.
Converting the single-character color entry to a full-word color value.
Rather than having the complete input validation code appear every
time color selection is needed, you should use a helper method to
implement the color-selection task.
With a helper method, the color-selection code appears only once in
the program, and whenever color selection is needed, the colorselection method is called.
8
Helper Methods
import java.util.Scanner;
public class Shirt
{
private String name;
// person's name
private String primary; // shirt's primary color
private String trim;
// shirt's trim color
//*********************************************************
public Shirt()
{
Scanner stdIn = new Scanner(System.in);
System.out.print("Enter person's name: ");
this.name = stdIn.nextLine();
this.primary = selectColor("primary");
this.trim = selectColor("trim");
} // end constructor
No need for a reference
variable dot prefix here.
//*********************************************************
public void display()
{
System.out.println(this.name + "'s shirt:\n" +
this.primary + " with " + this.trim + " trim");
} // end display
//*********************************************************
9
Helper Methods
Use the private access modifier for a helper method.
// Helper method prompts for and inputs user's selection
private String selectColor(String colorType)
{
Scanner stdIn = new Scanner(System.in);
String color; // chosen color, first a letter, then a word
do
{
System.out.print("Enter shirt's " + colorType +
" color (w, r, y): ");
color = stdIn.nextLine();
} while (!color.equals("w") && !color.equals("r") && !color.equals("y"));
switch (color.charAt(0))
{
case 'w':
color = "white";
break;
case 'r':
color = "red";
break;
case 'y':
color = "yellow";
} // end switch
return color;
} // end selectColor
} // end class Shirt
10
Helper Methods

In the Shirt constructor from two slides ago, note how we call
the selectColor method without a reference variable prefix:
this.primary = selectColor("primary");


If you're in a constructor (or an instance method, for that
matter), if you call another method that's in the same class, the
reference variable dot prefix is unnecessary.
Benefits of using helper methods:
1.
2.
By moving some of the details from big public methods into
helper methods, you enable the public methods to be more
streamlined (smaller). And that leads to improved program
readability.
Using helper methods can reduce code redundancy. For example,
in the Shirt program, we called the selectColor method
twice, but implemented it only once.
11
Encapsulation


A program exhibits encapsulation if its data is
hidden; i.e., if its data is difficult to access from the
“outside world.”
Why is encapsulation a good thing?


Since the outside world isn't able to directly access the
encapsulated data, it's more difficult for the outside world
to mess things up.
How is encapsulation implemented?


Break a big problem into separate classes where each class
holds a set of encapsulated data (those data items are
called instance variables, and they should use the private
access modifier).
Break a class's tasks into separate methods where each
method holds a set of encapsulated data (those data items
are called local variables).
12
Encapsulation

Declaring data as instance variables within a class is one form
of encapsulation, and declaring data as local variables within a
method is another form of encapsulation. Which is the
stronger (more hidden) form of encapsulation?


An instance variable may be shared by all the methods in the
class, whereas a local variable is local to one method, so a local
variable is more encapsulated.
Thus, in the interest of encapsulation, you should use local
variables, as opposed to instance variables, whenever possible.

Declare a variable locally within a method:

important

If the variable only needs to persist (remain alive) for the duration of
that particular method.
Declare a variable as an instance variable:


If the variable stores a fundamental attribute of the class's objects.
If the variable needs to persist for the duration of the class's objects
(i.e., it needs to persist longer than the duration of one particular
method).
13
Algorithmic Design with OOP

Given a problem description. What steps should you
use to implement its solution?





Decide on the classes/objects that are needed.
For each class, decide on its instance variables.
For each class, decide on its public methods (= the
interface).
For each method, implement it using top-down design.
Use top-down design for your methods:


In writing a public method (a "top" method), if the
method is fairly involved and can be broken into subtasks,
then have the public method call private helper
methods to do the subtask work.
Finish writing your public methods before starting to write
your private helper methods.
14
Algorithmic Design with OOP

Why is top-down design beneficial?


The programmer doesn't have to initially worry about the
details of each subtask's implementation. That way, the
programmer can focus on the big picture first. And focusing
on the big picture is crucial because if the big picture is
wrong, the whole thing is wrong.
Why is top-down design also called stepwise
refinement?
15
Algorithmic Design with OOP

16
Example: Write a top-down outline for a method that
calculates an estimated cost for a building.
Public interface method:
Private helper method:
Private helper method:
pub vd calcBldgCosts()
{
...
calcBathrooms();
calcOtherRooms();
...
}
pri vd calcBathrooms()
{
...
calcFloorSpace();
...
}
pri vd calcOtherRooms()
{
...
calcFloorSpace();
...
}

If two or more methods perform the same subtask,
avoid redundant code by having those methods call a
shared private helper method that performs the
subtask.
Algorithmic Design with OOP

Algorithmic Design Example:

Implement the functionality of a square. More specifically,
the square should be able to:



Set/assign its width.
Calculate and return its area.
Draw itself with asterisks using either an asterisks border or a
solid pattern of asterisks. Each time the square is drawn, the
user is prompted as to whether he/she wants to draw with a
border or with a solid pattern.
17
Stubs

After writing your entire program in pencil on paper, enter your
program on a PC using stubs for your subtask methods. A stub
is a dummy method like this:
public void drawSides()
{
System.out.println("In drawSides");
}

Benefit of using stubs:


If the program is initially entered with stubs, then the programmer
will be able to more easily get an initial successful compilation
(and that leads to a "warm fuzzy" feeling).
Debugging is easier.



After the program is successfully compiled and run with stubs, then
the programmer replaces the stubs with actual code one method at a
time.
Ideally, after each method is replaced, it's thoroughly debugged.
That way, if a bug appears, it should be easy to find since you know
it's probably in the newly replaced method.
19
20
Merging Driver Method into Driven Class




So far, we've split each of our OOP programs into two separate
files - a file that describes an object (e.g., Mouse, Car) and a
driver file (e.g., MouseDriver, CarDriver).
It's legal to merge the two files into one file, but we've refrained
from doing that because using two separate files leads to a
more understandable program.
We'll continue to use separate files for most programs, but for
short programs that don't do much except illustrate a concept,
we'll merge the main method into the driven class.
Why?

It's a matter of convenience - there's one less file to create and
there's slightly less code to enter.
21
Merging Driver Method into Driven Class
public class Time
{
private int hours, minutes, seconds;
//*******************************************************
public Time(int h, int m, int s)
{
this.hours = h;
this.minutes = m;
this.seconds = s;
}
//*******************************************************
public void printIt()
{
System.out.printf("%02d:%02d:%02d\n", hours, minutes, seconds);
} // end printIt
//*******************************************************
public static void main(String[] args)
{
Time time = new Time(3, 59, 0);
time.printIt();
} // end main
} // end class Time
22
Accessing Instance Variables Without Using this

For a while now, we've used this to access instance
variables from within a method. Here's a formal
explanation for when to use this:



Use this within an instance method or a constructor to
access the calling object's instance variables. The this
reference distinguishes instance variables from other
variables (like local variables and parameters) that happen to
have the same name.
If there's a parameter or a local variable with the same name
as an instance variable, then you must use this in front of
the name to refer to the instance variable and use the name
by itself to refer to the parameter or local variable.
However, if there is no name ambiguity (i.e., there are no
same-named variables), you may omit the this prefix when
accessing an instance variable.
23
Accessing Instance Variables Without Using this
public class MouseShortcut
{
private int age;
private double weight;
// age in days
// weight in grams
//************************************************
public MouseShortcut(int age, double weight)
{
setAge(age);
setWeight(weight);
} // end constructor
//************************************************
public void setAge(int a)
{
age = a;
} // end setAge
OK to omit this before
instance variable age because
it's different from parameter, a.
24
Accessing Instance Variables Without Using this
//************************************************
public void setWeight(double weight)
{
Not OK to omit this before
this.weight = weight;
instance variable, weight, because
} // end setWeight
it's same as parameter, weight.
//*************************************************
public void print()
{
System.out.println("age = " + age +
", weight = " + weight);
} // end setWeight
} // end class MouseShortcut
OK to omit this
before age and
weight instance
variables.
Download