Homework 5: Refactoring in Eclipse and Encapsulation of Graphics Code
To Deliver: Release 7.0
To Download:
Due date for submission: Nov 4, at 5 AM
Drop out date: Nov 6, at 5 AM
"All problems in computer science can be solved by another level of indirection" David Wheeler
Motivation
We discussed refactoring as a necessary step in test driven design to achieve a good quality of code. The key observation was that a series of small changes where individual steps are of low complexity and possibly well supported by an IDE like Eclipse can be performed to obtain a cleaner and clearer coded base without introducing errors in this transformation. Refactoring is a transformation of code that does not introduce new functionality or does not change observable behavior of a program.
The goal of this homework is to get more experience in refactoring. To make this exercise worthwhile, we will use it to localize and encapsulate access to graphics in the maze program.
On an Android platform, java.awt and java.swing packages do not exist. So we will need to replace those by some corresponding Android-supported packages.
In order to port our existing maze project to Android, we will:
- redesign and recode the user interface (next Project assignment 5), which will make MazeApplication.java obsolete for our new Android app. It will also move all graphical UI functionality away from Maze.java and its viewers into a new UI with screens and a switching between screens via message passing (Android intents) .
- recode the graphics part when moving falstad/*.java classes to the AMaze Android project (Project assignment 5)
Note that this is the topic of the next project assignment and homework 5 is a preparation for this step.
Let's check a list of classes that have the AWT problem:
- MazeApplication.java: This class will not be used in an Android app. So we need not change anything here.
- SimpleKeyListener.java:This class will not be used in an Android app. So we need not change anything here.
- Maze.java imports java.awt.* to basically handle events in keydown() and to have the MazePanel as an attribute. This class needs to be considered.
- Viewer interface imports awt because methods of its implementing classes operate with a graphics objects. This needs to be considered.
- DefaultViewer imports jawa.awt.Graphics just because methods of its subclasses operate with a graphics objects. This class needs to be considered together with its subclasses FirstPersonDrawer and MapDrawer.
- FirstPersonDrawer.java imports java.awt.Color, java.awt.Graphics, java.awt.Point; This class needs to be considered!
- MapDrawer.java imports java.awt.Color, java.awt.Graphics; This class needs to be considered! HINT: One can encapsulate Colors in MazePanel and have a getColor method return an Object to obscure that a Color is returned.
- MazeView.java imports awt classes. It will become obselete in Android such that changes should only be a consequence of changing the Viewer interface.
- RangeSet.java:import java.awt.Point; This class needs to be considered! HINT: Point is actually misused here and replacing it by something else is the easiest fix.
- Seg.java:import java.awt.Color; This class needs to be considered!
To facilitate the graphics part, we isolate the graphics as much as we can into a single class and move all functionality that requires objects from AWT into this class. For instance the buffer image, fonts, graphics object and so forth will be attributes of this class such that other existing classes in falstad call methods for graphics be calling such methods on this wrapper object. Do we need a new class for this? May be not as the MazePanel class already wraps the AWT Panel. Let's extend the MazePanel as a graphics wrapper class.
The wrapper provides its functionality by delegation to its internal attributes like the buffer image. This means to implement this one simply needs to know which methods to call inside the wrapper class.
In the ordinary Java environment, this will simply take place by using existing functionality of AWT entities.
So we basically move existing functionality around, we need to relocate methods and adjust parameter types as necessary.
If you manage to get this right, you will be able to move existing classes towards Android such that only the refined MazePanel class will require a reimplementation in the new Android environment
to work as the backend behind a newly designed UI.
The benefit of the graphics wrapper is that you can do all necessary adjustment within a single encapsulated class such that you can test the functionality locally and then use a working version of the graphics wrapper on Android to make your maze code work in that environment.
Of course existing test classes are still supposed to work (possibly after marginal adjustments).
Requirements
Add new methods to the MazePanel class to support necessary graphics methods (like drawing a line or a polygon).
Exercise eclipse methods for refactoring to achieve this goal.
Eliminate import statements for awt and swing packages from certain classes (see check list above) and move graphics methods to the MazePanel class.
To do list:
- Check supported refactoring functionality in Eclipse (Eclipse->Refactor pull down menu). Work on a copy of some classes first to see how functions work, e.g. how to rename variables and methods, how to extract methods, how to push methods up and down the inheritance hierarchy, how to extract an interface and so on. Use those files to figure out how things work and then delete those damaged copies.
- Transform your code base in a sequence of steps to move functionality for graphics into the MazePanel class and have that class provide corresponding functionality on its own such that classes listed as 3-10 (in bold) above become dependent only on your MazePanel class and no longer on AWT objects. Also read code carefully and fix inappropriate usage of AWT objects: there is RangeSet.intersect(Point p) which uses the Point class but not for graphics purposes. For this case, check the code and replace Point by something else that also does the job but does not misuse a graphics class for that.
- Clean up import statements in your classes.
- Update your Java maze project in your svn repository.
- Produce a tag release 7.0
Grading:
You will receive points
- if Viewer, FirstPersonDrawer, MapDrawer, RangeSet and Seg classes do not directly rely on AWT any more.
- if your MazePanel class encapsulates access to AWT objects like an Image, Fonts, Colors and so forth. (Hint the graphics wrapper is a lightweight class of about 100 lines of code in my solution.)
- if your maze application works with the refined MazePanel class such that one can play the Maze game as before
- if your junit test cases operate with no errors or failures