ANU The Australian National University



____________________________________________________

[ANU] [DCS] [COMP2100/2500] [Description] [Schedule] [Lectures] [Labs] [Homework] [Assignments] [COMP2500] [Assessment] [PSP] [Java] [Reading] [Help]

____________________________________________________

COMP2100/2500
Midsemester Exam sample solutions

Question 1 [10 marks]

(a) Explain the difference between the strict and soft locking mechanisms used in version control systems to prevent information loss due to revision's conflict. [1 mark]

Solution:

This is a knowledge of the concept question: simply explain in your own words, that strict locking mechanism disallows more than one developers to have a simultaneous write access (they can have the read access) to the item, thus avoiding overwrite and potential information loss, while soft mechanism allows multiple simultaneous modifications of the same item, but the "conflict resolution" kicks in when they are overlapping.

(b) Elaborate the meaning of the black box testing and white box testing. What is their relation to the structural and specification testing. [2 marks]

Solution:

(c) Name and characterise three kinds of static code analysis. [2 marks]

Solution:

(d) Explain why the Visitor pattern is not necessarily a good choice if the class hierarchy the visitor objects are meant to operate on is volatile, i.e. subject to frequent change. [2 marks]

Solution:

Use of the Visitor pattern results in the inter-dependency between the formally independent classes from the original (target) hierarchy, the so called cyclic dependency. A modification of a class from this hierarchy, which without the Visitor pattern would not affect other classes from the same hierarchy, now affects them, since they all depend on the interface of the Visitor, which changes when a class in the target hierarchy is modified or added. If the Visitor hierarchy is extensive, it itself will result in a substantial re-coding. Apart from this, the whole target hierarchy needs to be recompiled (which can be costly).

(e) Give the definition of callbacks. [1 marks]

Solution:

Callback is a notion from the Even-driven programming (which includes the modern GUI programming), which means that the user input (event) is only recognised by the application, but forwarded to the library routine, the callback (an EventHandler in Swing library), where it is properly dealt with resulting in the change of the system state in Model and its representation in View.

(f) What is Java anonymous inner classes; why are they useful in Graphical User Interface Programming. [2 marks]

Solution:

These are the inner classes (classes defined inside Java's standard classes) whose instantiation and complete implementation are done in one Java statement; no explicit name for the inner class is used, hence anonymous. The AIC are useful because they allow reduction in coding, placing the class declaration to the place where it's (only) used; the naming scheme for AIC makes it convenient for coding large GUI components, which can be assisted with code generating tools.



Question 2 [8 marks]

This question is about recursive tree data structures for representing algebraic expressions. We use the ‘Expression Version 4’ design (with the Visitor pattern) studied in lectures and in Lab 2. Your task here is to add the notion of variables to the system.

A variable has (a) a name, i.e. a textual representation, which is a single letter, represented in Java using the type char; and (b) a value, which is an integer, represented in Java using the type int. The set of variables used in evaluating an expression is stored in a Hashtable which maps variable names to variable values.

You may assume that the main class has a field:

Hashtable variables = new Hashtable();

which is initialised thus:

variables.put('a', 1);
variables.put('b', 2);
variables.put('c', 3);
variables.put('d', 4);

So, for example, the expression

System.out.println((Integer) variables.get('c'))

will print the number 3. (This uses the automatic boxing and unboxing features of Java 1.5, but not generics. We could implement the lookup table with a Hashtable<Character, Integer> but since we haven't used this in labs or assignments, we'll stick to the old form for now.)

The Expression class looks like this.

public abstract class Expression {
    public abstract void accept(Visitor v);
}

Operations on expressions are performed by visitors, which must all implement the following interface.

public interface Visitor {
    public abstract void visit(Constant c);
    public abstract void visit(Addition a);
    public abstract void visit(Variable v);
    public abstract void visit(Multiplication m);
}

Class Expression will have four effective subclasses, representing constants, variables, sums and product of two expressions. Two of these, class Constant and class Variable, have been implemented:

public class Constant extends Expression {

    int value;

    public Constant(int v) { value = v; }

    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

and

public class Variable extends Expression {

    char name;

    public Variable(char c ) { name = v; }

    public void accept(Visitor visitor) {
    visitor.visit(this);
   }
}

In the class Variable, the field name represents the variable name (like x or y), the constructor is used to initialise it, and the accept method implements the Visitor call.

(a) The Variable implementation is not perfect. How this implementation may be improved to better express the property that the name of the Variable object must stay the same during the object life time? Include only the changed parts.

[1 mark]

Solution:

This is a small design problem. The modification should ensure that the value of name must not change after the instantiation. The simplest way to achieve this is to modify the code as follows:

final char name;
public Variable (final char c) { name = c; }

But a more "traditional" approach to make name private and supply the standard get and set methods, would also suffice. Both answers deserved 1 point.

(b) Write class Multiplication, which inherits from class Expression. Note the following:

[2 marks]

Solution:

public class Multiplication extends Expression {

    Expression left;
    Expression right;

    public Multiplication(Expression l, Expression r) {
        this.left = l;
	this.right = r;
    }

    public void accept(Visitor v) {
        v.visit(this);
    }
}

This part was done correctly by the majority of students, partly because two of the hierarchy classes have already been implemented above. They allowed to see the pattern even if one has forgotten the actual details. Perhaps, it was therefore easier than last year.

(Ian's note from the last year still relevant): Many students gave the Expression arguments (l, r above) a nice identifier (name), but then gave the field(which is part of the public interface of the class) a single-letter identifier. This is the wrong way round. The class interface needs to be carefully designed, while method arguments and locals can have single-letter identifiers without damaging usability and readability. I didn't take marks off for this, which is lucky for many of you. I will take marks off in the final exam, so be warned!

(b) Write class Substituter, which traverses a tree, finds nodes which are instances of Variable class and have a given name, and substitutes a given expression in place of every such variable. Note the following:

[5 marks]

Solution:

Surprisingly or not (perhaps not too surprising given the amount time spent on counting a particular utterance during the lectures), this turned out to be a difficult question for many. Despite all helping information and hints, not everybody understood the meaning of implementing the Visitor interface, where the interface itself is defined (see the beginning of the Question). If a class implements an interface, it means that every method declared there must be implemented, which in our case means implementing (providing the body of) every visit method. Getting only this point right (and given the overall dismal handling of this question) would bring 2 points already. Getting the idea that you have to propagate the visitor down to the leaf nodes (which are Constant or Variable objects), such that the visit(Addition a) and visit(Multiplication m) method should contain a.left.accept(this) and a.right.accept(this) calls to achieve this, would demonstrate an impressive prowess on the protagonist's part and bring another 1.5 points. Finally, how to implement the visit(Variable v) method? The idea of it was understood by many students, though the implementation varied. Nobody (or may be just one student, if I remember correctly) used expr.clone() instead of just reference to expr, when reassigning the value of v. Why clone() is better? It is better if different Variable leaf nodes with the same name have different object references for expr fields (even if these objects are equal). Getting this point right (even without clone()) would bring another 1.5 points. The actual marks came out as partial sums of the above terms, and I was most generous and accommodating in calculating these figures.

Here is the sample solution:

public class Substituter implements  Visitor {

    public Substituter(char t, Expression e) {
        
        this.target = t;
        this.expr = e;
    }

    public void visit(Constant c) {
        
        // do nothing
    }

    public void visit(Addition a) {
		
        a.left.accept(this);
        a.right.accept(this);
    }

    public void visit(Multiplication m) {
		
        m.left.accept(this);
        m.right.accept(this);
    }

    public void visit(Variable v) {
		
        if (v.name == target) v = expr.clone();
    }
}

Thus, if matching the target, the reference v is being assigned to an Expression type object, which is legal since Variable is Expression.



Question 3 [7 marks]

In this question you have to write a JUnit test class (test code) for a Java class (production code).The Java class Point defines two constructors for creating an instance of this class, and several methods which can be called on such instances.

public class Point {

    private double x;
    private double y;
 
    /** constructor for the (0,0) */
    public Point() { ... }
 
    /** regular constructor */
    public Point(double x, double y) { ... }
 
    /** point in coordinates relative to the point p
     * (the centre of coordinate frame moved to p) */
    public Point relativeTo(Point p) { ... }
 
    /** point moved on the vector v */
    public Point movedOn(PlanarVector v) { ... }
 
    /** standard getter methods for point coordinates */
    public double getX() { ... }
    public double getY() { ... }
 
    /** equals test for this and Point r */
    public boolean equals(Object o) { ... }

    ... ... ... 
  
    /** distance from this Point to another Point p */
    public double distance(Point p) { ... }
 
    public String toString() {
  
        return "Point (" + x + "," + y + ")";
    }
}

(a) The test code utilising the JUnit framework will contain several test methods and, possibly, fixture methods: setUp() and tearDown(). Explain the usefulness of the fixture methods, and how many times each of them (setUp() and tearDown()) is called during the test run of the class which contain them.

[1 mark]

Solution:

This question tests knowledge of the concept. The fixture allows to reuse the code (like variable instantiation and resetting, stream opening and closing etc) used in every test method, such that the test methods cannot affect each other by perturbing the test environment (value of global variables, state of objects etc), and can be run independently. The fixture methods are called as many times as there are test methods in the test class; the setUp() is called before the body of the test method is executed, and tearDown() is called after the execution is finished.

This is quite a basic fact you should know from the (very small) JUnit "theory". Many students displayed compelling ignorance regarding the subject.

(b) What assert method will you use to test the distance() method given that it returns the double value.

[1 mark]

Solution:

Similarly to the part (a), you should have known what assert methods the framework has, and for what test each of them can be applied. Since we have to test the equality of two floating type values, the most appropriate (the only suitable) method is, of course,

assertEquals(String message, double expected, double actual, double tolerance)

Students who answered with assertEquals() without the last parameter tolerance, were awarded 0.5 point.

(c) What factors determine how many assert calls you put into a test method.

[1 mark]

Solution:

This depends on the nature of the test, of course. Here, it was implied that we meant testing the Point class, and thus the methods for testing were equals(), distance etc. If we are testing the creation of an object, then the assertNotNull() call may be included in the testPoint() method as many times as there are different constructors in the class. For the testDistance() method and the like, we should include as many assert calls as there are equivalence classes and boundary cases in which the input data (here, Points created with different constructors, equal Points etc) can be broken into.

Every reasonable answer along those lines was properly rewarded. But many papers contained blanks.

(d) Write a JUnit class TestPoint for testing both constructors, and methods relativeTo(p), equals(o) and distance(p). Each method in the test code must follow the naming pattern testSmth() (you may not test the method moveOn(v) and the getter methods getX() and getY()). You can assume that the Assert class is imported. What class from the JUnit framework will the TestPoint extend? Each of the test methods may contain only one assert method call.

[4 mark]

Solution:

First, here is the code.

public class TestPoint extends TestCase {
 
    private Point p, p1, p2, p3;
 
    public TestPoint(String name) {
        super(name);
    }

    // Set up for Point test 
    public void setUp() {
        p  = new Point();
        p1 = new Point(1, 1);
        p2 = new Point(1, 2);
        p3 = new Point(-2, 7);
    }

    // Tear Down for Point test
    public void tearDown() {
	    p  = null;
	    p1 = null;
	    p2 = null;
	    p3 = null;
    }
    
    // testing both constrictors at once
    public void testPoint() {

        Assert.assertNotNull("What?! no points!?", p1);
        Assert.assertNotNull("What?! no points!?", p);
    }

    // testing the equality of points
    public void testEquals() {

        Assert.assertEquals("Two equal objects which aren't!", p3, 
                                  new Point(-2, 7));
        Assert.assertEquals(p, new Point());
        Assert.assertEquals(p1, new Point(p1.getX(), p1.getY()));
    }

    // testing relativeTo method (Point in a shifted coordinate frame)
    public void testRealativeTo() {
        
        Assert.assertEquals("Shift and get the same, no?!",
                                p2.relativeTo(p1), new Point(0, 1));
    }

    // testing distance
    public void testDistance() {
        Assert.assertEquals((p3.distance(p3), 0.0, 0.001);
        Assert.assertEquals((p2.distance(p1), p1.distance(p2), 0.001);
        Assert.assertEquals(p1.distance(p2), 
                            p1.relativeTo(p2).distance(p), 0.001);

        ... ... /* more testEquals */ ... ...

}

Generally, this question was answered most poorly, though it should have been quite simple since it only required application of simple and well defined JUnit prescriptions for writing the test cases. You had to rely on either your memory, or scribbles on that A4 paper with notes on both sides. Whichever way, the results were fairly unimpressive. Many students did not even produce the class structure and its major features — the test methods. Providing the class definitions and making it to extend the testCase alone would earn 1.5 points. Inclusion of two or three test methods even without correctly named assert calls (but showing the understanding of what the test methods are), would bring 2 or 2.5 points depending on the level of detail. Correct naming of assert calls, defining the setUp() method, and including correct test data, would result if the maximum or close to it mark of 4. Only few students have actually achieved this.



Question 4 [10 marks]

This question is about the PSP. A student has completed a PSP Project Plan Summary form for Program #2 and now starts working on Program #3.

Fill in the ‘Plan’ column of the PSP Project Plan Summary form based on a size estimate of 60 lines of code with maximum of 70 and minimum of 50. Take all other plan data from the completed form for Program #2.

The student takes 24 minutes to complete the Planning phase, 36 minutes to complete the Design phase, 24 minutes to complete the Code phase, 24 minutes to complete the Compile phase, 96 minutes to complete the Test phase, and 24 minutes to complete the Postmortem phase.

The student injects 7 defects in the Design phase, 9 in the Code phase and 4 in the Test phase.

The student removes 2 defects in the Code phase, 2 in the Compile phase and 16 in the Test phase.

The finished program is 40 lines of code.

Record all this information on the form.

Now complete the rest of the form: all totals in the ‘Actual’ column, plus everything in the ‘To Date’ and ‘To Date %’ columns.

You do not have to fill in the ‘greyed-out’ parts of the form.

(Note that the numbers have been carefully chosen so that all the results come out as simple round numbers. You do not need a calculator.)

Here is the student's PSP Project Plan Summary form for Program #2, with all details completed.

StudentA. Student Date1/5
ProgramAverage Program #1
InstructorA. Khorev LanguageJava
SummaryPlanActualTo Date
Minutes/LOC 2.04.03.0
LOC/Hour 301520
Program Size (LOC):
Total new & changed 504080
Maximum size 60
Minimum size 40
Time in phase (min) PlanActualTo DateTo Date %
Planning 15122410%
Design 58125%
Code 40286025%
Compile 10162410%
Test 10889640%
Postmortem 2082410%
Total 100160240100%
Maximum Time 120
Minimum Time 80
Defects Injected ActualTo DateTo Date %
Planning
Design 4525%
Code 81155%
Compile 2210
Test 1210%
Total 1520100%
Defects Removed ActualTo DateTo Date %
Planning
Design
Code 3420%
Compile 7840%
Test 5840%
Total 1520100%

Here is a new PSP Project Plan Summary form for Program #3 that you have to complete using data taken from the form for Program #2 and the description of events above.

Solution:

The only subtlety was calculating the "Minutes/LOC", where you had to take into account that this was 3rd program and its actual Minutes/LOC values was 6.0 (40 lines of code were written during 240 minutes), while two previous programs produced average value for Minutes/LOC 3.0; therefore, the updated value of Minutes/LOC after the third inroad into coding should have been calculated as follows: (3.0 * 2 + 6.0) / 3 = 4.0. No need to use calculator, all the numbers are round and cute. Many students got this right, but not all. Few students performed badly in Q4 (less than 5 points). For many students, this question was a saver, allowing them to achieve decent (or, at least pass) result, despite the sum for the first three question was relatively low.

StudentA. Student> Date2/5
ProgramMoreThan Average Program #3
InstructorI. Barnes LanguageJava
SummaryPlanActualTo Date
Minutes/LOC 3.06.04.0
LOC/Hour 201015
Program Size (LOC):
Total new & changed 6040120
Maximum size 70
Minimum size 40
Time in phase (min) PlanActualTo DateTo Date %
Planning 18244810%
Design 9364810%
Code 45369620%
Compile 18244810%
Test 729619240%
Postmortem 18244810%
Total 180240480100%
Maximum Time 210
Minimum Time 150
Defects Injected ActualTo DateTo Date %
Planning
Design 71230%
Code 92050%
Compile 025%
Test 4615%
Total 2040100%
Defects Removed ActualTo DateTo Date %
Planning
Design 000%
Code 2615%
Compile 21025%
Test 162460%
Total 2040100%
____________________________________________________

[ANU] [DCS] [COMP2100/2500] [Description] [Schedule] [Lectures] [Labs] [Homework] [Assignments] [COMP2500] [Assessment] [PSP] [Java] [Reading] [Help]

____________________________________________________

Copyright © 2006, Alexei Khorev, The Australian National University
Version 2006.2, Friday, 2 June 2006, 10:14:35 +1000
Feedback & Queries to comp2100@cs.anu.edu.au