Assignment 4

Due Saturday, December 5th, 2009 11:55PM

  1. (10 points)

    Apply the Replace Method with Method Object refactoring to the following code.

    public int hash(String s) {
    	int temp = 0;
    	for (char c : s.toCharArray())
    	{
    		temp ^= (int)c;
    		temp = (temp << 25) | (temp >>> 7);
    	}
    	return temp;
    }
    			
  2. (10 points)

    Examine the following snippet of code.

    public int foo(boolean cond, int a, int b) {
    	boolean answer = not(cond);
    	if (answer) {
    		return a;
    	} else {
    		return b;
    	}
    }
    
    private boolean not(boolean b) {
    	if (b==true)
    		return false;
    	else
    		return true;
    }
    			
    1. (5 points)

      What is wrong with this code? What refactoring would you use to fix it?

    2. (5 points)

      Show the code which you would have after you apply the refactoring.

  3. (15 points)

    Consider the following code.

    class Cat {
    	private String name;
    	private Color furColor;
    	// assume appropriate getters and setters here
    	public void feed(CatFood food) { ... }; // assume some method body for ...
    	public void nap(double hours) { ... };
    ]			
    
    class CatOwner extends Cat {
    	private String ownerName;
    	// assume appropriate getters and setters here
    	public void petCat() { ... };
    	public void trainCat(Task task) throws TrainFailureException {
    		throw new TrainFailureException("It's a cat.");
    	}
    }
    
    // for example, we cause the owner to feed the cat by calling
    //     catOwner.feed(someCatFood);
    			
    1. (5 points)

      Which software design principle does this code violate? Explain.

    2. (10 points)

      Which refactoring would you use to fix this problem? Show how the code would look after you used that refactoring.

  4. (10 points)

    Suppose the source code on which you are working has two classes named A and B. The A class has a field named foo and appropriate getter and setter. An instance of B has a reference to an instance of A. A never accesses its foo field, nor does it call its getter or setter for that field. The B class accesses the foo getter and setter on occasion.

    What refactoring should be used on the above code? Describe the result of using that refactoring.

  5. (15 points)

    For each of the following scenarios, describe what design pattern should be used and briefly explain why.

    1. (5 points)

      You have a tree data structure where each node in the tree is of type Node and has a List<Node> representing its children. Each node in the tree has a number of type double. You also have a method with signature double sumTree(Node root) which sums all of the values in the tree it is provided. Assume that each Node also carries several megabytes of other data.

      You wish to obtain the sum of the squares of all of the values in this tree. You want to use the existing sumTree method but cannot afford to create a copy of the tree because of the overhead of copying the several megabytes of other data.

    2. (5 points)

      You wish to write a logging facility for your application. The logger should be able to write to several different target streams (possibly a collection of OutputStreams) and should be able to accept dynamic policies at construction time (such as ignoring messages of debug level or lower). You want the caller to be able to request that logging take place without being bothered by the details of which streams receive the message or how you make that decision.

    3. (5 points)

      You are writing a framework to describe the generation of summary reports. These reports summarize data to which you have access in an object-oriented format. You may be asked to regenerate these reports. As a result, the generation of the report cannot be invoked by a simple method call; you need to store the parameters of this method call so it can be invoked numerous times.

  6. (10 points)

    For each of the following code snippets, identify the design pattern which is being used.

    1. (2 points)
      // Note: this class is unnecessary as Collections.unmodifiableList has a similar purpose
      public class EmptyUnmodifiableStringList extends AbstractList<String> {
      	public static final EmptyUnmodifiableStringList INSTANCE = new EmptyUnmodifiableStringList();
      	public int size() { return 0; }
      	public String get(int index) { throw new IndexOutOfBoundsException(); }
      }
      					
    2. (2 points)
      public double calculateTotalDistance(DistanceMetric metric, Example rootExample)
      {
      	double sum = 0;
      	for (Example example : this.examples) {
      		sum += metric.calculateDistance(example, rootExample);
      	}
      	return sum;
      }
      					
    3. (2 points)
      /** Represents a read-only Set backed by an array. */
      public class ReadOnlyArraySet<T> extends AbstractSet<T> {
          private T[] backingArray;
          public ReadOnlyArraySet(T[] backingArray) {
          	this.backingArray = backingArray;
          }
          public int size() {
          	return this.backingArray.length;
          }
          public Iterator<T> iterator() {
          	return Arrays.asList(this.backingArray).iterator();
          }
      }
      					
    4. (2 points)
      public class ByteSkippingInputStream extends InputStream {
      	private InputStream backingStream;
      	public ByteSkippingInputStream(InputStream backingStream) {
      		this.backingStream = backingStream;
      	}
      	public int read() {
      		// throw away a byte
      		this.backingStream.read();
      		return this.backingStream.read();
      	}
      }
      					
    5. (2 points)
      HappyBuilder builder = new HappyBuilder();
      builder.setAwesome(true);
      builder.setNifty(true);
      builder.setTubular(false);
      Happpy happy = builder.make();
      
      builder.setAwesome(false);
      builder.setTubular(true);
      Happy happy2 = builder.make();
      					
  7. (12 points)

    Examine each of the following members from the Java API. For each one, identify the design pattern that the member represents and briefly explain why.

    1. (4 points)

      The MouseAdapter class.

    2. (4 points)

      The AbstractList.get(int) method.

    3. (4 points)

      The Enumeration interface.

  8. (18 points)

    For each of the following code snippets, describe which design pattern should have been used and explain why it would produce better code than that shown here.

    1. (6 points)
      public class Person {
      	private static enum State { STUDENT, FACULTY, ALUMNUS };
      	private State state;
      	private Name name;
      	private Address address;
      	// various getters, setters, other methods
      	public void sendTuitionReminder(MailSystem system) {
      		if (this.state.equals(State.STUDENT)) {
      			system.sendMail(MailTemplates.TUITION_LETTER.generate(this));
      		}
      	}
      	public void askForMoney(MailSystem system) {
      		if (this.state.equals(State.ALUMNUS)) {
      			system.sendMail(MailTemplates.DONATION_LETTER.generate(this));
      		}
      	}
      	public void sendSemesterStartLetter(MailSystem system) {
      		if (this.state.equals(State.STUDENT)) {
      			system.sendMail(MailTemplates.STUDENT_SEMESTER_START_LETTER.generate(this));
      		} else if (this.state.equals(State.FACULTY)) {
      			system.sendMail(MailTemplates.FACULTY_PREPARE_FOR_CLASSES.generate(this));
      		}
      	}
      }
      					
    2. (6 points)
      public class LeafNode {
      	private int value;
      	// appropriate property constructor, getter, and setter
      }
      public class NonLeafNode {
      	private int value;
      	private List children;
      	// appropriate property constructor, getters, and setters
      	public int[] getValues() {
      		// get all child values
      		int[][] values = new int[children.size()][];
      		int totalSize = 0;
      		for (int i=0;i<children.size();i++) {
      			Object child = values[i];
      			if (child instanceof LeafNode) {
      				values[i] = new int[]{((LeafNode)child).getValue()};
      			} else {
      				values[i] = ((NonLeafNode)child).getValues();
      			}
      			totalSize += values[i].length;
      		}
      		// serialize into a single array
      		int[] ret = new int[totalSize];
      		int k = 0; // new array index
      		for (int i=0;i<values.length;i++)
      		{
      			System.arraycopy(values[i],0,ret,k,values[i].length);
      			k+=values[i].length;
      		}
      		// finish
      		return ret;
      	}
      }
      					
    3. (6 points)
      public int performHash(Sample[] samples, int hashMode) {
      	int hash = 0;
      	for (int i=0;i<samples.length;i++) {
      		switch (hashMode) {
      			case MD5:
      				hash ^= md5hash(samples[i]);
      				break;
      			case SHA1:
      				hash ^= sha1hash(samples[i]);
      				break;
      			case SHA256:
      				hash ^= sha256hash(samples[i]);
      				break;
      			default:
      				throw new IllegalArgumentException("Invalid hash mode: " + hashMode);
      		}
      	}
      	return hash;
      }
      					

Submission Instructions

Submit your answers via WebCT. Handwritten submissions are acceptable as long as they are legible. If we cannot read your homework with a reasonable amount of effort, we will not assign credit for it. We encourage the use of diagramming applications and other such tools. Your homework must be submitted electronically; we will not accept paper copies.