Contract-based software development with Franca
This is the first part of a three-part series about software interfaces and contracts. We will explain how modeling and formal specification of interface contracts helps in improving development as well as the quality of the resulting software products. In the first part, we will introduce Franca IDL as a foundation.
Interface definition languages
In any kind of software architecture, interfaces between components, subsystems or systems are important artifacts. They represent the contract not only between these architecture building blocks, but also between organizational units like teams, departments, or companies. Therefore, interfaces are often modeled as first-class entities using an Interface Definition Language (short: IDL).
Compared to interfaces defined using a general-purpose programming language (e.g., a Java interface or a C++ class), IDL models are technology-neutral and language independent. The same interface definition can be used in a web application by mapping it to a RESTful service and in an embedded system by generating proper C++ code from the interface definition. The interface is then realized as a connection between two processes on top of some inter-process communication stack. The data structures and communication primitives defined by the interface will be mapped to proper implementation concepts on the target system.
Franca is a tool for definition and transformation of software interfaces. Its core is Franca IDL, which is a textual language for specification of APIs. Franca IDL covers the following aspects:
- data types, constants and initializer expressions
- actual interfaces consisting of attributes, methods and broadcasts
- protocol state machines for specification of dynamic behavior
An interface instance will typically be provided by a server component (or service) and used by one or more client components. In this context, attributes are data items provided by the server which can be accessed by the clients. Attributes may also support a notification mechanism. Methods are called by a client and executed on the server, which may send a result response or an error back to the client. With broadcasts the server initiates the communication with its clients. Broadcasts are similar to events, but may contain additional data. All details about data types and interfaces of Franca IDL can be found in the reference chapter of the Franca User Guide.
Example Franca interface
The following screenshot shows an example interface using Franca IDL. It specifies a simple music playback API.
findTrackByTitle provides a way to select a musical track based on an input string. From all tracks matching the input string, the best match will be selected and set as attribute
currentTrack. If no matching track can be found, the server will return a NOT_FOUND error code. The attribute is flagged as readonly, as clients should not be able to change its value. Note also that the type of attribute currentTrack is a struct with the elements
coverURL. The latter allows to retrieve the cover art for the album corresponding to the track.
After a proper track has been selected, the methods
pause may be used to control playback. None of these methods have arguments or return values. There is no broadcast element in this interface definition.
Although Franca IDL could be implemented by any kind of modeling tool supporting textual notation, the current standard implementation is based on the Eclipse IDE. The Franca project is open-source and released under the Eclipse Public License. Its source code repository is hosted on github. Franca has been approved as a standard Eclipse project and the transition to Eclipse Foundation is ongoing. The implementation is using the Eclipse Modeling Framework (EMF) and the DSL-enabler framework Xtext.
Apart from Franca IDL, the Franca tool project provides a rich set of features shown in the following diagram.
Transformations and generation
Franca offers a framework for building transformations from/to other IDLs and model-based interface descriptions (e.g., D-Bus, Protobuf, OMG IDL, UML, AUTOSAR). Some of these transformations are included in the standard Franca releases as optionally installable features. Franca also supports code generation with some open-source code generators already available. Currently the most powerful open-source code generator tool based on Franca is CommonAPI C++.
In specific application domains, it may be necessary to extend interface specifications by platform- or target-specific information. E.g., in order to implement Franca interfaces as SOME/IP communication, unique IDs have to be specified for each method. This is supported by Franca's deployment model DSL, which allows users to specify these extensions in a type-safe way.
Flexible deployment models
An executable test environment for an interface definition can be generated instantly, allowing users to see the interface in action. This is accomplished by generating test clients and mock servers from Franca interfaces. This feature is experimental.
Rapid interface prototyping
With Franca, the dynamic behavior of client/server interactions can be specified using protocol state machines. Tools are available to use these specifications for validating implementations, e.g., checking runtime traces against the expected order of events on the interface. Franca also provides a graphical viewer for protocol state machines.
Specification of dynamic behavior
Applications of Franca
Aside from defining and reviewing interface definitions, typical use cases of Franca include code generation (e.g., by using the CommonAPI C++ project), transformations from and to other modeling languages and technologies and, as a building block for more expressive architecture modeling tools, providing concepts as hierarchical components, ports and connectors.
Franca is being used as IDL and integration tool by the GENIVI consortium, which provides an open platform for building In-Vehicle Infotainment systems. It is used mostly by car manufacturers and suppliers in the Automotive domain (e.g., by BMW, Bosch or Continental), but also in non-Automotive environments. There are also research projects and open-source frameworks applying Franca as a building block in a larger tooling environment. E.g., the joynr web-based communication framework uses Franca as an IDL and as a basis for its Java and C++ code generators. It supports the interaction of applications which are deployed on consumer devices, vehicles, or backend infrastructure.
Contract-based development with Franca
Usually, IDLs focus on the static aspects of interfaces, i.e., data types, attributes and operations. However, often there are constraints on the order of interactions on the interface. E.g., an init() method has to be called before any other interaction on the interface is allowed. This specification of event order and dynamic behavior is often part of the documentation accompanying the interface, e.g., as plain text or sequence diagrams. This has significant drawbacks: Plain text cannot be exploited by automatic tools at all – sequence diagrams can only represent single examples of allowed or prohibited behavior.
Franca IDL provides a more expressive means of specifying this kind of dynamics: A protocol state machine (PSM) can be defined for each interface. This allows to define exactly what order of events is allowed on any implementation of this interface. Every sequence which is not covered by the PSM is violating the contract. The PSMs in Franca IDL are defined in a textual form. Additionally, there is a graphviz export for PSMs and an Eclipse view based on ELK (formerly KIELER).
The following PSM specifies the dynamic behavior for the Musicplayer interface example. For example, it defines that
play can only be called after a successful call to
findTrackByTitle. The initial state of this PSM is Idle. Note that each Franca method is represented as a call/respond pair of transitions in the PSM.
What are the benefits of defining PSMs for all your interfaces? After all, this is additional work, and writing some lines of documentation probably is a proper replacement. But as we know from complex industrial projects, many hard-to-find integration errors are caused by misunderstandings about the actual event sequences on the interfaces between organizations or subsystems. This is why defining PSMs for interfaces and using tools to enable static or at-runtime checking of violated contracts is so beneficial.
One important use case is to check traces recorded from a real-world system against the PSMs of its interfaces. As the messages exchanged between components can often be traced without changing the actual source code (e.g., by activating a probe in the communication infrastructure), this is a lightweight, but nevertheless powerful way to validate the dynamic interactions between components. The tool EB solys supports this and many other advanced features based on Franca. It will be described in a later blogpost by our partner Elektrobit – stay tuned!
Meanwhile you can learn everything about the framework Franca in the free User Guide!