The following is an excerpt from the paper Donatelli and Rizzoli (2008) which summarizes requirements identified to build re-usable components, and which are matched by the design proposed and implemented.
The design
The re-usability of software components can be enhanced by addressing the following requirements: 1. The component must target the solution of a sufficiently widespread modeling problem; 2. The published interface of the component must be well documented and it must be consistent, 3. The configuration of the component should not require excessive pre-existing knowledge and help should be provided in the definition of the model parameters 4. the model implemented in the component should be extensible by third parties, 5. The dependencies on other components should be limited and explicit, 6. The behavior of the component should be robust, and degrade gracefully, raising appropriate exceptions, 7. The component behavior should be traceable and such a trace should be scalable (browsable at different debug levels), and 8. The component software implementation should be made using technologies with a widespread adoption. There are a number of solutions to address these requirements and we present the choices made for the design we have used in some components we have developed.
1. Targeting an explicit common modeling problem is associated with the granularity of the modeling approach. Fine grained components are more likely to be reused for specific computations, in the context of larger modeling problems. Simple model units can either be used in isolation or they can be composed to develop other modeling units. An example are the CLIMA components (Donatelli et al. 2006a; Carlini et al., 2006) which implement fine-grained models that generate synthetic weather variables. The component architecture adopts the Strategy design pattern in order to allow for the plugging-in of alternative model formulations to generate the model output, since various models can be used for the same purpose. The components referenced above match such requirements. A large coarse-grained component that simulates groundwater transport of a contaminant over a region might require a very complex configuration. This does not mean that large components are not reusable, but the effort to reuse them is bigger.
2. Components depend on the data they access (inputs, parameters, states etc.). Such data can be described and implemented by means of data structures called Domain Classes (Del Furia et al., 1995). Each attribute of such classes will also have, beside its value, a set of attributes such as minimum, maximum, and default value; units; description, and may refer to a publicly available ontology via the attribute URL. Reflection can be used on such types thus allowing access to their ontology. The values of domain classes goes beyond their meaning as software implementation items, in fact they describe the domain of interest. The use of domain classes is equally valid for static and dynamic components (e.g., Acutis et al., 2007; Trevisan et al., 2007). If domain classes and interfaces are implemented in a separate discrete unit from models, the model unit can be replaced without affecting the client using the components (this is the Bridge design pattern). A component implementing domain classes and interfaces and another implementing models are a unit of reuse; the model component alone can be defined as a unit of interchangeability.
3. The API of the component must implement a pattern like the Create-Set-Call; objects are created via a default constructor, some attributes are set, and finally the model is called. The interface used for models should be the same for all modeling solutions in the component, implementing the Façade pattern to hide the complexity of each model solution. This leads to having a unique signature for internal and (see below) extended models. Such unique signature (its first overload in its simplest form), can be like: Update(DomainClass d, IStrategy s);being dan input-output object. Components should be stateless, to simplify their use in different systems. Sample clients, inclusive of code, must be made available.
4. The component must expose public interfaces to allow extensibility by third parties without requiring the re-compilation of the component, and to allow freedom of implementation. Components can be extended inheriting also from domain classes to extend them,
5. While dependencies should be kept at a minimum, we found necessary and particularly useful to introduce a dependency to another component, available both in .NET and Java (http://www.apesimulator.it/help/utilities/preconditions) which implements the Design-by-contract approach (see next point), and provides a type (VarInfo) to set the attributes of each variable. Moreover, it provides other base interfaces for models (strategies) and domain classes. Other dependencies to specific libraries (e.g. for numerical calculus) can be included, but no dependency to specific frameworks is implemented.
6. The robustness of the component is ensured by the implementation of the Design-by-contract approach, thus a clear contract between client and server is established. This allows not only developing a better targeted library of unit tests, but it also sets the domain of applicability of the models, contributing to the transparency of the modeling solution. If an unhandled exception occurs, an informative message describes the error and model and component source of the exception, allowing for continuing execution of the client according to a user choice.
7. The traceability of component behavior is implemented in the .NET versions using the TraceSource class, in one implementation that allows setting the listeners by the client. Various levels of tracing can be hence pooled in one or more listeners with all traces from other components and from the client. In Java component this is obtained using a logger.
8. The technology used is based on the object oriented programming (OOP) paradigm via the MS .NET 2.0 framework. However, the object model of .NET allows easy migration to the Sun Java platform. Such migration has been realized for some of the components referenced.
Design patterns used
The architecture of components is based on four different software design pattern in order to implement the desirable features extensibility and modularity. Three of the used patterns are structural, and one is behavioral (Bishop, 2008).
The keystone pattern used is the Composite pattern. Different types of model units, i.e. simple strategies and composite strategies, implement the same interface, IStrategyComponent, as shown in the diagram below. This means that composite strategies are associated with simple strategies and they implement the same operations (i.e. a composite strategy calls the methods specified in the interface also for associated strategies). Thanks to this, composite and simple strategies are treated in the same way and can be accessed through the same API method.
From the modelling point of view, the software design can be seen as an implementation of the Transparent Façade pattern; composite strategies offer a unique entrance to layers of modelling, hiding the complexity behind them but preserving a robust, modular structure. Simple strategies are still accessible.
A third type of model unit, the context class, is defined by imposing the implementation of the same IStrategyComponent interface. Context classes are defined in the behavioral pattern Strategy; in a context class decisions on the strategies to be used at run-time (simple or composite) are taken based on a specific model, responding to the context of operation. A typical use of such context classes is the selection of the appropriate strategy based on the inputs available in the instance of the domain class (classes).
Finally, by keeping interfaces, domain classes, and the component API class in one single component, and all model units (simple and composite strategies, contexts) in a different one, the Bridge pattern is implemented. This pattern de-couples the abstraction (data structures, methods declaration) from the implementation (models). In fact, a client will have a dependency on the data and interface component, and no dependency on the model component. This allows both easy replaceability of the latter, and the extensibility to multiple model components without the need of recompiling the client.
The subdivision to meet the architecture described subdivides classes in the following components:
Proofs of concept
Components implementing the solutions above have been made available for public use and other are being developed (examples are referenced below). The design has been tested on static and dynamic biophysical models, on agro-management models, and on statistical indices. Use of components has been done on applications and via frameworks such as TIME and Modcom.
References
M. Acutis et al. Software components to simulate water and nitrogen dynamics in soil. 2007 Proc. of Farming Systems Design 2007, Catania, Italy, 10-12 September, 2007
L. Carlini et al., Rain, a software component to generate synthetic … 2006 Agron. J. 98:1312-1317
L. Del Furia et al, Lakemaker: a general object-oriented software tool for modeling … 1995 Env. Soft.
M. Donatelli et. al., A software component for estimating solar radiation. 2006a Env. Model. Soft. 21:411-416
M. Donatelli et al., Sharing knowledge via software components: models… 2006b Eur. J. Agron. 24:186-192
M. Donatelli et al., A software component to simulate agro-management. 2007 Proc. of Farming Systems Design 2007, Catania, Italy, 10-12 September, 2007.
M. Trevisan et al., A software component to simulate agro-chemicals fate. 2007 Proc. of Farming Systems Design 2007, Catania, Italy, 10-12 September, 2007.
Created with the Personal Edition of HelpNDoc: Free EBook and documentation generator