Rapide Sw Engineering Tutorial |
Operations come from a tradition of functional or subroutine based programming evolved into object oriented techniques. Their semantics is usually synchronous, although some efforts have been made to make them loosely coupled by using variable placeholders and delayed evaluation (See for example Bertrand Meyers's Concurrent Eiffel). The use of signals come from the communications and concurrent programming tradition. Its theoretical foundation is rooted in the landmark paper by C.A. Hoare "Communicating Serial Processes" and a very popular language to design such systems is SDL standardized by the International Communications Union (formerly CCITT).
Rapide explicitly provides the concepts of architecture, interface and connection. The underlying model for this structure can be found in the article Three Concepts of System Architecture. It also provides direct support for complex synchronization patterns and specifically for signals and operations as described in the previous paragraphs (actions and functions).
An architecture is composed of a number of interfaces and the connections among them. A complete definition of an interface requires both what services it offers to other components in the system and the services required from the rest of the system to perform the offered services. As described in the language trail, a Rapide interface is defined by the primitives (actions and functions) it offers and the ones it requires. Rapide offers in this way a complete set of tools to specify a system component's interface. It is to be noted that current languages concept of interface is restricted to the offered services, e.g., a Class declaration in C++, with only a loose statement of the modules it requires (C/C++ include statements, Java import statements, Ada "use" and "with" clauses).
The designer is interested in describing the architecture and experimenting with it to probe its behavior and the protocols between components.
The architecture is described by declaring interfaces and connections, then specifying how the interfaces react to the events presented to them through the connections. At this level of abstraction an architecture execution is the set of primitives interchanged between interfaces through the defined connections. An example architecture may be found in the Client/Server example.
It is important to observe here that the behavior to be specified is only the one relevant to the interface interaction and not the behavior of the "prospective module" that will implement it. The module that implements an interface may execute other actions not shown at this level of detail, like internal DB access, I/O or operating system calls. The specification of the interface behavior at this point in the development will act as a guideline and as a constraint for the module to be implemented. Interface behavior can be expressed in Rapide through the use of reactive rules and by imposing constraints on the generated events.
Two tools are available to assist building architectures and
inspecting their executions at this level of descriptions:
Following the example of client/server, the module to implement a resource should be implemented to conform with this behavior definition written in the form or rules.
The second alternative of attaching a subordinate architecture to a Rapide interface is shown following the steps in the example on transaction processing. In this example, a component in the top level architecture is instanciated with another subarchitecture. We achieve this by providing connections with the external world (top of the canvas) that relate the actions in the subarchitecture to those specified in the component interface.
Again, any system described in Rapide is readily executable using the architecture compiler and the resulting poset can be inspected with the poset viewer (pov) or animated with raptor. This converts a detailed design of the system expressed in Rapide into a prototype that can be tested for adequacy to the specifications.
So far, we have used Rapide in a fairly conventional way of "think then model and finally program." A more advanced practice of engineering a system is supported by Rapide by means of expressing the requirements directly and then composing them to form a "specified architecture." A specified architecture basically describes the interfaces and connections among them and a set of rules and constraints that restrict the possible posets that result from a system execution.
The key idea is to describe the allowed and forbidden posets in the architecture and then combining them in a set of architectural constraints that the system has to meet. This set of constraints is in effect an observational specification of the system as it describes what kinds of generated events and protocols the system is to exhibit.
To illustrate this, a transaction processing system can be specified by starting with the expected behavior to ensure ACID properties. In technical report CSL-TR-96-710, this process is carried out in detail.
The activities involved are first to define what properties the system needs to have, in our example, we want the system to exhibit:
We will not provide here a detailed description on how these properties are modeled, but just taking atomicity, one could require that for a given transaction, there are no commit and rollback events in the same computation. Thus in Rapide, and with the given system architecture as a reference, would be expressed as:
never
(?x : Xid; ?i, ?j : Integer)
(RMs(?i).Commit_retn(?x, True) ~ RMs(?j).B.Rollback_retn(?, True));
Then, once the constraints and the reference architecture are defined, to test conformance with the designed architecture, a map is needed to relate the events defined in the reference (e.g. Commit_retn) and the ones produced in the architecture under test.
Once the map is complete, The constraints expressed in the reference architecture can be interpreted in terms of actions in the new architecture. This interpretation allows to determine if the computations of the design (generated posets) are compliant with the constraints or not, and thus whether the design is compliant with the specification.