Comp 170 Week 9

Exam 2 is set for Wednesday, April 8 (the Wednesday before Easter)
Main topic will be inheritance. A study guide will again be provided.

Review features of DomeLab:
Next concept: static type versus dynamic type.

Main advantages of this (at this point):
Java and pointers
Remember that everything is represented internally in Java with a "pointer", or memory location. This is what makes it possible to put a CD object into an Item variable, even though the latter takes fewer bytes. The actual variable is just an address. (Draw a picture with a single variable and with an array)

Static v Dynamic type
The static type of a variable is the type it is declared as:
    Item it
    ArrayList<Item> items
As it's now possible to put something into a variable that is not an exact match, we need to distinguish the static type of the variable itself from the dynamic type of what its contents is at a particular moment. (Review pictures above)

Example: list() method of database class, item and items.

Vehicle hierarchy
Animal hierarchy

Subclass constructor
Basic principle: we must construct the base-class object too! Through a call to super().
Example: dome

DomeLab:
print method: how to print Item fields?
keyword method


inheritance demo

source code at http://cs.luc.edu/pld/courses/170/spr09/zips/inheritance.zip


    public class Base {
        private int x;
   
        public Base(int x)  {
            this.x = x;
        }
   
        public String foo() {
            return "All your BASE are belong to us!";
        }
          
        public int bar( ) {
            return x;
        }
    }


    public class A extends Base {
        private int y;
   
        public A(int x, int y) {
            super(x);
            this.y = y;
        }
   
        public String foo() {
            return "I am an A";
        }
       
        public int bar() {
            return super.bar() + y;
        }
       
        public int baz() {
            return 0xDEADBEEF;
        }
    }


    public class B extends Base {
        private int z;
       
        public B(int x, int y) {
            super(x);
            this.z = y;
        }
   
        public String foo() {
            return "BBBBBB>>>" + super.foo() + "<<<BBBBBB";
        }
       
        public int bar() {
            return 1000*z + super.bar();
        }
    }


 
Wednesday

"Test until fear turns to boredom"


Chapter 6: Testing

(We're going to defer this until after Zuul)

Diary example: from book projects, chapter 6
diary-prototype: introduces basic ideas of diary project; doesn't really do anything.

concept of "Regression Testing": apply old test to each new version

manual test program: diary-testing.

Problem: how do we interpret the results??

JUnit testing:

Create a new test in a copy of the Diary v2 example have it create a day, and two new appointments, and test some things

JUnit testing doesn't work as well for simulating interactive input!

Demo of adding a test, eg findslot

Skip the calculator for now

How do I test Zuul lab? I try take & drop.
I should try taking a 1-weight thing when I have 9-weight, and also when I have 10-weight.
This would tell me if you made a mistake in < versus <=.


How to test generateResponse(ArrayList sentence)??

1. sometimes you do have to write manual test code. BlueJ adds the Object Bench, but some objects (like ArrayLists) can't be created there.
2. Write (in the responseTest test class) a method testSentence() that returns a sentence. Then, using the test-recording feature of bluej, run a test on generateResponse() and as parameter supply responseTest.testSentence();
3. JUnit supports the concept of a "Fixture"; a set of objects needed for tests.
4. Even if manual creation is necessary, automated run & interpret are still powerful.

There is also a particular issue in testing methods that use randomness to achieve their results!

MAYBE: Take a quick look at finding problems with bricks example.
Tools:

Testing:

Bricks test: check height, weight for 1 brick, 10 bricks
 0 bricks? problem with height!

Weight: 3 kg/brick

BASE_WEIGHT not included??

Is weight of a brick even right?

Use DEBUGGER to find problem with height: put a breakpoint at height method

How long to test?
    Test until fear turns to boredom

To some degree, this depends on how much fear is internally (or externally!) imposed.


LockSerpent project

What does it do? How do we do it?

Basic tour:
    go south & east to get the COOKIE, then back and down.
    GIVE COOKIE to the serpent. TAKE KEY.
    Then go to the lecture hall and GO NORTH.

Note two "locked" doors: UP out of STEAMTUNNEL, and NORTH out of THEATRE

We've added steamtunnel with special responses to GO and GIVE (try GIVE somewhere else), and also the theatre/preproom now has a locked door (the special room is actually the theatre). 

Note that LockSerpent is an example of doing it the WRONG WAY!


Take a look at LockSerpent code. Look at how we have to modify Game class, just to implement one new room. This is NOT good reuse. We have a good example here of complex coupling.

Note also the
    if (currentRoom == theatre && ....)


Keep in mind:

Adding steamtunnel (special words: GO, GIVE) and preproom (special word GO, actually special for theater)


processCommand:
Note the global variable serpent_happy, and the check
    if (currentRoom == steamtunnel && ! serpent_happy)
What rules does this violate?

Note also the code
    if (currentRoom == theatre && ....)

serpentCommand



Goals:
    Rigorously avoid code duplication by having serpentCommand only handle commands that are different from processCommand; serpentCommand passes everything else back to processCommand to handle.

    Shoot for good cohesion. Or, at least, the best we can do.

changes to create LockSerpent

  1. Add new rooms
  2. Move room declarations from being local to createRooms() to fields in Game class, so we can refer to them by name from anywhere
  3. Room.setDescription, so a room description can be changed later (eg the steamTunnel)
  4. serpent_happy: should be in a room, but we can't do that! (Well, we could have steamtunnel.getSerpentHappy() return true or false, but that doesn't entirely help.)
  5. Add serpentCommand check to processCommand, ahead of others, so processCommand can still handle anything serpentCommand decides to pass on.
Violations of rules:

cohesion is not really doing well here. The concept is that one method should do "one thing", and we're really forced to address lots of little checks. (Note that one can argue that this is acceptable cohesion, though; it is all tied to command processing.)

responsibility-driven design is faring even worse: processCommand is dealing with too many things that should not be its responsibility.

Maybe the easiest problem to point to is coupling: we're trying to create a Room with special behavior, but we're having to put the code for that into class Game (where processCommand is)