General Modularity Example Module Projects & Files Commands & Scripting
Windows Menus Charts Tables Buttons & tools
Trees and Taxa Characters & Models Documentation General Utilities
Modular architecture Modules: subclasses of MesquiteModule Modules employing other modules
Duty Classes Writing modules Documentation for particular modules Packages of Modules
Also: User's introduction to modularity class MesquiteModule Example Module

Introduction to Mesquite's modular architecture

(updated August 2005)

The Mesquite system includes the basic class libraries (primarily in the package mesquite.lib), and a series of modules (subclasses of mesquite.lib.MesquiteModule). While the basic library includes many classes that serve as windows, user interface objects, and so on, perhaps the dominant theme of Mesquite's architecture is the interaction of the modules. The modules serve as the primary organizers in Mesquite. The modules may not themselves perform all calculations and control all user interface elements, but when they don't, they at least supervise the objects that do. This page has three parts:

A simple introduction to Mesquite modularity, intended for users, is given at How Mesquite works.


Modules and the Employee Tree

All modules are subclasses of the class MesquiteModule. The core application that gets Mesquite up and running is itself a subclass of MesquiteModule, and thus the core application is also a module. It is mesquite.Mesquite, a subclass of MesquiteTrunk.

When the core Mesquite module (the "trunk") starts up, it finds all of the available modules by looking into the subdirectories of the Mesquite_Folder/mesquite directory. (To be found, a module must have the same name as the directory in which it resides, e.g. BeanCounter.class would have to be within the a directory "BeanCounter".) Mesquite temporarily instantiates each of the MesquiteModule classes. From each, it gathers information, including its name and the precise subclass of MesquiteModule it represents. This information is stored in a special vector.

Modules are "hired" by other modules as employees to perform certain tasks. Typically a module will decide whether to hire a prospective employee module according to the particular subclass the module belongs to. These subclasses are referred to as duty classes, since each subclass represents a particular job or duty and employee could perform. For instance, one subclass of MesquiteModule is DrawTree, which extends the base class MesquiteModule in having a method createTreeDrawing(), which returns a special tree drawing object. The module responsible for the tree window hires a module that coordinates tree drawing, which in turn looks for a DrawTree module. There may be multiple DrawTree modules available -- one may make square trees ("phenograms"), another diagonal trees ("cladograms"), another circular trees, another may plot the nodes of the tree in a three dimensional space, and so on. The fact that a module is a subclass of DrawTree guarantees to any employer that it will perform a task in a predictable way (that is, it will have the appropriate methods). The coordinating module could choose any of these to hire. The DrawTree module chosen in turn might hire a module to help it assign node locations.

An example — For instance, at one point while Mesquite is running, the employee tree for the basic tree window module might look as follows:

Basic Tree Window Maker
  Basic Tree Draw Coordinator
      Diagonal tree
          Node Locations (standard)
      Basic Draw Taxon Names
  Stored Trees
  Trace Character
      Stored Characters
      Parsimony Ancestral States
          Parsimony Irreversible
          Parsimony Linear
          Parsimony Ordered
          Parsimony Unordered
      Shade states

In this example, the module Basic Tree Window Maker has three employees: Basic Tree Draw Coordinator, Stored Trees, and Trace Character. The first takes care of drawing the tree, the second supplies a tree for the tree window. The third, Trace Character, is active because the user has requested it to trace a character on the tree. In response to the request, the tree window module hired it as an employee. The Basic Tree Draw Coordinator has two employees, Diagonal Tree (which draws "cladogram" shaped trees) and Basic Draw Taxon Names. Trace Character has three employees, Stored Characters (which supplies characters from a data matrix in a file), Parsimony Ancestral States (which reconstructs states at the nodes), and Shade states (which colors the branches to reflect the reconstructed states).

Each module has only one employer. Modules therefore cooperate in a tree-like arrangement of employees. The root or trunk of the whole tree is the core Mesquite class which is a subclass of MesquiteTrunk which is a subclass of MesquiteModule. Each instance of a module is a branch in this tree of employees.

Although modules claim to perform duties such as tree drawing, the module classes themselves do not need to perform these duties: the tree drawing, phylogenetic calculations and so forth can and probably should generally be performed by non-module objects that the modules instantiate. Thus the modules primarily serve to provide the lines of communication and the organization of the user interface, and hence serve as the administrative scaffolding to the system. (Actually, at present many key calculations are done within the module classes, but that might best be changed for future efforts in parallelization.)

Politeness is expected but not enforced. That is, a module is expected to call the methods of its employees, but only in a few cases should it call the methods of its employer or modules that aren't its employees. Modules can and do call others' methods for information (e.g. get... methods), however, but in general they should not call methods to manipulate their employers, or to manipulate employees of other modules (e.g. set... methods). Exceptions to this include the notifying methods (e.g. parametersChanged) which indirectly call an employer's methods so as to manipulate the employer's behaviour.

Typically there will be alternative modules to perform any given task, and thus if some modules fire the employees they have and hire some alternatives, we might arrive at the following:


Basic Tree Window Maker
  Basic Tree Draw Coordinator
      Basic Draw Taxon Names
      Circular tree
          Node Locations (circle)
  Simulated Trees
      Harding Branching
  Trace Character
      Parsimony Ancestral States
          Parsimony Irreversible
          Parsimony Linear
          Parsimony Ordered
          Parsimony Unordered
      Simulated Characters
          Simple evolve characters
          Tree of context
      Label sets

The tree drawing module is now Circular tree. The source of trees is no longer Trees from file, but now Simulate Tree, which in turn hires tree simulating modules to supply trees. Trace Character is no longer using Data Set to get data from a file, but rather is using as its character source Simulate Characters, which in turn hires modules to simulate characters evolved on the current tree. Trace Character is also using a different module, Label sets, to display the results.


Benefits of modularity

From a programmer's point of view:

From a biologist's point of view:

Often it seems that in programming, the number of features rises linearly with the number of hours of effort, while the number of bugs rises considerably more than linearly. The object-orientation combined with the multiplicative rise in possible analyses as modules are added makes Mesquite behave closer to the reverse, with the number of features rising considerably more than linearly, and the number of bugs rises linearly (gods of silicon willing), with programming effort.


Challenges of modularity

Although modularity has many benefits, it presents some considerable challenges. For instance, such a fluid system with different modules installed at different times, or with different modules in use at different times, presents many opportunities to confuse the user. In Mesquite, some of the challenges turned out to be unexpectedly easy to overcome. Other challenges appear more menacing, and it remains to be seen how well users are adapting to a modular system. Here are some of the challenges, beginning with a fairly simple one. To understand the solutions to some of these challenges, you should be aware that many Mesquite objects accept text strings as commands, and indeed much of the user interface interacts with the objects by sending such commands to them.


© W. Maddison & D. Maddison 1999-2005