18. Cleanup and Multiple Source Files

Part of CS:2820 Object Oriented Software Development Notes, Fall 2015
by Douglas W. Jones
THE UNIVERSITY OF IOWA Department of Computer Science

 

Problems with the Road Network Simulator

In our road network simulator, there are many bug messages. Some have to do with extending the simulator to more interesting models, adding stop signs, making source intersections pump out multiple vehicles instead of just one, making vehicles have an identity and current location, and so on.

But the code also contains junk left over from poorly thought out development process. It is time to clean this up! There is a global class Event which we never used! Instead, class Simulator contains an inner class for this.

Class ByName is only explicitly used inside SyntaxCheck. While it is implictly used elsewhere in lambda bindings, this class need not be global, it can be a public inner class of SyntaxCheck.

Breaking up the Source File

The code is getting large, approaching 680 lines. At some point, it would make good sense to break it into multiple source files. The Java compiler allows you to say:

[HawkId ~]$ javac File1.java File2.java

This builds a project where the source is written in multiple files. However, if you had to type all the file names every time you compiled your program, it would get very tiring. Fortunately, the Unix/Linux shells (as well as the DOS/Windows command line) provide an abbreviation in the form of a wild-card character that matches essentially anything, so you can type:

[HawkId ~]$ javac *.java
This matches any file ending with .java, and it works well for a project where there is only one application in the directory. You might, however, develop a set of files to build a highway network where, depending on which main program you used, it could be used for correctness checking or for simulation or for pretty-printing. In that case, you might want to keep a file with explicit lists of the source files to be used. Such a file is called an @argfile. Suppose you wanted to call your argfile classes. You could construct such a file as follows:
Simulator.java
RoadNetwork.java

Given that this file exists, you can compile these two source files together with the command

[HawkId ~]$ javac @classes

If the classes file gets big, it would be nice to be able to add comments to it. Unfortunately, Java does not have a standard way to put comments in @argfiles.

Breaking Out One Class

In the above example, we assumed that the classes file specified a separate source file for class Simulator. We can break this out of the original monolithic source file like this:

// Simulator.java
/**
 * Framework for discrete event simulation.
 * @author Douglas Jones
 * @version ...
 */

import java.util.PriorityQueue;

class Simulator {

	public interface Action {
		// actions contain the specific code of each event
		void trigger( float time );
	}

	... remainder of body of class ...
}

Note that our original source file had imported a large number of different classes. Of those, only class PriorityQueue is relevant to class Simulator, so that is the only import statement used in this source file.

Note also that the header comments from class Simulator have been moved up into the header comment for the file, and note that the header comments for the file include indications of authorship, version and other documentation of the provenance of this file.

Class Simulator is almost the perfect size for a single class that fits comfortably in one source file. Some of our other classes are rather small, and we will investigate splitting them out into separate packages.

The Remainder

In our example classes file, the remainder of the file aside from class Simulator was still in the file RoadNetwork.java. With the removal of class Simulator, the file RoadNetwork.java could now begin like this:

// RoadNetwork.java
/**
 * Classes that define the topology of a road network and simulate that network.
 * @author Douglas Jones
 * @version MP4?
 */

import java.util.LinkedList;
import java.util.List;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.Random;

// import Simulator;

... the remaining classes in our project

Note that the list of import statements has been shortened because of the omission of imports that were only needed in Simulator.java. Of more importance, note that Java does not permit an explicit import of class Simulator. It would have been nice if each file could explicitly reference the other files on which it depended, but Java neither requires nor permits such documentation other than in comments. So, we have included the import statement we wanted to use in a comment.