Program Design

advertisement

Program Design

“Programming”

• I use the term “programming” to include a wide range of activities--but many people don’t

• Sun provides three Java certification exams:

– Programmer: The SCJP exam tests your knowledge of the core language.

– Developer:

The SCJD tests whether you can apply the core language to solve a coding problem.

– Architect: The SCEA exam tests your ability to produce an enterprise architecture using J2EE TM .

• In this terminology, “programmer” is the lowest tier

“Coder”

• A coder is someone who write code (equivalent to

Sun’s term “programmer”)

• Coders are low-level flunkys--their manager tells them exactly what to program

• A developer is someone who can figure out how to use a computer to solve a problem

• Most of what I have asked you to do is coding

• I really want you to be (at least) developers--

– but I don’t really know how to teach this skill

– moreover, the curriculum doesn’t help much

– nevertheless, I have to try!

Approaches to design

• The UNIX approach:

– Determine what functionality is required

– Implement that functionality

– Put a user interface on top of it (or not)

• The Macintosh approach:

– Determine what functionality is required

– Decide how that functionality should be presented to the user (i.e. design the GUI)

– Implement the functionality

Example: Expression evaluation

• In this set of slides, I will try to explain something about the way I went about this problem

• You do not need to implement expression evaluation the same way that I did

– These are not added requirements for your assignment

The problem

• Here’s the problem:

– Come up with another class assignment

• Constraints:

– It has to be doable in a week or less

– It has to help students understand and remember the ideas we are currently discussing in this course

– It has to avoid concepts we haven’t talked about yet

– In order to discourage dishonesty, it has to be something students can’t just get from the web

– It has to be something that isn’t too difficult to grade

Stacks and ADTs

• We are currently talking about stacks and ADTs

• ADTs are everywhere, so the hard part is stacks

• I thought about several possibilities, and decided that expression evaluation seemed like the best

– This is doable if I provide enough instruction and help

– It’s directly related to current course material

( and it’s a classic use for stacks)

– It’s ubiquitous, so I had to make numerous specific requirements in order to discourage cheating

– It uses a HashMap , but I can provide code for that

– With a GUI, it shouldn’t be too difficult to grade

Specific requirements

• To discourage cheating, here’s what I did:

– Gave you the complete algorithm, as best I could, so you only have to code it

• If you find any errors, please point them out quickly so I can post the corrections!

– Specified how to implement the stacks

• This also let me tune the assignment to emphasize certain important concepts

– Added the bit about handling assignments as well as expressions (which, by the way, introduces some unpleasant complications)

Classes and responsibilities

• In designing an Object-Oriented program, the most important step is deciding what classes to have, and what their responsibilities are

• Classes should be cohesive and loosely coupled

– cohesive: a class should represent a logical whole

• the data should, collectively, describe one thing

• the operations should apply to that one thing

– loosely coupled: the class should depend as little as possible on other classes; it should be relatively independent of its environment

The GUI

• This program doesn’t require a GUI

– it could read expressions from one file, and write results to another file

• But--

– The GUI is trivial, especially with Forté

– It makes the program both nicer and easier to grade

• Since the GUI is trivial, we could just put the expression evaluation code in the same class

– But this would couple the expression evaluator to the

GUI, so it would not be independent--you couldn’t pull it out and use it elsewhere

– Combining the evaluator and the GUI is a bad idea!

The GUI and the evaluator

• The expression evaluator doesn’t need the GUI

– Therefore, it should be separate and independent

• The GUI does use the expression evaluator

– A GUI is almost always program-specific

• But...

how does the GUI use the expression evaluator?

– Only as a black box

– The GUI:

• takes an input and gives it to the black box

• takes the result from the black box displays it

– Hence, the GUI can be almost entirely independent

• We now have two cohesive and loosely coupled classes!

Who’s in charge?

• The GUI is almost always “in charge,” in the sense that it starts everything and controls everything

• This is because, as a good design principle, we want to put the user in charge, not subservient to the computer

• There is no obvious reason to do things any differently in this program

• However, the evaluator could be in charge

– There’s something useful to be derived from this, which we’ll explore a bit later

Communication

• The GUI and the Evaluator have to talk to each other, but we want to keep them loosely coupled

• Since we start from the GUI, it has to create an instance of the Evaluator

• In the Evaluator, we’ll have a method evaluate that takes a String and returns a double

– The GUI can use this method as a black box

– The Evaluator needs to know absolutely nothing about the GUI

– However the Evaluator is used, it needs this method

The Evaluator stacks

• The Evaluator needs two stacks (that’s just the nature of the algorithm)

• A stack is an obvious ADT

– The Evaluator should be concerned with evaluating an expression; it should use stacks, not implement them

• Java’s Stack , like everything in the Collection framework, holds arbitrary Object s

– You have to wrap primitives to put them in, and unwrap them when you take them out

– This is work that can be moved out of evaluate

An added bonus

• Since two stacks are required, I can ask you to implement them in two different ways

• Remember, the problem I am trying to solve is not how to evaluate expressions--

– it’s how to teach you about stacks!

• I can ask you to implement one stack yourself

– This teaches you about stack implementation

• For the other, I can ask you to wrap Java’s Stack

– This demonstrates how to create a wrapper, and how doing so can simplify the other parts of your program

Other methods

• I decided to store operators simply as char s

• I need to compare the precedences of two operators, so I wrote an int precedence(char) method

• I had to do the following repeatedly:

– pull two values off the value stack

– apply an operator (represented as a char )

– push the result back onto the value stack

• This was another obvious candidate for a method

• I also had a method to decide if a token is a value or an operator

• These are all private methods in the Evaluator class

Assignment statements

• I decided to add assignment statements as well as expressions to the programming assignment

– This makes it harder to just pull a program off the web

– It’s also a nice feature to have

– However, it does complicate matters a bit

– Hint: decide if it’s an assignment before you evaluate

• The obvious ADT for holding values is a HashMap , but we haven’t studied these yet

– I decided to disguise HashMap lightly, by means of a simpler, more problem-oriented wrapper, Memory

– memory.store(name, value) assigns a value to a variable

– memory.fetch(name) looks up the value of a variable

StringTokenizer

• This leaves the problem of breaking the input expression up into tokens --variables, numbers, and operators

• You could do this yourself, with just String or

StringBuffer operations, but java.util.StringTokenizer

is exactly the right tool for the job

• I haven’t taught you StringTokenizer , but:

– It’s easy enough to figure out from the API

– This will give you practice using the API

– StringTokenizer is well worth learning in any case

• I made its use required, so you won’t do it yourself because you (mistakenly) think that would be easier

Unit testing

• The idea of unit testing is that every component

(unit) should be tested by itself, in isolation

• Your stack classes are such units

• Your Evaluator class is another such unit

• We can (and should) do unit testing on these

– I didn’t do unit testing on the Evaluator, but I did on the stack classes

– It’s a more effective use of your time to test each unit separately and get the bugs out, before you put it all together and have to debug it as a whole

The main method

• You are familiar with public static void main(String args[]) as where your program starts

• But did you know:

Any and all classes can have a public static void main(String args[]) method

• This is the perfect place to put unit tests

• Start from this class to test this class

• Start from your “main” class to run the program

Sample unit test

• For the Evaluator class:

• public static void main(String args[]) {

System.out.println("2+3 gives " + evaluate("2+3"));

System.out.println("3*(4-2) gives " + evaluate("3*(4-2)"));

System.out.println("x=17 gives " + evaluate("x=17"));

System.out.println("x gives " + evaluate("x"));

// etc.

}

Concluding remarks

• Design hints

– Solve the real problem

– Consider more than one way of doing things

– Choose classes and methods early, before you start coding

– Strive for independence: keep your classes cohesive and loosely coupled

– Don’t put actual work in the GUI class

• Coding hints

– Write and test in small pieces, not all at once

– Do unit testing

The End

Download