Reducing the gap between design and code for critical software with Ada 2012
The latest version of the Ada language standard, known as Ada 2012 , has extended the language’s support for minimizing the gap between design and code by raising the level of discourse, a principle that is fundamental to software development and that has been an underlying goal throughout Ada’s evolution.
The initial version of the language, Ada 83, provided modular programming with real-time message-based multi-tasking. Ada 95 added object-oriented features and data-oriented synchronization. Ada 2005 introduced interfaces for both normal and synchronized types.
In Ada 2012, contracts have been added in the form of pre- and postconditions, type invariants, and subtype predicates, along with finer-grained control for multicore programming. Ada has, in effect, integrated low-level requirements into the source code, and is the first ISO standard language to include contract-based programming,.
How to embed the design in the code
A key ongoing challenge for software developers is to reduce the gap between the high level requirements (design) of the system and the coded program, simplify development, and reduce the likelihood of error. Ada helps achieve this goal though a set of portable high level features that relate directly to concepts relevant at design time, while still providing lower level control where needed.
As an example, many critical embedded systems involve concurrent activities that need to interact safely through shared data or message passing while meeting hard or soft real-time requirements. In Ada, such activities map directly to multiple Ada tasks, with their interactions and real-time constraints representable directly in the code.
These facilities help make concurrent programming in Ada simpler and more reliable than in languages based on lower-level constructs. Another example is Ada’s support for object-oriented programming, where the interface feature allows multiple-inheritance class hierarchies to be directly represented.
Figure 1 illustrates how Ada reduces the gap between the design and the code, and between the code and the underlying hardware platform.
How to connect the model with the code
A new trend in a number of domains is the increasing usage of executable models, with products such as MathWorks’ Simulink, Esterel's SCADE, and various UML-based tools. The developer can use such tools to represent a portion of the system’s high-level logic in a form that can be directly executed by a simulation engine, and/or translate it automatically into compilable source code. Yet even with the best modeling systems, some portions of the system still need to be hand coded, either as modules that are plugged in to the modeling system, or as wholly separated components that are not amenable to executable modeling.
A major challenge is then how to test and verify the ultimate system, which combines the automatically generated code and the hand-written code, as represented in the compilable language. Translating from the modeling language to the compilable language may introduce synchronization, timing, or correctness issues, necessitating a full system test and certification on the compilable code even if the model has been shown to conform to the higher-level requirements.
When Ada is used as the compilable language generated from the model, Ada's strong interface checking helps detect potential inconsistencies. Moreover, its higher-level features such as tasks, protected objects, and interface types reduce the distance between the modeling language and the compilable language, making the transformation performed by the automatic code generator simpler to validate.