• 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
• 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!
• 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
• 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
• 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
• 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
• 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)
• 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
• 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 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!
• 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
• 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 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
• 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
• 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
• 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
• 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
• 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
• 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
• 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.
}
• 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