Jean Ichbiah devant un terminal informatique

ADA

Ada est un langage de programmation créé à la demande du département de la Défense des États-Unis (DoD) à la fin des années 1970. Son objectif est inhabituel : il ne s’agit pas seulement de faciliter l’écriture des programmes, mais aussi de rendre plus fiables des logiciels complexes destinés à fonctionner pendant de nombreuses années.

Ada n’est pas un sigle. Le langage porte le prénom d’Ada Lovelace. D’ailleurs, le numéro 1815 de son premier standard militaire rappelle son année de naissance.

Le langage vise en particulier les systèmes embarqués et temps réel : avions, radars, systèmes de contrôle, équipements militaires ou industriels. Pour répondre à ces besoins, il accorde une grande importance au typage, à la modularité, à la gestion des erreurs et à la concurrence.

En 1979, le DoD choisit la proposition de l’équipe « Green », dirigée par l’informaticien français Jean Ichbiah chez CII-Honeywell-Bull. Une première définition officielle paraît en 1980. Puis, en 1983, une version stabilisée devient célèbre sous le nom d’Ada 83.

Fiche rapide

  • Nom : Ada
  • Première définition officielle : 1980
  • Concepteur principal : Jean Ichbiah et l’équipe Green
  • Commanditaire : département de la Défense des États-Unis
  • Premier grand standard : Ada 83
  • Versions majeures : Ada 83, Ada 95, Ada 2005, Ada 2012, Ada 2022
  • Domaines privilégiés : systèmes embarqués, temps réel et logiciels critiques
  • Norme actuelle : ISO/IEC 8652:2023, correspondant à Ada 2022

Pourquoi le département de la Défense veut-il un nouveau langage ?

Dans les années 1970, le DoD doit entretenir un immense parc de logiciels. Les différentes armées, les constructeurs et les projets utilisent leurs propres langages, souvent liés à un processeur particulier. Cette fragmentation complique donc la maintenance, la formation des programmeurs et la réutilisation du code.

Une estimation historique souvent reprise évoque au moins 450 langages et dialectes généralistes employés dans l’environnement du DoD. Le National Research Council précise toutefois qu’aucun recensement exhaustif ne permet de considérer ce chiffre comme un total exact. Il donne néanmoins une idée de l’ampleur du problème.

Chaque langage nécessite ses compilateurs, ses outils et ses spécialistes. De plus, certains systèmes militaires restent en service pendant plusieurs décennies. Le logiciel doit donc pouvoir évoluer longtemps après le départ de l’équipe qui l’a créé.

Le DoD cherche alors un langage commun adapté aux systèmes embarqués. Celui-ci doit permettre de construire de grands programmes, de contrôler précisément les données, de gérer plusieurs activités simultanées et de rester proche du matériel lorsque cela devient nécessaire.

Steelman : définir les besoins avant d’inventer le langage

Le projet Ada commence par un cahier des charges plutôt que par une syntaxe. À partir de 1975, le High Order Language Working Group (HOLWG) précise progressivement les besoins du futur langage.

Plusieurs documents se succèdent sous des noms volontairement imagés : Strawman, Woodenman, Tinman, Ironman, puis Steelman en 1978.

Steelman insiste notamment sur la fiabilité, la maintenabilité, l’efficacité, la programmation de grands systèmes, le traitement des erreurs et l’exécution concurrente. Parallèlement, les responsables étudient les langages déjà disponibles.

Aucun ne répond suffisamment à l’ensemble des exigences. Le DoD décide donc d’organiser une compétition pour concevoir un nouveau langage.

Jean Ichbiah et la proposition « Green »

Quatre projets concurrents reçoivent des noms de couleurs : Red, Green, Blue et Yellow. Cette désignation permet de concentrer l’évaluation sur les propositions plutôt que sur leurs auteurs.

Après une première sélection, Red et Green restent en compétition. En mai 1979, le DoD choisit finalement la proposition Green, développée par l’équipe de Jean Ichbiah chez CII-Honeywell-Bull.

Le projet appartient à la grande famille des langages structurés influencés par ALGOL et Pascal. Cependant, Ada va beaucoup plus loin dans la définition des types, la modularité, la programmation concurrente et l’organisation de grands logiciels.

Le nom Green disparaît alors. Le langage devient Ada, en hommage à Augusta Ada King, comtesse de Lovelace. En 1843, Ada Lovelace avait publié des notes détaillées sur la machine analytique de Charles Babbage, dont un algorithme destiné au calcul des nombres de Bernoulli.

De 1980 à Ada 2022

  • 1980 : publication de la première définition officielle sous la référence MIL-STD-1815.
  • 1983 : publication de la version stabilisée ANSI/MIL-STD-1815A-1983, appelée Ada 83.
  • 1987 : Ada devient une norme internationale ISO 8652.
  • 1995 : Ada 95 introduit notamment un modèle complet de programmation orientée objet et renforce les mécanismes temps réel.
  • 2007 : publication de l’amendement correspondant à Ada 2005.
  • 2012 : Ada 2012 introduit notamment les préconditions, postconditions et invariants dans le langage standard.
  • 2023 : publication de la norme ISO/IEC 8652:2023 correspondant à la révision appelée Ada 2022.

Le numéro 1815 du premier standard militaire n’est pas choisi au hasard : Ada Lovelace est née en 1815.

Un premier programme Ada

La syntaxe d’Ada privilégie les mots explicites. Un programme très simple peut s’écrire ainsi :

with Ada.Text_IO;
use Ada.Text_IO;

procedure Bonjour is
begin
   Put_Line ("Bonjour !");
end Bonjour;

with indique qu’une bibliothèque est nécessaire. Ensuite, procedure déclare ici le programme principal. Le bloc d’instructions commence par begin et se termine par end Bonjour.

Cette écriture paraît plus verbale que celle du C. Ce choix est volontaire : pour les concepteurs d’Ada, un programme destiné à vivre pendant des années doit avant tout rester compréhensible et vérifiable.

Le typage fort : donner un sens aux nombres

L’une des caractéristiques essentielles d’Ada est son typage statique fort. Le programmeur peut créer de nouveaux types représentant réellement des notions différentes.

type Metres   is new Float;
type Secondes is new Float;

Distance : Metres   := 100.0;
Temps    : Secondes := 9.58;

Metres et Secondes sont deux types distincts. Ada interdit donc de les mélanger implicitement, même si les deux utilisent une représentation numérique comparable.

L’intérêt apparaît immédiatement dans un logiciel technique. Une altitude, une vitesse, une température et un angle sont tous représentés par des nombres. Pourtant, ils n’ont pas la même signification. Ada permet ainsi au compilateur de détecter certaines confusions avant même l’exécution du programme.

Des valeurs que l’on peut limiter

Ada permet également d’inscrire certaines contraintes directement dans les déclarations. Un pourcentage peut, par exemple, être limité à l’intervalle de 0 à 100 :

subtype Pourcentage is Integer range 0 .. 100;

Charge : Pourcentage := 75;

Si une opération tente de produire une valeur incompatible avec cette contrainte, Ada peut détecter le problème. Selon le cas, le compilateur le signale directement ou un contrôle effectué pendant l’exécution déclenche une exception comme Constraint_Error.

Ainsi, le programmeur fournit au compilateur davantage d’informations sur ce que les données sont censées représenter. Cette philosophie distingue Ada de langages plus permissifs.

Les tableaux et la mémoire

La même logique s’applique aux tableaux :

type Tableau_Mesures is array (1 .. 10) of Float;

Mesures : Tableau_Mesures;

Les indices autorisés vont ici de 1 à 10. Par conséquent, un accès en dehors de cette plage provoque normalement un contrôle de contrainte.

Ada cherche ainsi à transformer certaines erreurs de programmation en anomalies détectables plutôt qu’en corruptions silencieuses de la mémoire. Bien sûr, cela ne rend pas automatiquement un programme correct. En revanche, le langage réduit plusieurs catégories de comportements dangereux.

Les paquetages : construire un grand programme par modules

Pour organiser de grands logiciels, Ada dispose de paquetages (packages). Ils regroupent des types, des constantes, des fonctions et des procédures appartenant à un même composant.

La spécification présente ce que le composant offre au reste du programme :

package Capteur is
   function Temperature return Float;
end Capteur;

Le corps contient ensuite son fonctionnement interne :

package body Capteur is

   function Temperature return Float is
   begin
      return 21.5;
   end Temperature;

end Capteur;

Un autre module peut ainsi utiliser le capteur sans connaître tous les détails de son implémentation. Cette séparation limite les dépendances et facilite donc la maintenance.

Les types privés : protéger les données internes

Les types privés permettent de cacher davantage la représentation d’une donnée. Imaginons, par exemple, un module chargé de gérer une batterie. Le reste du programme pourrait utiliser des opérations comme Lire_Charge ou Est_Faible sans savoir comment le module stocke réellement les informations.

Cette technique empêche une autre partie du programme de manipuler directement une donnée interne qui ne devrait pas lui être accessible. De plus, elle facilite les évolutions : l’implémentation peut changer sans modifier l’interface utilisée par les autres composants.

Les génériques : réutiliser un algorithme

Ada permet aussi d’écrire des composants génériques. Le programmeur définit une opération pour une catégorie de types, puis l’adapte à différents cas.

generic
   type Element is private;
procedure Echanger (A, B : in out Element);

Grâce à ce mécanisme, une même structure logicielle peut être réutilisée tout en conservant les contrôles du système de types. Cette propriété devient particulièrement utile dans les grands projets, où la duplication du code augmente les coûts de maintenance.

Les exceptions : prévoir les situations anormales

Ada intègre un mécanisme d’exceptions. Lorsqu’un événement empêche la poursuite normale d’un traitement, le programme peut prévoir une réaction particulière :

begin
   -- opérations susceptibles d'échouer
   null;
exception
   when Constraint_Error =>
      Put_Line ("Valeur hors limites");
end;

Une exception peut provenir du programme lui-même ou d’un contrôle défini par le langage. Une valeur hors limites peut, par exemple, déclencher Constraint_Error.

Le mécanisme ne résout évidemment pas le problème à lui seul. Il fournit toutefois au programme un moyen explicite de détecter une situation anormale et de décider comment y répondre.

Les tâches : plusieurs activités dans un même programme

Un système embarqué doit souvent effectuer plusieurs opérations simultanément : lire des capteurs, surveiller des alarmes, communiquer ou commander des actionneurs. Ada intègre directement la notion de tâche pour représenter ces activités concurrentes.

task Capteur;

task body Capteur is
begin
   loop
      Lire_Mesure;
      delay 0.1;
   end loop;
end Capteur;

Le langage fournit également des mécanismes de communication et de synchronisation entre tâches. Ada 95 ajoute notamment les objets protégés, qui facilitent l’accès contrôlé à des données partagées.

Cette prise en charge de la concurrence explique en partie l’intérêt d’Ada pour le temps réel, où certaines opérations doivent respecter des délais précis.

Un langage de haut niveau proche du matériel

Un logiciel embarqué ne peut pas toujours rester dans des abstractions de haut niveau. Il doit parfois communiquer directement avec un périphérique, traiter une interruption ou imposer la représentation exacte d’une donnée en mémoire.

Ada prévoit donc des mécanismes permettant de contrôler la représentation des données et de s’interfacer avec des composants matériels ou avec du code écrit dans d’autres langages.

Cette combinaison est fondamentale : le langage cherche à conserver les contrôles d’un environnement de haut niveau sans empêcher la programmation proche de la machine.

Ada 95, 2005, 2012 et 2022 : un langage qui continue d’évoluer

Ada 95 : la programmation objet

Ada 95 constitue la première grande révision du langage. Le projet, dirigé par S. Tucker Taft, ajoute notamment les types étiquetés (tagged types), l’héritage et la répartition dynamique des appels.

La révision améliore également les mécanismes destinés aux systèmes temps réel et introduit les objets protégés.

Ada 2005 : interfaces et temps réel

Ada 2005 enrichit le modèle objet, ajoute les interfaces et étend plusieurs bibliothèques standard. Cette révision intègre aussi le profil Ravenscar, conçu pour limiter les mécanismes de concurrence dans les systèmes temps réel qui exigent un comportement particulièrement prévisible.

Ada 2012 : les contrats entrent dans le langage

Ada 2012 permet d’exprimer directement des préconditions et des postconditions :

function Racine_Carree (X : Float) return Float
  with Pre  => X >= 0.0,
       Post => Racine_Carree'Result >= 0.0;

La précondition indique ce que l’appelant doit garantir avant l’exécution. À l’inverse, la postcondition décrit une propriété que le résultat doit respecter.

Le programme ne décrit donc plus seulement comment réaliser une opération. Il peut également exprimer une partie de ce qui doit être vrai avant et après cette opération.

Ada 2022

La révision la plus récente porte le nom d’Ada 2022. La norme internationale correspondante, ISO/IEC 8652:2023, paraît en 2023.

Elle poursuit l’évolution du même langage et améliore notamment les agrégats, les itérations, les contrats et plusieurs mécanismes liés à la programmation parallèle.

SPARK : quand le programme peut aussi être démontré

SPARK est un langage fondé sur Ada accompagné d’outils de vérification formelle. Il restreint certaines constructions difficiles à analyser et permet d’exprimer précisément des propriétés que le programme doit respecter.

L’outil GNATprove peut ensuite tenter de démontrer mathématiquement ces propriétés. Il peut notamment vérifier l’absence de lectures de variables non initialisées et démontrer l’absence de certaines erreurs d’exécution, comme un dépassement de tableau ou certaines erreurs arithmétiques.

Cette approche va plus loin qu’un test traditionnel. En effet, un test vérifie seulement un nombre limité de situations, tandis qu’une preuve cherche à établir une propriété pour tous les cas couverts par le modèle et les hypothèses utilisées.

Toutefois, SPARK ne peut pas prouver qu’une exigence oubliée est correcte. Une démonstration porte uniquement sur les propriétés réellement exprimées. La qualité de la spécification reste donc fondamentale.

Ada dans le monde réel : du métro à l’espace

Ada n’est pas resté cantonné aux projets militaires. On le retrouve dans les transports, le spatial, l’aéronautique et le contrôle aérien. Tous ces domaines ont un point commun : une erreur logicielle peut produire des conséquences physiques importantes.

La ligne 14 du métro parisien

Le projet Météor, devenu la ligne 14 du métro parisien, constitue un exemple remarquable. Les logiciels de sécurité de son système automatique ont fait appel à la méthode formelle B et à Ada.

CLEARSY indique que le projet représentait plus de 110 000 lignes de modèles B, traduites en environ 86 000 lignes de code Ada. La ligne entre en service en 1998.

La méthode B permet de construire un modèle mathématique du comportement attendu, puis de démontrer certaines propriétés avant la production du logiciel. Ada sert ensuite de langage pour le code correspondant.

Il serait donc trop simplificateur d’écrire que « le métro parisien est programmé en Ada ». En revanche, on peut affirmer qu’Ada joue un rôle dans les logiciels critiques du pilotage automatique des lignes 14 et 1.

La Station spatiale internationale

Ada a également trouvé sa place dans l’espace. Un document technique de la NASA consacré aux logiciels de vol indique que le logiciel de vol de l’ISS associait du code Ada écrit manuellement et des composants issus de l’environnement de modélisation MatrixX.

Dans ce type de système, la fiabilité prend une importance particulière. Les logiciels doivent contrôler des équipements complexes pendant de longues périodes et réagir de manière prévisible aux situations anormales.

Ariane 5 : les limites d’un langage sûr

Le premier vol d’Ariane 5, le 4 juin 1996, fournit un contre-exemple particulièrement instructif. Le logiciel de son système de référence inertielle comportait du code Ada.

Une conversion d’une valeur en virgule flottante sur 64 bits vers un entier signé sur 16 bits provoque une exception. Une partie du logiciel provenait d’Ariane 4 et reposait sur une hypothèse qui ne convenait plus à la trajectoire d’Ariane 5.

Les deux systèmes inertiels, principal et redondant, rencontrent alors le même problème. Le lanceur perd ses informations de guidage, s’écarte de sa trajectoire et se détruit peu après.

L’enquête de l’ESA attribue l’accident à des erreurs de spécification et de conception du logiciel. Le cas Ariane 5 rappelle donc une règle essentielle : un langage sûr ne peut pas rendre correcte une hypothèse de conception erronée.

Ada détecte bien une situation anormale en déclenchant une exception. Le problème vient de l’architecture logicielle, qui n’avait pas prévu une réponse permettant au système de poursuivre correctement son fonctionnement.

Le contrôle aérien britannique

Le système britannique iFACTS (Interim Future Area Control Tools Support) utilise SPARK Ada. Il fournit aux contrôleurs aériens des outils de prédiction de trajectoires et de détection de conflits.

Selon les publications consacrées au projet, le logiciel comprend plus de 200 000 lignes de SPARK. iFACTS entre en service au centre de contrôle NATS de Swanwick en 2011.

Le contrôle aérien illustre bien l’intérêt de cette famille de langages : le logiciel doit effectuer de nombreux calculs tout en fournissant un comportement extrêmement prévisible.

Pourquoi Ada convient-il aux systèmes critiques ?

Les exemples précédents permettent de mieux comprendre les caractéristiques recherchées :

  • typage fort : le compilateur peut empêcher certains mélanges de données incohérents ;
  • plages de valeurs : le programme peut exprimer les limites acceptables d’une donnée ;
  • contrôles d’exécution : Ada détecte de nombreuses violations de contraintes ;
  • modularité : les paquetages séparent clairement les interfaces des implémentations ;
  • concurrence : les tâches et les objets protégés font partie du langage ;
  • temps réel : Ada fournit des mécanismes adaptés aux systèmes soumis à des contraintes temporelles ;
  • contrats : les versions modernes peuvent exprimer préconditions, postconditions et invariants ;
  • vérification formelle : SPARK permet de démontrer certaines propriétés du programme ;
  • accès au matériel : Ada reste utilisable pour la programmation de bas niveau.

Aucune de ces caractéristiques ne garantit à elle seule qu’un logiciel est correct. Ensemble, elles donnent cependant au compilateur et aux outils d’analyse davantage de possibilités pour détecter une incohérence avant qu’elle ne provoque une défaillance.

Le « mandat Ada » du DoD

Le gouvernement américain ne se contente pas de financer Ada. En 1983, le sous-secrétaire à la Défense Richard DeLauer impose son utilisation pour les nouvelles applications critiques, avec un système de dérogations.

Puis, en 1987, la directive DoD 3405.1 étend cette politique à une grande partie des nouveaux développements et acquisitions concernés.

Cette obligation accélère l’adoption d’Ada dans la défense. Elle montre cependant aussi ses limites : un projet peut choisir un langage pour de mauvaises raisons simplement parce qu’une administration l’impose.

En 1997, le National Research Council recommande donc une approche plus souple. Le DoD abandonne alors l’obligation générale d’utiliser Ada et revient à une sélection des technologies davantage fondée sur les besoins du projet.

Pourquoi Ada n’a-t-il pas remplacé C et C++ ?

Ada possède de nombreuses qualités techniques, mais un langage ne s’impose pas uniquement grâce à sa conception. C puis C++ bénéficient d’un immense écosystème de compilateurs, de bibliothèques, de systèmes d’exploitation, de constructeurs et de programmeurs.

Par ailleurs, les premiers compilateurs Ada demandent beaucoup de travail. La richesse du langage et la volonté de contrôler strictement la conformité compliquent leur développement. Pendant les années 1980, les outils restent donc souvent coûteux.

L’association d’Ada avec le secteur militaire limite également son image auprès du grand public et de certains milieux universitaires ou commerciaux.

Le langage trouve par conséquent sa place principalement là où ses qualités compensent le coût d’un environnement plus spécialisé : avionique, spatial, défense, ferroviaire, contrôle aérien et autres logiciels à haute intégrité.

GNAT : Ada devient accessible à tous

La situation change avec GNAT, le compilateur Ada intégré à l’écosystème GNU. Grâce à lui, un étudiant ou un développeur peut installer un compilateur Ada sur un ordinateur courant sans disposer d’un environnement industriel spécialisé.

GNAT prend en charge les versions modernes du langage. Il constitue également la base de nombreux outils professionnels utilisés avec Ada et SPARK.

Un langage exigeant, pas un langage magique

Opposer simplement Ada, qui serait « sûr », à C, qui serait « dangereux », donne une vision trop simpliste. Ada cherche effectivement à empêcher ou à détecter plusieurs catégories d’erreurs que C laisse davantage sous la responsabilité du programmeur.

Cependant, Ada reste un langage de programmation système. Il permet des opérations de bas niveau et certaines constructions dont le programmeur doit maîtriser les conséquences.

Sa différence tient surtout à sa philosophie : exprimer le plus clairement possible l’intention du programmeur afin de permettre au compilateur et aux outils de la vérifier.

Ainsi, un type indique ce qu’une donnée représente. Une plage précise les valeurs possibles. Un paquetage définit une interface. Un contrat décrit les conditions d’une opération. Enfin, une tâche exprime une activité concurrente.

Cette discipline peut demander davantage de travail au départ. Elle devient particulièrement intéressante lorsque le logiciel doit ensuite être testé, certifié, maintenu et modifié pendant plusieurs décennies.

Un héritage particulier dans l’histoire de l’informatique

Ada n’a jamais atteint la diffusion générale du C, de C++ ou de Java. Son importance historique se mesure autrement. Il représente l’une des tentatives les plus ambitieuses pour considérer un langage de programmation comme un véritable outil d’ingénierie logicielle.

Son histoire repose sur trois idées principales :

  • réduire la fragmentation des langages utilisés pour les grands systèmes du DoD ;
  • détecter les incohérences le plus tôt possible grâce aux types, aux contraintes et aux outils ;
  • construire des logiciels durables et vérifiables tout en conservant les capacités nécessaires au temps réel et à la programmation proche du matériel.

Plus de quarante ans après sa création, Ada continue donc d’occuper une place particulière. Il reste relativement discret sur les ordinateurs personnels et le Web. En revanche, on le retrouve là où le logiciel doit fonctionner longtemps et où une erreur peut avoir des conséquences bien réelles.

Sources principales


Illustration de couverture : Jean Ichbiah devant un terminal informatique, illustration générée par intelligence artificielle avec ChatGPT (OpenAI), d’après l’iconographie historique disponible.

Publications similaires

  • Fortran

    FORTRAN, contraction de FORmula TRANslation (« traduction de formules »), est l’un des langages les plus importants de l’histoire de l’informatique. Développé chez IBM sous la direction de John Backus, il permet aux scientifiques et aux ingénieurs d’écrire leurs calculs sous une forme beaucoup plus proche des mathématiques que des instructions d’une machine.Lorsque le premier…

  • Le langage C

    Le nom C n’est pas un sigle. Il succède au langage B, lui-même issu de BCPL. Le langage qui a rendu Unix portable Au début des années 1970, programmer un système d’exploitation signifie encore travailler presque entièrement en assembleur. Cette méthode permet de contrôler précisément la machine, mais elle exige beaucoup de temps et lie…

  • BASIC

    Le nom BASIC vient de Beginner’s All-purpose Symbolic Instruction Code : un langage pensé pour que des débutants puissent enfin dialoguer avec l’ordinateur. Le langage qui a fait entrer la programmation dans les salles de classe Au début des années 1960, l’ordinateur reste encore une machine distante, coûteuse et intimidante. Dans beaucoup d’universités ou de…

  • COBOL

    COBOL, acronyme de Common Business-Oriented Language, est un langage de programmation créé à partir de 1959 pour répondre à un problème devenu crucial : comment écrire des programmes de gestion capables de fonctionner sur des ordinateurs provenant de constructeurs différents ? À la fin des années 1950, IBM, UNIVAC, RCA, Honeywell, Burroughs et d’autres fabricants…

  • FLOW-MATIC

    FLOW-MATIC est un langage de programmation développé dans les années 1950 par l’équipe de Grace Hopper chez Remington Rand, puis Sperry Rand UNIVAC. Conçu pour le traitement des données commerciales, il poursuit une idée alors audacieuse : permettre au programmeur de décrire les opérations à effectuer avec des mots proches de l’anglais courant plutôt qu’avec…

  • BCPL

    BCPL signifie Basic Combined Programming Language : une version simplifiée de CPL, conçue pour écrire des compilateurs et des logiciels système plus faciles à transporter d’une machine à l’autre. Au milieu des années 1960, les langages de programmation deviennent plus expressifs, mais leurs compilateurs restent souvent longs et difficiles à adapter. Un langage peut être…