Parameters - Design Patterns
Design patterns utilized in LANDIS-II and LIME for parameters and their files.
Read-only Access to a Complete Set of Valid Parameters
How the user creates parameter files is not relevant to the scientific code in the LANDIS-II model and extensions. This code just needs to use the parameters. This access is read-only because the scientific code has no need to modify parameters during execution. The scientific code just needs a set of parameters that is complete and valid.
This concept of read-only access to a complete set of valid parameters is embodied in a design pattern used throughout the LANDIS-II core and extensions. The pattern uses interfaces. In the core, a species’ parameters is represented by the ISpecies interface, while an ecoregion’s parameters is represented by the IEcoregion interface. (Unfortunately, the pattern hasn’t been applied consistently; for example, there isn’t an IScenario interface yet.)
The set of parameters for an extension is represented by the IParameters interface. Subsets of an extension’s parameters may be represented by separate interfaces. For example, the wind extension’s IParameters interface uses the two other interfaces: IEventParameters and ISeverity.
Minimal Implementation of Parameter Interfaces
The goal of this design pattern is the simplest implementation of each parameter interface. Keeping each class to a minimum facilitates comprehension and maintenance. Examples include the Scenario, Species, and Ecoregion classes in the core, and the Parameters classes in the extensions.
These classes simply represent complete sets of valid parameters and provide read-only access to them. The classes do not contain any information about how the parameters are loaded from parameter files, or how they are validated. Other classes are responsible for reading and validating parameters.
Text File Parsers
These classes read parameters from text files. Each class is designed to read a particular set of parameters from a text file. For example, in the core, the Species.DatasetParser class reads parameters for all the species from a file.
For uniformity among parameter files, LANDIS-II text parsers are derived from a base class in the core’s utility module. This base class handles the LandisData parameter at the top of each parameter file. The base class is a generic class called Landis.TextParser<T>. The generic parameter T is the type that represents the parameters in the file, for example, an extension’s IParameters interface or the core’s Species.IDataset interface.
This LANDIS-II base class for text parsers is derived from a base class in the FLEL utility library. The FLEL base class encapsulates the functionality shared by text parsers in general, not just LANDIS-II parsers. In addition to this base class, the FLEL utility library includes supporting classes used with text parsers. These classes represent input variables, their values and associated exceptions: InputVar<T>, InputValue<T>, InputVariableException, and InputValueException.
Text parsers are responsible for checking the structure of parameter data in a file. They delegate the validation of parameter data to other classes.
Encapsulate Parameter Validation in Separate Class
The text parser and input editor for a parameter file both need to validate parameter data. To share code and avoid duplication, the validation logic is encapsulated in a separate class. By convention, these classes have names that start with “Editable” because they represent parameter data that can be edited. In the case of text parsers, the data are simply being assigned to these editable objects as parameter files are read. The CLI user actually edits the parameter files with a text editor. But in the case of input editors in LIME, the GUI user can enter and edit parameter data in any order.
It’s challenging to design an Editable class to support both a text parser and an input editor. Supporting the arbitrary order that a GUI user may edit parameters is more challenging than supporting the sequential order that a text parser reads data from a file. This challenge becomes more complex when there are dependencies among the parameters.
For example, in the species parameter file, there are numerous dependencies among the species’ age parameters: longevity, sexual maturity, minimum and maximum sprouting ages. These age parameters for a species must be valid with respect to each other; for example, none of the other age parameters can exceed longevity. The validation logic in the Species.EditableParameters class has to handle any situation where the GUI user enters a new value or edits an existing value for one of these parameters. That logic has to handle situations where another parameter has a value, and situations where it doesn’t.
A developer can build an extension without Editable classes. An extension developer is free to embed the validation logic in the text parser. This approach may be appropriate for initially exploring some ideas, or if the extension is intended for private use only. But if the developer plans to release the extension for public use, then this design pattern should be followed to facilitate the eventual development of an input editor for the extension’s parameters.
Even if the validation logic for an extension’s parameters isn’t encapsulated in a separate class, that doesn’t prevent the development of an input editor. The GUI developer who is constructing the editor will have to duplicate the validation code, which in the long run is a maintenance problem. However, the duplication is acceptable as an interim solution. It allows the GUI developer to release the input editor for the current version of the extension, while the extension developer refactors the parser to extract the validation code for the extension’s next version.
Limit GUI Dependencies to Input Editors
Although Editable classes are designed to be used by input editors for validation, these classes along with text parsers and parameter implementation classes should not have any dependencies on GUI frameworks. The LANDIS-II model and extensions don’t need to know which GUI framework that LIME and its input editors are built upon. The model and extensions are designed to be independent of how the user interface is implemented. They communicate with the user interface, whether it’s a CLI or a GUI, via the UI class in the core’s utility module. In LANDIS-II 5.1, this UI class hadn’t yet been integrated into the new PlugIns.ICore interface; it will be in LANDIS-II 6.0.
Keeping GUI dependencies out of LANDIS core and extensions is critical to support the development of input editors. The most likely situation is that the team developing an extension will not be the same team developing input editors for its parameter files. The latter requires knowledge about GUI application programming. It’s enough of a challenge for the extension team to develop the skills needed to build extensions (e.g., object-oriented concepts, C# language, IDEs and their tools). Given the complexity of GUI programming, coupled with the fact that extensions can be built without input editors, the most likely scenario is that one or two teams will emerge to develop input editors, while most other teams will focus on extension development.
Helper Method in Core for Loading Parameters
At a high-level of abstraction, the model and extensions just want to load valid parameter data from input files. Every LANDIS-II parameter file should be loaded with a helper method in the core’s utility module. This method is named Data.Load<T>. The generic parameter T is the type that represents the parameters in the file, for example, an extension’s IParameters interface or the core’s Species.IDataset interface.
Unfortunately the current documentation of that method doesn’t fully describe in detail the method’s functionality. The method is designed to handle parameter files whether they were created by the CLI user with a text editor, or by the GUI user with LIME input editors. The Load method uses the filename’s extension to determine how to load the file.
If the extension is “.landis”, then the parameter file contains a serialized object that implements the interface IEditable<T>. The IEditable generic interface is defined in the FLEL utility library. The Load method deserializes the editable object, and then tries to obtain a complete set of parameters from that object. If the object has a complete set, then the Load method returns that set; otherwise, it reports an error to the user.
If the filename’s extension is not “.landis”, then the Load method treats the parameter file as a text file, and uses a given text parser to read the parameters from the file.
Therefore, input editors can store parameter data in files as serialized objects. For example, if an editor is designed for a set of parameters represented by the interface IFooParameters, then the editor can store the parameters as an object whose class implements the IEditable<IFooParameters> interface.
In LANDIS-II 5.1, this Load method uses binary serialization. Unfortunately, according to the .NET framework, if portability is a requirement, then other forms of serialization are recommended. Portability is critical so that a GUI user can create a parameter file on her computer, and then send it to another LANDIS-II user to run on a different system.
XML serialization is used by the extension administration tool, which was developed after the LANDIS-II core. This text-based serialization format is easier to debug by developers. Although it is not as compact as the binary format, the larger size is not significant because parameter files are much smaller than input maps in a typical scenario.
LANDIS-II 6.0 needs to support XML serialization of parameter files for portability. Furthermore, the association between filename extensions and serialization formats is hard-wired in the Load method. The flexibility in developing LIME would be maximized if that hard wiring is replaced with a dynamic mechanism that allows the association to be modified without recompiling the core. Possible candidates for that mechanism include the application configuration file and the technique used by the extension administration tool.

