cs205: engineering software?
(none)
20 September 2010

Sample Exam 1

Specifying Procedures

1. (10) Muddle B. Fuddle wants to add a deleteName method to the StringTable class:
public class StringTable 
{
    // overview: StringTable is a set of <String, double> entries,
    //    where the String values are unique keys.  A typical StringTable
    //    is {<s0: d0>, <s1: d1>, ... }.
    //

    ...
}
Muddle is planning to use a Vector of String, value record pairs to represent his StringTable. He suggests this specification:
public boolean deleteName (String name)
   // REQUIRES: The parameter name is not null.
   // EFFECTS: Goes through the entries in the elements Vector, and removes
   //     the one whose key matches name.
   
Identify at least three important problems with Muddle's specification and explain why each problem is bad.

2. (10) Write a good specification for the deleteName method.

Data Abstractions

For these questions, we will use the WDGraph data abstraction specified below:
public class WDGraph {
   // OVERVIEW: 
   //      A WDGraph is a mutable type that represents a weighted,
   //      directed graph. 
   //
   //      It consists of nodes that are named by Strings, and edges
   //      with non-zero integer weights that connect a pair of nodes.
   //      For any two nodes, a and b, there is at most one edge from
   //      a to b and one edge from b to a.  
   //
   //      A typical Graph is: < nodes, edges >
   //       where
   //         nodes = { n1, n2, ..., nm }
   //       and 
   //         edges = { <from_1, to_1, weight_1>, ..., <from_n, to_n, weight_n> }
   //
   //      For example,
   //	      nodes = { "Charlottesville", "Dulles", "Richmond" }
   //         edges = { <"Charlottesville", "Dulles", 119>,
   //                   <"Dulles", "Charlottesville", 139>,
   //                   <"Charlottesville", "Richmond", 89>,
   //                   <"Richmond", "Dulles", 79> }
   //      could represent the flights and fares between
   //      Charlottesville, Dulles and Richmond (e.g., you can fly from
   //      Richmond to Dulles for $79, but there is no direct flight from
   //      Richmond to Charlottesville.

   // Creator
   public WDGraph () 
      // EFFECTS: Initializes this to a graph
      //      with no nodes or edges: < {}, {} >.

   // Mutators
   public void addNode (String node) throws DuplicateNodeException
      // MODIFIES: this
      // EFFECTS: If node is the name of a node in this.nodes,
      //    throws the DuplicateNode exception.  Otherwise, 
      //    adds a node named name to this:
      //        this_post = < this_pre.nodes U { node }, this_pre.edges >

   public void addEdge (String fnode, String tnode, int weight) 
      thows NoNodeException, DuplicateEdgeException, InvalidWeightException
      // MODIFIES: this
      // EFFECTS: If fnode or tnode is not the name of a node in
      //    this.nodes, throws NoNodeException.  If this already has
      //    an edge between fnode and tnode, throws
      //    DuplicateEdgeException.  If weight is 0, throws
      //    InvalidWeightException.  Otherwise, adds an edge to this
      //    from fnode to tnode with weight:
      //       this_post = < this_pre.nodes, 
      //                     this_pre.edges U { <fnode, tnode, weight> } >
      
   // Observers
   public boolean hasNode (String node)
      // EFFECTS: Returns true iff node is a node in this.

   public boolean hasEdge (String fnode, String tnode)
       throws NoNodeException
      // EFFECTS: If fnode or tnode is not the name of a node in
      //    this.nodes, throws NoNodeException.  Otherwise, returns
      //    true iff there is an edge from fnode to tnode.
}
3. (7) As specified above, is WDGraph likely to be a useful abstraction? If so, explain briefly an application that could use it. If not, explain what methods must be changed or added to make it useful.

4. (8) As specified, WDGraph is a mutable type. Explain what changes would be necessary to make WDGraph an immutable type instead, and identify at least one good reason why we might prefer the immutable version.

5. (15) Suppose we decide to implement WDGraph using this rep:

   // Rep:
   String nodes[]; 
   int edges[][];

   // Abstraction Function:

   // AF (c) = < nodes, edges > where
   //          nodes = { c.nodes[i] | 0 < i <= c.nodes.length }
   //          edges = { < c.nodes[fi], c.nodes[ti], c.edges[fi][ti] > |
   //                    0 < fi <= c.nodes.length,
   //                    0 < ti <= c.nodes.length 
   //                    where c.edges[fi][ti] != 0
   //
   // For example, the representation below would represent the flight
   // graph described in the overview:
   //    
   //     c.nodes = [ "Charlottesville", "Dulles", "Richmond" ]
   //     c.edges = [ [   0, 119, 89],
   //                 [ 139,   0, 0 ],
   //                 [   0,  79, 0 ]
   //

The hasEdge method is implemented as:

   private int lookupNode (String node) throws NoNodeException
      // EFFECTS: If node is a node in this.nodes, returns the
      //    index such that this.nodes[result].equals (node).
      //    Otherwise, throws NoNodeException.

      //   (Note that lookupNode is a private method.  Hence, it is okay that we
      //    have specified it using the concrete representation instead of in
      //    terms of the abstraction.)

   public boolean hasEdge (String fnode, String tnode) 
      throws NoNodeException {
      return (edges[lookupNode (fnode)][lookupNode (tnode)] != 0);
   }
What rep invariant would be necessary to make this implementation correct?

Testing

6. (10) What would be a reasonable set of black box test cases to the addNode method?

7. (10) Suppose we implement addNode as below. What additional glass box test cases (if any) are necessary?

      public void addNode (String node) throws DuplicateNodeException {
         try {
	    lookupNode (node);
	    throw new DuplicateNodeException (node);
	 } catch (NoNodeException e) {
	    String [] oldnodes = nodes;
	    nodes = new String [oldnodes.length + 1];

	    for (int i = 0; i < oldnodes.length; i++) {
	       nodes[i] = oldnodes[i]; 
	    }
	    nodes[oldnodes.length] = node;
	}
     }	
8. (10) What is the serious flaw with our addNode implementation?