Implementation Notes

We chose to write Laj in the Java programming language because Java provides a convenient way to produce interactive graphical interfaces that can run on a variety of computer platforms and across the world-wide web. Java is an object-oriented language, so the program code is divided into units called classes, which are like templates for creating objects. Usually the code for each class is stored in a separate file, and contains some data variables and some functions, or methods, that operate on these variables.

Laj and its sister programs, Lat and Maj, are all built using the same package of underlying classes for reading data, displaying output, etc. But they have different versions of some of the higher-level classes -- for example, the main class representing each program, and the outer wrapper that starts it. For additional flexibility, Laj can be run either as an applet over the web, or as a stand-alone program. These two modes require different ways of supplying input parameters like the names of data files, so they use different wrapper classes for startup. A variable in the main class records which mode is being used, so that lower-level objects can behave appropriately.

The class structure of Laj and Maj is based on the model-view-controller paradigm. Tasks are divided in a fairly modular fashion among several groups of classes: those that read and store the various types of input data, those that display the graphical user interface, and those that record and maintain the current state of the user's choices (e.g., the current zoom region). There are also some miscellaneous utility classes, e.g., for reporting errors. Note that Lat uses a simpler paradigm, since it does not have an interactive interface.

Another characteristic of object-oriented programming is inheritance: if two classes are similar, one can be declared as a subclass of the other, inherit most of the other class's variables and methods automatically, and just make a few adjustments as needed. This avoids having multiple copies of the same common code, and generally makes the program easier to understand and maintain. The Laj/Maj/Lat programs use inheritance to manage similar classes both within and between programs. For example, several of Maj's classes inherit from their counterparts in Laj; this is better than maintaining separate classes with large chunks of identical code, and often simpler than trying to make a single class that can handle the requirements of both programs.

The ZoomPane class presents another example of inheritance: it is an abstract "skeleton" that provides the basic functionality for all of the white panels in Laj and Maj. Any subclass of ZoomPane (such as PlotPane, FeaturePane, AnnotationPane, or RulerPane) inherits the ability to zoom all of these panels when the user drags with the left mouse button, and to supply crosshairs when the user presses the right button. ZoomPane declares prototypes for additional methods to draw the contents of the panel, to respond to mouse clicks, and to display the current position of the mouse pointer, but it does not actually implement them. Each subclass is responsible for implementing these methods in a manner appropriate for the particular type of data it displays.

The PlotPane class (which inherits from ZoomPane) can display either a dot-plot or a percent-identity plot (PIP), depending on one of the arguments to its constructor method. This could have been handled by using further inheritance to make separate classes instead, say DotPane and PipPane, but it was decided to use a single class because the differences needed for the two types of plots were fairly minor and scattered through several methods.

Sometimes it is hard to say whether two or more classes are similar enough that they should inherit from each other. One case where Laj does not use inheritance, but perhaps should, is the set of data classes for storing color underlays, hyperlinked annotations, and sequence features like exons and repeats. Each of these classes stores the endpoints of the associated sequence region, together with a label and some additional fields that tend to appear in several of these classes, but not all. Perhaps this situation could be better handled by inheritance, or even by having a single, multi-faceted class like PlotPane, where objects representing the various types of data would use different subsets of the available fields. However, class structure reorganizations like this can require considerable care and effort. Fortunately, as long as the program works correctly, borderline organizational decisions like these are rarely critical.

Cathy Riemer, January 2001