WCOP'97, held together with ECOOP'97 in Jyväskylä, was a follow-up workshop to the successful WCOP'96, which had taken place in conjunction with ECOOP'96. Where WCOP'96 had focused on the principal idea of software components and their goals, WCOP'97 was more directed towards composition and other topics, such as architectures, glueing, component substitutability, evolution of interfaces, and non-functional requirements.
WCOP'97 had been announced as follows:
COP has been described as the natural extension of object-oriented programming to the realm of independently extensible systems. The most prominent examples of such systems are constructed around compound document models such as OLE, OpenDoc, JavaBeans, or Netscape ONE and rest on object models such as SOM/CORBA, COM or Java's virtual machine. WCOP'97 intends to address their methodological and theoretical underpinnings.
COP aims at producing software components for a component market and for late composition. Composers are third parties, possibly the end user, who are not able or willing to change components. This requires standards to allow independently created components to interoperate, and specifications that put the composer into the position to decide what can be composed under which conditions. These needs raise open research questions like what kind of standards are needed and how they should be defined. Or what information specifications need to give, how this information should be provided, and how correct implementation and usage of specifications could be verified or enforced.
16 position papers were submitted to the workshop and formally reviewed. 12 papers were accepted for presentation at the workshop and publication with the proceedings. Unfortunately, the paper by M.Goedicke and T.Meyer could not be presented, because force majeure hindered the authors to attend the workshop. Still, 25 participants from 13 countries were counted at the workshop.
During the morning session, participants presented their work, which covered a wide range of topics. A major theme was how to select components for composition in a specific situation. Such a selection must rest on two pillars. Firstly, the selected components must be compatible with each other. Secondly, characteristics that are not part of the standardized component interface may decide which component to pick from otherwise equal ones. Examples are time or resource requirements, fault tolerance, degree of distribution, etc.
To address the compatibility of components, various approaches and philosophies were presented. An important property of component-oriented programming is that a single specification may be supported by multiple implementations. However, problems may arise if individual implementations depend on the implementation of other components. These dependencies may cause conflicts, which can often only be detected when the composed system is analysed as a whole.
One solution is that dependencies on other components as well as known conflicts with other components become part of a component's specification. Reuse Contracts [De Hondt et al.] have been proposed as a tool for this. They also allow the composer to decide quickly whether a given set of components may conflict.
[Mikhajlov & Sekerinski] suggest to define rules that, if being followed, exclude conflicts in principle. These rules affect the design of specifications, the implementation of components, and the implementation of a component's clients. For inheritance between classes of objects, such rules can be derived formally.
A third approach is to accept that components will have some dependencies that are not part of a specification and hence cannot be checked by the composer. The component creators, however, are aware of these dependencies. Thus, this knowledge, available during component creation time, has to be maintained and made accessible to system composers. [Murer] suggests that this requires tool support.
Finally, a component may not be applicable in a specific situation as it is. In these cases, it needs to be adapted, which can be done either by modifying the program's source code or by wrapping it. Both approaches have their disadvantages. Alternatives on a middle ground are needed. [Bosch] proposes the use of component adaptation types that can be superimposed on components.
One aspect of specifications is that they embody a contract between programmers of service providing components and service clients. Because it is impossible to test a provider component against all clients and vice-versa, it must be decided without testing both whether a specification is implemented correctly and whether a client uses it correctly. For this, formal methods are helpful, but need to be made applicable in practice. [Büchi & Sekerinski] address the problem of poor scalability by specification statements, which are used in refinement calculus.
The second mayor theme of the presented work were properties of components that are not part of the (functional) standard interface. One may want to add such properties to existing components when putting them together to a complete system. This allows the system's composer to pick those properties that are actually needed in the specific situation. [Troya & Vallecillo] discuss some technical precautions for this, such as a specific communication mechanism.
An example of such add-on properties are mechanisms for run-time fault management in distributed systems. [Baggiolini & Harms] propose to use wrappers for providing monitoring, diagnosis, or failure correction.
Components that are otherwise interchangeable will distinguish themselves by some important (unchangeable) properties, such as resource requirements. It is an important task to select the right components, meeting possible constraints imposed by the deploying system or the problem to be solved. [Lalanda] suggests that this selection may be best made at run-time, and proposes a special architecture.
Some of the work addressed other topics than these two main themes. Workflow systems seem to lend themselves to component-oriented software, because of their configurability and building-block-like structure. [Schreyjak] proposes a special component framework to support component-based workflow systems.
One way of composing systems is by expressing relations and cooperation between components in a special language. [Steensgaard Madsen] proposes an interpreted language, in which the commands are components. Such language interpreters are specialized for an application domain and need to be generated automatically.
[Weck] discusses problems of code inheritance across component boundaries, such as the danger for unwanted dependencies. Instead, inheriting classes need to refer to specifications of base classes. With this, inheritance can be replaced by object composition without sacrificing the possibility of static analysis, yet being more flexible.
Because of the many participants, during the afternoon session the workshop was split up into discussion groups. The participants expressed interest in four areas: Components, Architectures, Non-Functional Requirements, and Glue. The following are short summaries, based on presentations and notes provided by different participants of the discussion groups.
Components: As a start, it was recognized that what makes something a component is neither a specific application nor a specific implementation technology. In this sense, "anything" may be cast into a component. To provide access to something about which so little is known, an interface needs to be provided. Interfaces are mainly seen as a collection of "Service Access Points", each of them including a semantics specification. The main purpose of components is reuse of both implementations and interfaces. For effective implementation reuse, the aforementioned independence from implementation technology is particularly important. Two kinds of life cycles are to be distinguished: that of the interface and that of the component itself. The latter is shorter than the former, because the interface exists as long as any implementation is around. For interfaces, formalization of semantics is necessary. Even more important, the interoperation between components must be described. On the technical level, one needs a binary interoperation standard and a mechanism to map semantics specifications to implementations using this binary standard.
Architecture: Architecture describes compositions of components, and therefore relationships between them. This requires consideration of the component's interfaces. Architecture is to be stated in terms of interfaces rather than component implementations. In contrast, if architecture would be seen just as design patterns for composition, a concrete architecture may not be realizable because the components at hand may not fit together (architectural mismatch). On the other hand, in a given architecture, components are replaceable by others implementing the same interface. Thus, architecture represents the longer lasting and slower changing design as opposed to component implementations. More precisely, an architecture consists of a collection of interfaces that represent slots to be filled (or roles to be played) by components. Some supporting white-box implementation, for instance, a kernel, may be bundled with a given architecture.
Non-Functional Requirements: Examples of systems currently under construction were collected together with their specific non-functional requirements. For instance, an avionics system that plans trajectories of a plane and must react to route problems (such as a storm or being low on fuel) must be fast (2-3 second response time) and must adapt itself to many different situations that might arise. Secondly, a system for numerical computing on parallel processors must run fast on a given parallel machine. It also must be quickly portable to run on a new machine. Thirdly, software for controlling a kidney dialysis machine must be responsive (quickly read various sensors and updates actuators), flexible (to adapt easy and reliably to changes in hardware, such as a new pump model, or medical practice, such as a new protocol for dialysis), and demonstratable (to be shown to a regulatory agency to convince them of its safety and benefit).
There are different ways of meeting non-functional requirements, depending on the type of requirement. Some are automatically satisfied if each component of the system is properly designed. Others arise out of the interaction of components, and can only be addressed at that level, not at the level of individual components. Four ways of providing non-functional properties could be found. One can parameterize components so that specific properties can be requested of them; or one can reorganize the components to deal with the property; or one can design an overall architecture that is responsible for the property and that can provide it if the components adhere to the architecture; or, finally, a meta-level mechanism can provide access to the component interaction to deal with the property. The latter is similar to aspect-oriented programming.
Glue: By glue, the participants understood middleware that is used to connect existing components. Examples are Tcl/Tk, scripting mechanisms, even make files. Some support for typing would be nice to have but hard to achieve due to the vast variety of types components may introduce. In general, the glue is more flexible than the components glued together, and thus should use a dynamic language. In connection with the discussion on architecture, it turns out that components are sandwiched between architecture and glue. To be accessible from within a given scripting environment, the components must meet some architectural requirements, like accepting messages sent by the script interpreter. Thus, the script (glue) builds on components that in turn are built for the scripting architecture.
Last update: 11 Sep 97, Wolfgang Weck