CSAIL Research Abstracts - 2005 link to http://publications.csail.mit.edu/abstracts/abstracts05/index.html link to http://www.csail.mit.edu
bullet Introduction bullet Architecture, Systems
& Networks
bullet Language, Learning,
Vision & Graphics
bullet Physical, Biological
& Social Systems
bullet Theory bullet

horizontal line

Evaluating Predicate-Oriented Programming:
Using Predicate Fields in a Highly Flexible Industrial Control System

Shay Artzi & Michael D. Ernst

Introduction

At the heart of object-oriented programming is the ability for run-time values to affect program behavior. Dynamic dispatch selects which implementation of a method to invoke, based on the run-time class of the receiver object. Researchers have proposed other, more powerful ways for run-time values to affect both the behavior and the structure of objects. Predicate classes [1] use predicates to dynamically classify an object to its subclasses. Predicate fields give a way of affecting object structure rather than object behavior. A predicate field is a field of an object that is present (can be read and written) depending on the values of other fields. In other words, the structure of an object varies at run time depending on the values of its own fields.

We present a case study of two command and control systems for a facility in which physical experiments are performed. The second system was designed with requirements similar to the first, and uses predicate fields in order to mitigate deficiencies in the first implementation. This use of predicate fields was successful: the resulting system is very flexible, the user interface is highly configurable, and development costs, especially in the user interface, were greatly reduced.

We believe this is the first evaluation of predicate-oriented computing in a realistic, large-scale development effort. Our observations help to indicate circumstances in which predicate fields are most useful, and the practical obstacles to their use. Our observations also suggest that many important benefits are obtained even in the absence of sophisticated predicate expressions and dispatching mechanisms. One implication for practitioners is that it can be advantageous to use even a primitive implementation of this language feature.

Predicate Fields

A predicate field is a field whose presence in an object depends on the run-time value of a predicate (a boolean expression). Predicate fields allow an object's structure to vary at run time.

Four motivations for predicate fields are as follows. First, predicate fields allow an object to change its structure during its life cycle (e.g., an employee gets promoted from hourly to yearly salary). Second, predicate fields permit the user to recover from errors, such as changing the type of a created object while preserving all the data which is mutual to both types. Third, predicate fields can ease UI development by presenting a unified view on arbitrarily many collections of fields (for example, using reflection). Fourth, predicate fields permit fine-grained customization of objects or object behavior, without requiring new class definitions (tagging an employee with special fields).

Predicate Fields Library

We have implemented predicate fields as a library in C#. Previous predicate-oriented systems [3,4,1,6,2,5] are based on language extensions, some of which are accompanied by a prototype implementation. Our decision to use a library is a pragmatic one.

Our library supports the creation of <em>dynamic objects</em>, objects in which each field is a predicate field. A dynamic object is an instance of a dynamic type. Conceptually, the declaration of a dynamic type lists the (predicate) fields contained in each object of the type.

Each dynamic object has a type, called its dynamic type; the dynamic types partition the set of all dynamic objects. The dynamic type is stored in a dynamic object upon creation and is permitted to change subsequently. A field definition contains its type, predicate, user interface information and persist storage. Field types specify the type of the data that is stored in the field, a class used to edit its value, and a class used to convert its value to and from a printed representation. A predicate is constructed from a pair of a field name and a value of the field's type. This decision implies that developers can define a predicate on every possible value of the object's state.

Case Study: Experimental Control System

We performed a case study involving two systems that control facilities for complex experiments. The two implementations serve as command and control software for experiment-conducting facilities. Their goal is to enable scientists and technicians to define, control, execute, and examine these experiments.

An experiment consists of a set of devices and a sequence of operations of those devices. Examples of devices are thermometers and drill presses. Examples of operations are measuring the temperature and drilling a hole. The operations of an experiment are written in a language called MML, or Mission Modeling Language.

The user interface is tree-based. The experiment designer adds new MML statements to the statements tree and new devices to the devices tree. Each element in the tree can be configured by a related properties form. The operator can observe the properties of the various items in the trees as well as the progress of the experiment shown on the statement tree.

The key requirement for the experimental control system is adaptability to physical hardware changes and replacements. New devices are developed constantly; incorporating those devices into the system should require no software changes in the experimental control system (but may require changes to experiments). In order to address these requirements, the design includes a highly configurable two-level system architecture, a knowledge level and an operational level. The operational level describes the concrete model of the system, derived from the functional requirements. The knowledge level contains the meta-model of the system and defines the legal configurations of operational level objects.

Implementations

We built two implementations of the experimental control system. The first implementation is in daily use at one experimental facility. The second implementation is in incremental integration at a different facility and will eventually replace the first implementation. Re-implementation took advantage of knowledge gained from the first effort and permitted exploration of different design decisions, most notably the use of predicate fields.

Implementation 1 is considered highly successful. It has been used daily since 2001 to design and run many experiments. It transformed the way that work was performed at the specific facility where it is installed, and other facilities are eager to obtain it.

There are three design deficiencies in implementation 1 that led to the decision to use predicate fields in Implementation 2. First, each object in the user interface (statement, device, device type, group, command, etc) had a custom-made property page for editing its information. User interface development took a significant share of the development time, and it was difficult to integrate new devices with unfamiliar editing information. Second, changes to the structure of the statements required cross cutting layer changes. Third, the type of an object could not be changed. Suppose the experiment designer added an automatic statement, then wanted to change it to a manual statement. He would have to delete the automatic statement and create a new manual statement in its place (losing all the mutual information).

Predicate Fields Motivation

This section gives three motivations for the use of predicate fields in Implementation 2.

First, we realized that all objects share the same characteristics while being edited. Implementation 1 connected the user interface tree's nodes (statement, device, ...) with viewers of the appropriate objects. However, it caused tight coupling between the objects in the user interface layer and the objects in the business logic layer resulting in the cross cutting modification problem mentioned earlier. The information required when editing an object consists of four parts: the object data structure, the possible values for each field in this structure, the storage location of each field, and the connection between the different fields. This led us to design a dynamic object, whose structure is defined by predicates on its state. The fields carry all the information that is used to edit, save, and load them. Every object that is selected has the same property page created using a PropertyGrid gadget (the PropertyGrid gadget queries the object about its fields using reflection and presents them in a readable way to the user.).

Second, the level of uncertainty in which the development team had to work pushed us into generalizing beyond Implementation 1, which was itself highly flexible. Implementation 1's knowledge level included devices, devices types, and commands. Using predicates to emulate dynamic reclassification into subclasses allowed us to move the statement hierarchy from the operational level into the knowledge level. Predicate fields also enabled us to insert device types' user interface information into the knowledge level. Moreover, controlling the entire knowledge level with predicates allows finer control over the operational level. Finally, by having each field contain all the knowledge needed to edit, load and save it the users can easily support new devices which are combinations of the existing fields.

Third, using dynamic classification permitted us to improve the user interface by allowing the designer to change the type of edited objects without removing the old one and creating the new one. The changed objects retain all their mutual information, saving the experiment designer the trouble of supplying the same information repeatedly.

Experience

User interface developers had to interact with the dynamic objects. A dynamic object provides a simple interface to query the values of its fields. In addition, it allows objects to register to a variety of events that are activated when the corresponding field's value is changed. The developer only had to instantiate the object (with the appropriate dynamic type), and possibly choose a storage location. Finally, the developer can pass the dynamic object to a wrapper object that can be used for reflection (for example passing it to PropertyGrid gadget for editing). Those developers reported that due to its simple interface the dynamic objects were easily used and the result was a significant decrease in development time. Some of the developers were even surprised by the ease and quickness of the development process.

Developers adding support for new requirements and features had to modify the dynamic types (rarely), fields, field types, and predicates (more frequently). These modifications demanded understanding the interaction between the different data structures. Adding new predicates and fields and modifying existing ones was initially difficult for most of the developers. This initial difficulty can be attributed to the following four factors, which we consider to be real limitations of the system. However, most problems result from the library syntax and would have had less impact had predicate fields been implemented as a language extension.

  1. Using a declarative approach. Parts of the resulting software can be harder to understand. Since we are using declarative definitions, it is very hard to grasp a component's full structure (even if we did not take into account dynamic structure modifications).
  2. Far-reaching effects of modification to the predicate data. Since system behavior heavily depends on meta data, changes to the meta data can have far-reaching affects. It was often the case that a careless developer made a seemingly simple change to the predicates fields definitions, only to discover that the system had become unusable. This requires careful modification, well-documented knowledge level structure, and unit testing.
  3. Predicate fields are implemented as a library, rather than as a language extension. This can cause the software to be less readable (again due to the declarative approach) and incur some performance overhead when modifying the object structure and accessing fields within the object (this overhead is negligible since dynamic objects are used in the user interface).
  4. Type safety problems. Objects appear to change their type dynamically. Combined with the library implementation, static type checking is very hard. However, developers can use testing scheme to easily transform their beliefs about the correlation between the object's state and its set of fields, into tests.

Whereas many developers initially disliked the predicate fields library, all developers reported that once they became familiar with defining predicates and fields (usually after the first two or three), they were able to proceed with ease. They also found out that their perspective toward designing the user interface has changed and noted that one result of using the predicate fields was that almost no custom forms had to be built.

Conclusions

We have presented an implementation of predicate fields as a library, and a case study of the use of predicate fields in a substantial industrial control system. Developers found predicate fields useful in practice. The library is used successfully and intensively in a project with very tight deadlines. This case study provides concrete evidence that other practitioners should try predicate fields, and that researchers should continue to refine designs and implementations.

Developers used predicate fields to support greater software flexibility, both for themselves and for power users. Predicate fields gave developers greater control over objects, allowed fined-grained modifications to specific fields, and provided a declarative approach to defining object structure, permitting changes to be easily reflected throughout the system.

Predicate fields were particularly useful in providing a uniform interface to an arbitrary (and dynamically changing) number of possible object structures, which was achieved through a combination of reflection and treating dynamic objects (created by the library) as real objects. Our experience suggests that predicate fields may be particularly useful in projects with a high level of user interface requirements. Furthermore, predicate fields are a good match for projects in which requirements (and persistent objects) change frequently, because they permit both the code and the objects themselves to be easily adapted to new circumstances.

The predicate fields implementation has a number of limitations: it is implemented as a library rather than integrated with the programming language; it does not support predicate dispatching or predicate classes; the syntax for predicates is very limited; and it uses dynamic type-checking, giving the possibility of run-time type errors. Despite these limitations, the implementation was sufficiently powerful to solve the problems encountered in building the industrial control system, and the developers did not feel that (for example) lack of support for dynamic behavior modification of objects was a significant hindrance. This result is suggestive regarding how much linguistic power and complexity is desirable in practice.

The case study also revealed some potential downsides of using predicate fields, some of which are consequences of the implementation and some of which are inherent to the use of predicate fields. Language and tools support are important in reaping the potential benefits of predicate fields. The declarative nature of the predicates was useful in propagating changes throughout the system, but the same characteristic (non-local control) could make component behavior difficult to understand. The biggest remaining problem is lack of static type safety. In the absence of integration into a widely accepted programming language implementation (a distant prospect), we have proposed a testing mechanism that may mitigate this problem.

Research Support

This research is supported in part by NSF grant CCR-0133580.

References

[1] C. Chambers. Predicate classes. In ECOOP '93, the 7th European Conference on Object-Oriented Programming, pp. 268--296, Kaiserslautern, Germany, July 1993.

[2] M. D. Ernst, C. S. Kaplan, and C. Chambers. Predicate dispatching: A unified theory of dispatch. In ECOOP '98, the 12th European Conference on Object-Oriented Programming, pp. 186--211, Brussels, Belgium, July 1998.

[3] J. Hamer, J. Hosking, and W. Mugridge. A method for integrating classification within an object-oriented environment. Technical Report Auckland Computer Science Report No. 48, Department of Computer Science, University of Auckland, Oct 1990.

[4] J. Hosking, J. Hamer, and W. Mugridge. Integrating functional and object-oriented programming. In Technology of Object-Oriented Languages and Systems TOOLS 3, pp. 345--355, Sydney, 1990.

[5] T. Millstein. Practical predicate dispatch. In Object-Oriented Programming Systems, Languages, and Applications (OOPSLA 2004), pp. 345--364, Vancouver, BC, Canada, Oct 2004.

[6] A. Taivalsaari. Object-oriented programming with modes. In Journal of Object-Oriented Programming, pp 25--32, June 1993.

horizontal line

MIT logo Computer Science and Artificial Intelligence Laboratory (CSAIL)
The Stata Center, Building 32 - 32 Vassar Street - Cambridge, MA 02139 - USA
tel:+1-617-253-0073 - publications@csail.mit.edu
(Note: On July 1, 2003, the AI Lab and LCS merged to form CSAIL.)