Mathijs Schuts is a software designer at Philips Healthcare. Dirk-Jan Swagerman is the senior director of the company’s imaging chain cluster. Ivan Kurtev is a model-driven engineering specialist at Altran. Jozef Hooman is a senior scientist at TNO-ESI. Comma is selectively available on request by contacting jozef.hooman@tno.nl.

14 September 2017

Precise interface descriptions are crucial in developing complex systems with many components. Interface unclarity is a frequent source of errors. Philips and TNO-ESI explain how their Comma language and tool suite helps to design better interfaces faster and more concisely.

When you want to buy a new car, you go to the dealership. After you’ve made your choice, the dealer will draw up a contract. This contract is a formal document describing two clauses (figure 1). But does it contain all the information required to execute the deal? For example, is it clear whether the buyer needs to pay before or after pickup? And when exactly can he come get the car? Clearly, some important information is missing in this contract: it lacks information about the order in which the clauses need to be executed and it doesn’t specify when a clause will be executed (figure 2).

Comma_Figure_1
Figure 1: A contract between two parties
Comma_Figure_2
Figure 2: What the contract fails to capture

Software interfaces are like contracts. In our experience, the clauses are always described (eg in a header file), sometimes including their order, but their timing behaviour is rarely made explicit. During system development, proper interface definitions are essential to prevent integration issues. During later phases of the system lifecycle, continuous interface monitoring is important to avoid system failures due to component changes. For instance, a supplier might deliver an improved version of a component, but with different timing characteristics.

To nip these problems in the bud, Philips Healthcare and TNO-ESI have developed Comma (Component Modelling and Analysis), an ecosystem supporting model-based component engineering. It’s a combination of domain-specific languages (DSLs) in which the interface between a server and its clients can be specified by three main ingredients: the interface signature, the allowed client-server interactions, and the time and data constraints.

The interface signature consists of groups of commands, signals and asynchronous notifications (illustrated in figure 3 for the patient table of an interventional x-ray system). Commands are synchronous: the caller is blocked until a reply is received, whereas signals are asynchronous: they do not block the caller and do not require a reply. State machines are used to describe the allowed client-server interactions, such as the allowed order of client calls and the allowed notifications from the server in any state (figures 4 and 5). Finally, Comma enables the definition of constraints such as the allowed response time, notification periodicity and data relationships between the parameters of subsequent calls (figure 6).

interface ITable {
    types
    enum Status {
        PosReached
        PosNotReached
        InMove
    }

    command
    bool start
    void stop

    signals
    alive
    moveVertical(int moveId, int pos)

    notifications
    verticalPosition(int pos, Status moveStatus)
}
Figure 3: A simplified version of the interface signature for the vertical movements made by the patient positioning table in an interventional x-ray system
import "table.if"

behavior

machine Main provides ITable {
    variables
    int currentMoveId

    init
    currentMoveId := 0

    initial state Inactive {

        transition trigger: start
            do:
            reply(true)
            next state: PositionReached
        OR
            do:
            reply(false)
            next state: Inactive
}
Figure 4: The first part of the state machine specifying the allowed order of commands, signals and notifications. The initial state Inactive has a non-deterministic choice after trigger start; depending on the internal table behaviour, it can stay in Inactive or go to PositionReached.
state PositionReached {

    transition trigger: moveVertical( int moveId, int target)
        guard: moveId != currentMoveId
            do: currentMoveId := moveId
            next state: Moving

    transition trigger: moveVertical( int moveId, int target)
        guard: moveId == currentMoveId
            next state: PositionReached

    transition trigger: alive
        next state: PositionReached

    transition
        do: verticalPosition (*, Status::PosReached)
        next state: PositionReached

    transition trigger: stop
        do:
        reply
        next state: Inactive
}
Figure 5: The specification of state PositionReached
timing constraints
timeForReply call stop - [ 10.0 ms .. 20.0 ms ] -> reply

intervalBetweenEvents call start and reply (true) -> [ .. 30.0 ms ] between events

continuousCommunication reply (true) to call start then
             any signal with period 100.0 ms jitter 10.0 ms until call stop
Figure 6: A few examples of timing constraints. Data constraints can be similarly specified, such as for the maximal distance the table is allowed to move after detecting the absence of move requests.

Monitoring

A number of artefacts can be generated from a Comma model (figure 7). Comma produces PlantUML files that visualize state machines. Constraints can be intuitively represented as annotated UML sequence diagrams. In addition, Word documents compliant with the company’s standards can be generated, based on the M2Doc framework. This transformation extracts definitions and comments from models and inserts them in a document template. It also uses the diagrams obtained from state machines and constraint rules.

To accelerate implementation, Comma interface signatures can be transformed to interface proxy code (C++ and C#). This code can be incorporated into the company-specific platform for transparent component deployment. Based on the state machines, models can be generated for various model-based testing tools, enabling test generation and online testing.

Comma Figure 7
Figure 7: A number of artefacts can be generated from a Comma model.

For simulation purposes, state machine models are transformed to Poosl programs (Parallel Object-Oriented Specification Language). Using Poosl’s step-by-step visual execution facilities, engineers can explore the model in simulation to support early feedback and error detection. A modified version of the transformation to Poosl produces an executable monitor for runtime verification.

The monitoring is based on a trace of the interaction between client(s) and server. This can be obtained by logging or sniffing the events during system execution (figure 8). Verdicts can be errors and warnings. Errors are violations of the state machine logic. Warnings are constraint violations. After an error the monitoring process stops; after a warning it continues. The trace is also used to obtain statistical data (figure 9).

Comma Figure 8
Figure 8: The monitor is a Poosl program that is partially synthesized from the constraint rules. It reads the events in the execution trace and sends them to an executable model (also a Poosl program) derived from the state machines. The state machine responds with events, which are compared to the events in the trace. The monitor also checks if the constraints hold for the trace.
Comma Figure 9
Figure 9: A histogram of the duration of all occurrences of the InjectStimulus command in a trace

Powerful

Comma’s most important business objective is to lower the cost of non-quality. First of all, it makes design cheaper. Architecture decomposition is traditionally done ‘on paper’. Comma enables a system designer to precisely define a subsystem in terms of its required functional and performance capabilities. This is a great way to define the ‘form/fit/function’ of architecture variation points explicitly. As the system designer can experiment with the simulated interface before the software is built, he has much richer opportunities for evaluation and review, helping him to design a better interface faster and more concisely.

Second, the Comma ecosystem speeds up software development through the automated generation of documentation artefacts and inter-process communication interface code. Finally, because the interface design and implementation are higher quality, the integration phase is shortened, lowering the cost of testing and integration. The cost of designing test cases is lowered through the automated generation of (model-based) unit tests. As the Comma ecosystem is able to measure and characterize interface performance timing through timing frequency plots, it’s much easier to spot anomalies in performance timing.

The ability to precisely specify interfaces and measure interface conformance is especially powerful when outsourcing parts of the system. Suppliers will benefit from the increased specification quality. Acceptance testing benefits from the ability to measure interface conformance.

Because of hardware and software obsolescence during the lifecycle of a high-tech system platform, many implementation increments for the same interface will need to be tested and integrated. Comma helps to nail down software form/fit/function with a rigour that was previously impossible. Its use in new product introductions has already proven to lower cost. We expect even more substantial benefits in managing the platform lifecycle. Future work includes enriching the language with data integrity checks and full system-level simulations.

Edited by Nieke Roos