810 likes | 906 Views
CISC121 – Lecture 6. Last time: Encapsulation Javadoc documentation Testing and Debugging. You Should Be:. Able to apply feedback from Assn 1 to Assn 2. Just about finished Assn 2. Finished reading over testing and debugging notes from last lecture. You Will Need To:.
E N D
CISC121 – Lecture 6 • Last time: • Encapsulation • Javadoc documentation • Testing and Debugging CISC121 - Prof. McLeod
You Should Be: • Able to apply feedback from Assn 1 to Assn 2. • Just about finished Assn 2. • Finished reading over testing and debugging notes from last lecture. CISC121 - Prof. McLeod
You Will Need To: • Look at Exercise 3 and start work on Assn 3 – both on Encapsulation. • Prepare for midterm: • Krista will hold midterm prep tutorial at 4:30pm in GOO456 (the lab) on Monday. E-mail her if you intend to go! • Next Tuesday, the 24th, at 10am – Note late start! • In BIO1120 (same room as lecture). • Look over and print out a copy of the aid sheet (now posted), if you want to use it. CISC121 - Prof. McLeod
Midterm Topics • Fundamental Java, Including: • Expressions, Loops and Conditionals • Methods • File and Console I/O • Catching Exceptions • Encapsulation • Testing and Debugging (comprehension only) • Linked Lists • (Staring, but not finishing, this topic today. I will not ask you anything hard on linked lists on the midterm.) CISC121 - Prof. McLeod
Midterm Format • All hand-written on paper: • Short answer comprehension questions. • “What is the Output” questions. • Write or complete or correct a method or program. CISC121 - Prof. McLeod
Today • Finish up Testing and Debugging by looking at invariants. • Start Linked Lists • But first, let’s go over how the debugger works in Eclipse. CISC121 - Prof. McLeod
Debugging in Eclipse • If you have not used Debug before – the “Debug Perspective” button will not show up at the top right. • To use debug mode, you must put a breakpoint into your program, by right-clicking on the bar at the left of your program, and choosing “Toggle Breakpoint”. • Then choose “Debug As” followed by “Java Application”. CISC121 - Prof. McLeod
Debugging in Eclipse, Cont. • Now you are in the “Debug Perspective”! • Lots of fun things to do here! • You can examine the current contents of variables and objects. • You can continue your program one line of code at a time. • etc.! • (Also look at version history in Eclipse…) CISC121 - Prof. McLeod
Program Correctness • Another logic tool that you can use to prove that your program is “correct” is the use of assertions. • Special assertions are called: • Preconditions, • Postconditions & • Invariants. • Essentially, an assertion is just a statement that describes a condition that should be true at a given point in your program. • An assertion could just be a comment. • Java provides the use of the “assert” command, that can do something useful in the event that the condition turns out to be false. CISC121 - Prof. McLeod
Pre- & Post- Conditions • These assertions are made at the beginning of a method (pre-condition) and at the end of the method (post-condition). • A precondition: • Specifies what is true before the method executes. • Describes the assumptions under which the method runs. • Satisfying the preconditions is the responsibility of the calling method (or “user”). • A postcondition: • Specifies what is true after the method executes. • Describes the effects of the code. • Satisfying the postconditions is the responsibility of the person coding the method. CISC121 - Prof. McLeod
Pre- & Post- Conditions - Cont. • These conditions form part of the specifications of the method. • A piece of code is said to be correct if the postconditions will be satisfied for all possible states of the preconditions. • It is not always possible to completely prove correctness by this definition. • Sometimes all you can say is that the postconditions will be satisfied whenever the method terminates normally. • This is called partial correctness. CISC121 - Prof. McLeod
Pre- & Post- Conditions - Cont. • For example, a little method to see if a number is prime: public static boolean isPrime (int n) { for (int i = 2; i * i <= n; i++) if (n % i == 0) return false; return true; } // end is Prime method CISC121 - Prof. McLeod
Pre- & Post- Conditions - Cont. • Add pre- and post- conditions: // pre: n is >= 2 public static boolean isPrime (int n) { for (int i = 2; i * i <= n; i++) if (n % i == 0) return false; return true; } // end is Prime method // post: true if n is prime, false // otherwise CISC121 - Prof. McLeod
Invariants • Invariants are assertions that are placed at strategic positions within the code. • Invariants state what is true at this position. • If the program logic is correct, then one insertion should lead from the one before and the last insertion should prove the post-condition to be true. • Next slide has our little method with invariants put in as comments: CISC121 - Prof. McLeod
// pre: n is >= 2 public static boolean isPrime (int n) { for (int i = 2; i * i <= n; i++) { // inv1: n has no factors between 2 and i-1 if (n % i == 0) { // inv2: i divides n evenly, therefore // n is not prime return false; } // inv3: n has no factors between 2 and i } // end for loop // inv4: n has no factors between 2 and// n, therefore n is prime return true; } // end is Prime method // post: true if n is prime, false otherwise CISC121 - Prof. McLeod
Invariants - Cont. • Note how the invariants below depend on the invariants above. The invariant above must be true in order to allow the invariant below to be true. • Also, the invariants above the return statements, inv3 & inv4, when combined, prove the post-condition to be true. • So, if you can chain together the invariants between the pre- and post- conditions, and thus prove that the post condition is true, then you have proved the “correctness” of your program. CISC121 - Prof. McLeod
Invariants - Cont. • In essence, the process is all about forming a contract between the pre- and post- conditions. • Having proved the “correctness” of your program, you are now ready to subject your program to a thorough testing with real values. • Since you can not test every possible input value, your proof of correctness along with some testing must be sufficient to give you confidence that your method works. CISC121 - Prof. McLeod
Aside – Loop Invariants • “inv1” is called a “loop invariant”, because it is inside the loop. • For this kind of invariant: • Make sure it is true when the loop starts. • Make sure it stays true each time through the loop. • Does the invariant lead to the desired condition when the loop terminates? • Make sure the loop will terminate! CISC121 - Prof. McLeod
Program Correctness - Cont. • For the example above, you could have walked through the logic in your head to prove that it works. Was all this fancy stuff necessary? • The use of assertions has two purposes: • It can help to provide documentation of your code: • Pre- and Post- conditions are an important part of the documented specifications of your code. • More complex methods would be difficult to “walk through” without some kind of commenting to indicate the progression of the logic. CISC121 - Prof. McLeod
Invariants – Triangle Example • Remember the example of the triangles? • It contains a logic error, but no syntax errors – it compiles and runs fine. • It took many random test cases to determine that there was a logic error. • Here is the code with assertions (squished…): CISC121 - Prof. McLeod
// pre: a,b,c > 0 and form a triangle public static String testTriangle (int a, int b, int c){ if (a == b) { if (b == c) { return "equilateral";} //inv1: a=b, b=c, a=c else { return "isosceles";} //inv2: a=b, bc, ac } else { if (b == c) { return "isoscles";} //inv3: ab, b=c, ac else { return "scalene";} //inv4: ab, bc, ac or a=c } } //end testTriangle // post: all possibilities have been tested Not so! CISC121 - Prof. McLeod
Invariants – Triangle Example – Cont. • Now it is easier to see that not all possibilities have been tested. A situation can be reached where: ab, bc, but a=c is unknown. • So there is a break in the logic between inv4 and the post condition. CISC121 - Prof. McLeod
Program Correctness - Cont. • In Java versions > 1.4, assertions can be put in the code using the “assert” command, where they can actually do something useful. • Use “assert” when you are having problems debugging a particular piece of code. • You can use a compilation switch to tell the compiler to ignore all assertions when it does the final compile on your code – this way you don’t have to take them out of the source code! CISC121 - Prof. McLeod
The Java assert Keyword • Syntax: assert expression1; assert expression1: expression2; expression1 must evaluate to a boolean result. For the second syntax, expression2 provides a String for the AssertionError that will be thrown when expression1 evaluates to false. CISC121 - Prof. McLeod
Using Assertions in Code - Cont. • By default, code is compiled with the assert command being treated as a comment - so they do not have to be removed when not needed. • You have to tell the compiler to “enable assertions” for them to work. • Make sure that your assert statement is passive. It should not “do anything” with variable contents or change how the program runs. • In this way, ignoring the assertions should not affect the program. CISC121 - Prof. McLeod
Using assert, Cont. • How is using assert different from just throwing an exception directly? • It is easier to do, and the invoking method does not have to worry about catching an exception. • You have the option of compiling and running your program in such a way that assertions can be ignored, speeding up the execution of your code. • During program development, enable assertions. Once done, disable them. • You can leave all your assert statements in your source code! CISC121 - Prof. McLeod
Aside – Using Assertions in Eclipse • To add the command line parameter: “-ea” for “enable assertions” • Go to “Run” on the menu bar, then choose “Run…”. • In the window that opens, choose the “Arguments” tab and enter “-ea” (without the quotes) in the “VM arguments” box. • This parameter gets reset when you exit Eclipse. • To set permanently: • Go to “Window”, “Preferences…”, “Java”, “Installed JREs” and choose “jre1.6.0” and then click on the “Edit” button. Add “-ea” to “Default VM Arguments”. CISC121 - Prof. McLeod
Best Reference on Assertions • http://java.sun.com/j2se/1.5.0/docs/guide/language/assert.html CISC121 - Prof. McLeod
Creating a Data Structure • Why create our own data structures when there are so many pre-defined in the Java API already? (Lets have a look in java.util in the API docs…) • To learn how they are put together. • Avoid including extra methods that are not needed. (Tighter, more efficient code.) • Specific structure for our requirements, not using a generic structure. • Avoid privacy leaks. CISC121 - Prof. McLeod
Comparison of Arrays, ArrayLists and Linked Lists • Arrays can be useful because: • The convenient “[]” notation allows immediate access to any element in the array. • Arrays can directly hold primitive types, as well as objects. • Primitive type storage is memory efficient, since the use of a Wrapper class is not necessary. CISC121 - Prof. McLeod
Comparison of Arrays, ArrayLists and Linked Lists - Cont. • Arrays can be a problem because: • The size of the array must be known or at least estimated before the array can be used. • Increasing the size of an array can be very time intensive. How would you do this? • Arrays can only use a contiguous block of memory. When a new element is inserted into an array, all elements above the new one must be shifted up. CISC121 - Prof. McLeod
Comparison of Arrays, ArrayLists and Linked Lists – Cont. • ArrayLists are useful because: • Sizing is no longer a problem. • They are built-in to the java.util class. • They inherit many useful methods. • ArrayList<T> (The generic ArrayList class.) elements do not need to be cast back to the original element type. • Automatic boxing and un-boxing in Java >= 5.0 CISC121 - Prof. McLeod
Comparison of Arrays, ArrayLists and Linked Lists – Cont. • An ArrayList can be a problem because: • Arrays are still used (in the background). • Every re-sizing of the ArrayList causes a time lag, since a new array must be created in another block of memory and all the elements copied over. • Element insertion is just as time-consuming as with arrays, and possibly even worse if the ArrayList has to be resized. • It can only store Objects, not primitive types. • Do not have the handy “[]” notation, only methods. CISC121 - Prof. McLeod
Linked Lists • A singly linked list consists of Objects called “nodes” that contain data and a link to the next node in the list: • A node is defined in one class, and another class, the linked list class, contains the “head” and “tail” pointers. • More detail shortly! tail head 20 15 10 5 null CISC121 - Prof. McLeod
Comparison of Arrays, ArrayLists and Linked Lists – Cont. • Linked lists are useful because: • Can store primitive types or Objects or any combination of the above. • A node can be anywhere in memory. The list does not have to occupy a contiguous memory space. • List size is only limited by available memory, and does not have to be declared first. • No empty nodes. • The adding, insertion or deletion of list elements or nodes can be accomplished with the minimal disruption of neighbouring nodes. CISC121 - Prof. McLeod
Comparison of Arrays, ArrayLists and Linked Lists – Cont. • Problems with linked lists include: • A node is not necessarily an efficient storage Object (in terms of memory usage), since it must hold links to other nodes in addition to the data item(s). • In order to access any one node in a linked list, all links must be followed from the “head” of the list to get to that certain node. Nothing like the “[]” notation of arrays. CISC121 - Prof. McLeod
Singly Linked List - Node Class public class IntNode { public int info; // a data value public IntNode next; // a link // constructors public IntNode (int i) { this(i, null); } public IntNode (int i, IntNode n) { info = i; next = n; } } // end IntNode CISC121 - Prof. McLeod
Singly Linked List – Cont. • The “data value” could just as easily be an Object (of any kind): public class GNode { public Object info; //a data Object public GNode next; // a link // constructors public GNode (Object newInfo) { this(newInfo, null); } public GNode (Object newInfo, GNode n) { info = newInfo; // should clone newInfo… next = n; } } // end GNode CISC121 - Prof. McLeod
Singly Linked List – Cont. • For simplicity, we will continue to consider a link holding an intvalue, “info”. • For example, create a linked list of three integers, 10, 8 and 50: CISC121 - Prof. McLeod
Singly Linked List – Cont. • First statement: IntNode p = new IntNode(10); • As usual, this operation takes place in four stages: (ii) (i) p p 10 info: next: p p 10 10 null null (iv) (iii) CISC121 - Prof. McLeod
Singly Linked List – Cont. • The above initialization uses the first constructor, which sets the value of info to 10and sets the value of nextto null. • The next node is created using p.next = new IntNode(8); CISC121 - Prof. McLeod
Singly Linked List – Cont. p.next = new IntNode(8); p 10 null p 10 8 null p 10 8 null null p 10 8 null CISC121 - Prof. McLeod
Singly Linked List – Cont. • The last node (50) is added using: p.next.next = new IntNode(50); p 10 8 50 null CISC121 - Prof. McLeod
Singly Linked List – Cont. • Note that the last node always contains null. • Right now, the list is only accessible through the variable “p”, so the cumbersome chain of “next”’s must be used to get at the individual elements. • (What happens to the list if you coded “p = null;”?) • Introduce another class that will keep track of the head and tail positions of the list: CISC121 - Prof. McLeod
public class IntSLList { // A “singly linked // list with a head and tail” private IntNode head; private IntNode tail; public IntSLList () { head = null; tail = null; } public void addToHead (int aNum) { head = new IntNode(aNum, head); if (tail == null) tail = head; } // more methods to be developed! } // end IntSLList CISC121 - Prof. McLeod
Singly Linked List - Node Class (again) public class IntNode { public int info; // a data value public IntNode next; // a link // constructors public IntNode (int i) { this(i, null); } public IntNode (int i, IntNode n) { info = i; next = n; } } // end IntNode CISC121 - Prof. McLeod
Singly Linked List – Cont. • Create a list using: IntSLList list = new IntSLList(); list head null null tail CISC121 - Prof. McLeod
Singly Linked List – Cont. list.addToHead(5); // step i list.addToHead(10); // step ii list.addToHead(15); // step iii list IntNode’s head 5 null tail head 10 5 null tail 15 10 5 head null tail CISC121 - Prof. McLeod
Singly Linked List – Cont. • Now either end of the linked list can be located using the head or tail pointers, without using a cumbersome chain of next’s. CISC121 - Prof. McLeod
Singly Linked List – Cont. • Simplify notation. This: • Is the same as: head 15 10 5 null tail tail head 15 10 5 null CISC121 - Prof. McLeod