CPSC 329 Software Development Fall 2017

CPSC 329 Lab 10: Encapsulate What Varies

This lab is about designing for flexibility - in particular, encapsulating what varies.

Objectives

Successful completion of this lab means that you:

Collaboration

Work in pairs (and one group of three) to complete this lab. Only one person needs to carry out the steps in the lab but everyone in the group should make sure they understand what is going on. There is no limit on collaboration with others, but you need to make sure that you understand for yourself how (and why) to do things.

Due Date and Deliverables

due Tue Nov 21 at the start of class

One handin per group.

To hand in the lab, create a handin tag as directed. Make sure the names of your group members are in the commit comment.


Setup

Create a project for this lab:

Provided Code and Files

The solver package contains implementations of three maze solving algorithms (depth-first search, breadth-first search, and best-first search); the main package contains the corresponding main programs to run them. The remaining packages provide support code - a parser to read maze description files, a maze data structure, a user interface - that you shouldn't need to work with directly (unless you get to the "If You Have Time" section). The details and tradeoffs of the different maze solving techniques are not the focus of this assignment (so don't worry if you aren't familiar with them), but if you are curious, you can try running each of the main programs to get a sense of how they differ. (When prompted for a maze filename, enter the name of one of the provided mazes.)


Encapsulating What Varies

Identifying Commonalities

Refactoring Code - Composition

Start by making sure you understand the delegation version of the ThingFilter example from class - the class ThingFilter contains the common code, with the interface Criteria and its implementing classes containing the parts that vary.

Now, implement that structure for the maze solver:

Refactoring Code - Subclasses

The composition version of ThingFilter was introduced as a way to avoid repeating the whole filter method for each version of the filter. However, it is possible to use subclasses and still avoid repeating the common parts of the filter method: create abstract placeholder methods for the parts that vary, then implement those methods in the subclasses. For ThingFilter, this would look like the following:

  public abstract class ThingFilter {

    public List filter ( List things ) {
      List matches = new ArrayList();
      for ( Thing thing : things ) {
        if ( matches(thing) ) {
	  matches.add(thing);
	}
      }
      return matches;
    }

    protected abstract boolean matches ( Thing thing );
}

Note how this is similar to the composition version: the units of encapsulation (in this case, the matches method) are the same, it's just a question of whether the method body is in another class entirely or a subclass.

Do this for the maze solver:

If You Have Time

(optional) If you have time, examine the MazeSolverGUI class, which keeps track of the status of each room (discovered, explored, or otherwise) and handles the program's GUI display. Imagine that you also wanted to offer a text-only display as an option. The text display would draw a text representation of the maze (similar to the maze file format - use x for walls, . for open rooms, d for discovered rooms, e for explored rooms, s for the start, g for the goal, and * for rooms on the solution path) when the path is shown, and should print out just the row and column and new status of each room that is marked as discovered or explored (instead of drawing the whole maze).

What is common to the GUI and text-based interfaces? What varies? How can you reorganize the code to encapsulate what varies? Answer the questions, then implement the solution. Note that the key thing here is the design - you do not need to fully implement every method of the text interface if the method headers are present and it is clear what code would go where.


Handin


Valid HTML 4.01!