Ce texte est extrait de mon livre Systèmes d'information, obstacles et succès, paru en mars 2005 aux Éditions Vuibert. Avec l'aimable autorisation de l'éditeur.
Page d'accueil de ce livre
#Sommaire-
De la nature de l'informatique
Premières croyances
Les premiers ordinateurs, qui entrèrent en fonction à l'extrême fin des années 1940 et durant les années 1950, étaient consacrés à des travaux militaires ou scientifiques puisque, à cette époque, on pensait qu'ils seraient utiles essentiellement aux calculs des physiciens. Le projet phare de ces années fut SAGE (Semi-Automatic Ground Environment), système de traitement des données issues des radars de défense anti-aérienne, destiné à prémunir les États-Unis contre une attaque nucléaire soviétique, dont le coût final atteignit huit milliards de dollars de l'époque. D'autres projets militaires d'une ampleur comparable permirent la naissance et l'expansion d'une population de professionnels de la programmation des ordinateurs et, au bout du compte, l'apparition d'une véritable industrie du logiciel, bien décrite par Martin Campbell-Kelly [1]. Cet afflux de financements militaires joua un rôle de premier plan dans l'élan initial de l'industrie informatique américaine.
Il ne fait aucun doute que lors de ces premières réalisations informatiques la part du logiciel fut considérablement sous-estimée tant sur le plan financier que sur ceux de la durée et de la complexité du travail à accomplir. On s'imaginait en être quitte avec quelques dizaines de lignes de langage machine écrites sur un coin de table pour faire marcher les ordinateurs qui, eux, exhibaient les signes extérieurs de leur prix élevé en pesant des dizaines de tonnes et en consommant des centaines de kilowatts-heure d'électricité. Aussi les dépassements de coûts et de délais furent-ils la règle et engendrèrent-ils frustrations et déceptions ; c'est d'ailleurs encore le cas aujourd'hui.
Les premiers programmeurs étaient des scientifiques recrutés pour leurs compétences en analyse numérique et en algèbre linéaire, puisqu'il s'agissait essentiellement, croyait-on, de résoudre des équations différentielles et d'inverser des matrices. Ces problèmes mathématiques furent d'ailleurs résolus sans soulever de difficultés insurmontables, même si l'application de l'informatique aux problèmes numériques reste un domaine de recherche actif, et le restera tant que les physiciens continueront à inventer de nouvelles équations pour modéliser de nouveaux problèmes. Ce qui est erroné n'est donc pas d'attribuer à ces problèmes de numériciens une place dans la science informatique, c'est d'imaginer cette place comme centrale et absolument décisive. Une conséquence éminemment visible de cette erreur se donne à voir en France (terre particulièrement affectée par elle) où le principal institut public de recherche en informatique a été animé, puis dirigé, de sa création en 1967 jusqu'à la fin de l'année 2003 par des numériciens purs qui avaient de l'informatique une vision très unilatéralement mathématique et numérique, pour ne pas dire très peu informatique.
Comment l'informatique diffère des mathématiques
J'aimerais à l'occasion de cette analyse attirer l'attention du lecteur sur une question qui est une source constante de malentendus au sujet de la programmation.
Il y a fort longtemps, à l'INSEE, un de mes collègues informaticiens débattait avec un statisticien, issu d'une grande école scientifique de la République, d'un projet informatique que le premier aurait à réaliser pour le second. L'informaticien expliquait le délai nécessaire à ce projet par la longueur des développements, due notamment à la nécessité de procéder à des essais pour éliminer les erreurs qui se seraient glissées dans les programmes. Cette démarche scandalisait le statisticien : « Quand je résous une équation différentielle, » disait-il, « je ne fais pas d'erreur, pourquoi en commettez-vous dans vos programmes ? ». L'auteur pourrait simplement rétorquer, d'expérience personnelle, qu'il arrive que l'on commette des erreurs en résolvant des équations différentielles, mais en fait la question n'est pas là. La démarche du calcul mathématique, pour qui en a acquis une maîtrise suffisante pour tel ou tel type de problème, comporte dans son déroulement même un dispositif d'auto-vérification. L'enchaînement des égalités qui conduisent à la solution obéit à des règles formelles et précises telles que les erreurs doivent, en principe, sauter aux yeux. L'imagination intervient dans l'élaboration de l'expression qui va faire progresser le calcul, et c'est pour cela que la résolution des problèmes mathématiques ne peut pas être confiée à un automate, fût-il un ordinateur, mais une fois cette expression rédigée et écrite au tableau, sa capacité à vérifier la relation d'égalité avec l'expression précédente est, pour quelqu'un qui s'y connaît, immédiatement perceptible.
Les preuves de programme
L'écriture de programmes informatiques obéit à de tout autres principes. Il convient de préciser cette affirmation pour la préserver d'une réfutation facile : du fait de sa naissance dans un milieu fortement influencé par le calcul mathématique, l'informatique a connu, et connaît encore, une activité assez intense de théoriciens qui entendent développer ce que l'on appelle des méthodes de preuve formelle, destinées à conférer à l'écriture de programmes la même capacité auto-vérificatrice que les équations mathématiques sont censées posséder. La recherche dans le domaine de la démonstration automatique de théorèmes n'a jamais cessé d'être active. Il serait erroné de nier l'influence notable que ces recherches ont exercée sur l'orientation prise, notamment, par la conception des langages et des outils de programmation. Mais le programme que chacun utilise quotidiennement pour écrire son courrier ou son livre, naviguer sur le WWW, faire la comptabilité de son entreprise ou jouer sur sa console de jeux a selon toute vraisemblance été écrit par des programmeurs qui n'en avaient même jamais entendu parler. Ce serait peut-être moins vrai pour le logiciel qui pilote Ariane V ou une centrale nucléaire, sans d'ailleurs que cela garantisse le moins du monde l'absence d'erreurs de programmation, l'expérience le prouve. En fait, de tels logiciels comportent un si grand nombre de lignes de texte (un programme, c'est un texte) qu'il serait irréaliste d'en entreprendre la preuve, si tant est que ce soit possible ; on se contente d'essayer de « prouver » les parties jugées les plus critiques, quitte à s'apercevoir plus tard, lorsqu'une erreur survient et amène la destruction d'Ariane V et de sa charge utile, que la criticité n'était pas là où on l'attendait... et l'erreur pas dans le logiciel (cf. Gérard Le Lann, The Failure of Ariane 5 flight 501, 1999). Bref, le logiciel, par nature, comporte des erreurs, encore et toujours. Nous aurons néanmoins l'occasion d'évoquer des méthodes réalistes de spécification formelle de programmes sûrs, par exemple à la section consacrée à la méthode B, et au chapitre 8 qui abordera les projets d'informatique industrielle et technique.
Si les auteurs de programmes réels ignorent les méthodes de preuves formelles, ce n'est pas toujours par incompétence ou négligence : ces méthodes sont souvent inadaptées à leur travail, nombre d'entre elles ont été imaginées par des théoriciens universitaires très éloignés de leur pratique. Il ne fait aucun doute qu'un rapprochement entre ces deux démarches serait fructueux pour les uns et pour les autres, mais aujourd'hui en France cela ne peut arriver qu'exceptionnellement pour deux raisons : l'informatique universitaire y est dominée par des mathématiciens réformés surtout désireux de ne jamais avoir affaire à un ordinateur, d'autre part l'accès aux formations professionnelles informatiques est artificiellement limité par des effectifs insuffisants et par des exigences excessives de niveau en mathématiques, ce qui a pour conséquence qu'une grande proportion des professionnels de l'informatique ne possède pas de diplôme et n'a qu'une formation acquise sur le tas ou auprès des fournisseurs, c'est-à-dire totalement dépourvue de bases théoriques.
Cette situation évolue depuis quelques années : la méthode B a commencé à obtenir des résultats convaincants. L'équipe LogiCal, qui associe des chercheurs de l'INRIA (Institut National de Recherche en Informatique et en Automatique) et du Laboratoire de Recherche en Informatique d'Orsay (LRI), a développé le logiciel Coq, un « assistant de preuve » prometteur doublé d'un langage de programmation sûr.
Programmation dans le monde réel
La vraie nature de la programmation des ordinateurs
Alors, comment s'écrivent les programmes informatiques ? Et d'ailleurs, qu'est-ce qu'une erreur de programmation ? Ces questions sont liées et elles sont, bien sûr, au cœur de notre préoccupation.
Si les énoncés des mathématiques sont auto-vérifiables, ou en tout cas nettement plus vérifiables que les énoncés du langage humain courant, c'est par la vertu de la méthode axiomatique, qui place au fondement de chaque théorie mathématique un corpus d'axiomes que les nouvelles propositions de la théorie devront respecter, et d'un formalisme rigoureux garantissant la solidité d'une démarche qui progresse d'hypothèses en conclusions par des transitions claires et sans ambiguïtés. Enfin, en principe. Kurt Gödel et d'autres ont montré les limites de cette méthode, qui n'en prête pas moins aux assertions des mathématiciens des fondations d'une exceptionnelle solidité, dans les limites de la théorie, s'entend.
Pour expliciter la démarche mathématique, les logiciens du XXe siècle ont élaboré la notion de système formel, déjà suggérée par Leibniz plus de deux siècles auparavant. C'est important pour notre propos, parce que si les systèmes formels ont eu un succès modéré auprès des mathématiciens qui affectent le plus souvent de négliger cette question des fondements, ils sont à l'origine de la théorie des ordinateurs. En voici la définition empruntée à l'encyclopédie Hachette Multimédia en ligne sur Yahoo :
« Le système formel est une notion logique fondamentale issue du double effort de constituer une logique mathématique et d'axiomatiser les théories mathématiques usuelles. Cet effort procède d'un idéal de rigueur — éviter les recours non contrôlés à l'intuition, expliciter toutes les hypothèses effectivement utilisées dans un raisonnement, par exemple — qui s'est diversement affirmé à partir de la fin du XIXe siècle. Les travaux de Frege, de Dedekind, de Peano, de Hilbert, de Whitehead et Russell, de Gödel jalonnent brillamment cet effort. Ils contribuent à mettre au centre de l'intérêt des logiciens l'analyse de l'idée de démonstration, ou, comme on dit encore, de déduction, de dérivation ou d'inférence. »
Nous pourrions ajouter à cette liste de logiciens l'Argentin Alonzo Church, créateur du λ-calcul, formalisme destiné à l'étude des fonctions mathématiques et qui a engendré le langage de programmation Lisp. Un disciple britannique de Church, Alan Turing, a cherché à préciser la nature des procédures effectives de Gödel, qui disait qu'un système était décidable s'il existait une procédure effective pour distinguer les propositions démontrables des autres. Inventer une procédure effective (un algorithme) consiste à déterminer un enchaînement d'opérations élémentaires qui exécuteront les calculs nécessaires à la solution d'un problème pour lequel existe une solution calculable (il y a des problèmes sans solution et des solutions incalculables). Une procédure effective doit recevoir une définition finie, et chacune de ses étapes doit pouvoir être exécutée mécaniquement. Pour clarifier cela, Turing a défini en 1936 le modèle théorique nommé machine de Turing, laquelle forme depuis lors avec le λ-calcul la base de la théorie des langages de programmation. Enfin le Hongrois naturalisé américain John von Neumann a élaboré en 1945 à partir de ces travaux théoriques le modèle concret de l'ordinateur, encore valable aujourd'hui et connu sous le nom d'architecture de von Neumann.
La science de la programmation des ordinateurs, qui constitue le cœur de l'informatique, est donc déterminée par un lien de filiation avec les mathématiques, ou plutôt (la nuance a son poids) avec l'étude logique des opérations des mathématiques. Le champ de cette étude logique qui a engendré l'informatique est organisé autour de la notion de procédure effective, dont le propos est de cerner précisément la suite des opérations concrètes par lesquelles s'effectue un calcul [2] ; ou, pour déjà parler informatique, la suite des opérations qui à partir de certaines données produiront certains résultats, constituant ainsi un traitement.
C'est pour définir sans ambiguïté des procédures effectives que Turing a imaginé la machine de Turing. Dès lors que l'on possédait le modèle théorique du calcul, la tentation de construire un automate capable de l'incarner était inévitable, et c'est ce que fit von Neumann.
Le propos d'un programme informatique n'est pas de démontrer un théorème à partir de certains axiomes et de certaines hypothèses, mais d'effectuer un traitement qui à partir de certaines données produira certains résultats. Pour se fixer les idées on pourra prendre comme exemple de traitement la multiplication de deux nombres selon la méthode apprise à l'école primaire, qui constitue un algorithme parfaitement transposable tel quel en programme informatique. Le traitement des données doit être effectif, c'est-à-dire que la méthode de passage doit pouvoir aboutir pratiquement au résultat. Le traitement comportera des étapes, en nombre fini. Chaque étape consistera à élaborer à partir des données initiales un état du calcul ; les états successifs du calcul doivent conduire au résultat final ; pour progresser d'étape en étape ces états successifs doivent être enregistrés : pour l'écolier armé de son crayon, ce sera sur sa feuille de cahier ; pour l'ordinateur ce sera dans sa mémoire. L'organe de l'ordinateur qui effectue les calculs est nommé processeur ; chaque étape du traitement est accomplie par une action du processeur ; une action du processeur consiste à modifier, à affecter la mémoire, éventuellement après avoir consulté son état précédent, pour y consigner le nouvel état du calcul ; c'est très précisément ces opérations de consultation et d'affectation de la mémoire que formalise la machine de Turing ; le calcul sera terminé lorsque la mémoire sera dans un état qui contienne le résultat recherché. À certaines étapes du calcul la procédure effective doit comporter la possibilité de choisir entre deux actions possibles en fonction des résultats intermédiaires — par exemple y a-t-il une retenue ou pas : la machine de Turing est dotée de cette capacité. Ainsi on dit d'un automate capable de reproduire le fonctionnement d'une machine de Turing quelconque qu'il possède l'équivalence turingienne.
Nous avons introduit la notion de mémoire en notant qu'une action du processeur consistait à consulter ou à modifier l'état de la mémoire. Cette définition de l'action est très importante, elle trace la ligne de séparation entre la conception mathématique traditionnelle du calcul et la conception informatique liée à la notion de procédure effective. La mathématique ignore cette notion d'état, qui introduirait dans son univers d'abstraction un aspect physique totalement incongru.
L'informatique, et plus précisément la programmation des ordinateurs, confère au calcul une dimension concrète, effective. C'est un peu comme si le papier sur lequel le mathématicien inscrit les signes du calcul avec un crayon acquérait un statut théorique. Ce passage permanent de l'abstrait au concret est d'ailleurs l'agrément suprêmement fascinant de la programmation : dire c'est faire. J'énonce la formule d'une action, et la machine l'exécute. Les lignes qui précèdent n'ont d'autre but que d'évoquer pour le lecteur ce qui apparente mathématiques et informatique, et ce qui les distingue. La dimension effective de la programmation des ordinateurs confère (impose) au calcul informatique une activité physique de construction de la solution, enregistrée dans les circuits électroniques de la mémoire de l'ordinateur (le mot anglais storage, emmagasinage, suggère mieux la nature de son rôle). La tâche du programmeur consiste donc à décrire les étapes successives de cette construction, au moyen d'un langage de programmation.
Langages de programmation
Un processeur quelconque est caractérisé par le jeu des actions élémentaires qu'il est capable d'effectuer. Ces actions élémentaires sont appelées les primitives du processeur, ou, si le processeur est une machine, les « instructions machine ». Un programme pour un processeur de von Neumann est une suite de primitives (d'instructions machine) du processeur destiné à l'exécuter. Chacune de ces instructions élémentaires correspond à un circuit logique du processeur considéré. L'ensemble des instructions machine et des règles de leur rédaction constitue le langage machine [3].
Une idée capitale du modèle de von Neumann, c'est d'enregistrer le texte du programme dans la mémoire de l'ordinateur, comme les données, et de considérer en fait ce texte exactement comme s'il s'agissait de données. Cette idée unificatrice permet d'appliquer aux programmes les mêmes traitements qu'aux données, de considérer le contenu d'un programme comme de l'information. Cela aura des conséquences évoquées plus loin.
Les premiers programmes d'ordinateur étaient écrits en langage machine, mais cela avait plusieurs inconvénients. D'abord c'était extrêmement difficile et long, parce que les instructions machine sont très élémentaires et très proches de la structure interne du processeur, et induisent une formulation très rigide et malcommode. Ensuite, chaque processeur a un langage machine différent, et il faut donc réécrire le programme chaque fois que l'on change d'ordinateur.
Pour pallier ces difficultés furent inventés les langages évolués, dont le premier fut Fortran créé par John Backus en 1954, suivi de Lisp et Cobol, puis C, Ada, Java et bien d'autres. Un langage évolué est un méta-langage par rapport au langage machine, un programme en langage évolué doit être traduit en langage machine pour pouvoir être exécuté par un ordinateur. Le programme qui effectue cette traduction est généralement appelé compilateur. Pour exécuter un programme donné écrit en langage évolué sur plusieurs types d'ordinateurs, il suffit de disposer pour chaque type d'ordinateur d'un compilateur de ce langage, qui traduira le programme initial vers le bon langage machine. Un langage évolué est donc inséparable de ses compilateurs.
Il peut y avoir plusieurs niveaux de langages évolués, un langage de haut niveau étant traduit vers un langage de plus bas niveau, lequel sera par exemple traduit en langage machine. Tout cela est un peu plus compliqué dans la réalité, il faudrait parler du système d'exploitation qui s'interpose entre le programme et l'ordinateur, comme en fait un super-programme qui présente au programmeur une vision plus abstraite de l'ordinateur, et aussi d'un langage tel que Java qui est utilisé selon un schéma un peu différent, mais ces nuances ne sont pas ce qui importe ici, encore une fois je renvoie le lecteur qui en serait curieux à mon livre consacré à ce sujet, ou à d'autres ouvrages d'excellents auteurs, notamment ceux d'Andrew Tanenbaum [4] [5] [6].
Les erreurs de programmation
Les explications données ci-dessus nous permettent de préciser ce que sont les erreurs de programmation, et en quoi elles se distinguent des erreurs de calcul ou de logique qui peuvent affecter une démonstration mathématique.
Le texte d'un programme informatique est constitué d'instructions qui effectuent des actions, ou d'expressions dont l'évaluation se traduit par des actions, selon le langage utilisé. Ces actions sont des modifications de l'état de la mémoire. Un langage pratiquement utilisable devra donc disposer d'un jeu de primitives suffisamment riche pour exprimer les différentes actions souhaitables, et cette richesse aura comme conséquence une grande complexité. L'initiation à un langage de programmation demande à un étudiant motivé plusieurs dizaines d'heures de cours et beaucoup plus encore d'exercices pratiques, pour en posséder juste les rudiments.
Le premier type d'erreur que le programmeur peut commettre est l'erreur de syntaxe, la violation des règles qui régissent le langage utilisé. Une erreur de ce type est bénigne, parce que le plus souvent le programme de traduction utilisé (le compilateur) la détectera et donnera des explications qui aideront à sa correction. On suivra pour l'éviter un conseil de Jacques Arsac : ne jamais programmer sans avoir le manuel du langage sous la main.
Un second type d'erreur est de nature sémantique : le programmeur a mal compris le manuel du langage, et il écrit un texte dont il pense qu'il va donner le résultat voulu, alors qu'il va donner un autre résultat, ou un programme faux, qui ne se termine pas, ou qui se termine par une erreur explicite. Une des qualités d'un programmeur expert, c'est de bien connaître la sémantique du langage qu'il utilise, connaissance qui demande des années de pratique assidue. Et il faut avoir le manuel du langage sous la main.
L'exécution d'un programme informatique peut aussi échouer pour une raison qui n'est pas à proprement parler une erreur de programmation, mais qui doit néanmoins retenir l'attention, parce que ce type d'incident est très fréquent : ce sont les échecs provoqués par le contexte technique. Ainsi, un programme qui écrit des données sur disque peut échouer si le disque est plein. La saturation de la mémoire est une autre cause d'échec courante. En principe ces circonstances sont prévisibles par celui qui lance le programme, mais pas par celui qui l'écrit.
Mais une fois vaincues ces erreurs techniques, restent les vraies erreurs de programmation ; elles résultent d'une mauvaise interprétation de l'énoncé du problème à résoudre, ou du choix d'un algorithme inapproprié, ou d'une programmation fautive de l'algorithme, c'est-à-dire que le programmeur aura écrit un texte qui commande des actions qui ne conduisent pas au résultat voulu. On aura compris de ce qui précède que l'élaboration d'un programme pour résoudre un problème est une démarche de construction de la solution, par induction. Il faut imaginer les actions à effectuer ; les méthodes de preuve de programmes évoquées ci-dessus et sur lesquelles nous reviendrons ne pourront aider que dans certains cas assez particuliers, parce qu'elles sont trop lourdes pour être appliquées à l'ensemble d'un programme ; la plupart du temps il n'y a rien qui puisse fournir au programmeur l'équivalent du caractère auto-vérificateur du calcul mathématique, d'abord parce que la programmation n'est généralement pas une démarche déductive, mais aussi parce que le texte d'un programme est considérablement plus volumineux que celui d'un calcul mathématique ordinaire : la taille d'un petit programme vraiment utile pour un usage professionnel pourra difficilement descendre en dessous de 10 000 lignes de texte, un programme moyen aura plusieurs centaines de milliers de lignes, un système d'exploitation général plusieurs millions, plusieurs dizaines de millions si l'on y inclut les interfaces graphiques interactives.
Il y a par contre des méthodes de programmation destinées à limiter le risque d'erreur, qui feront l'objet de la section suivante. Le dernier mot reste sur ce sujet à Peter J. Denning : « il n y a pas de règles immuables à suivre pour écrire un programme logique, efficace et lisible. Il y a bien sûr des guides, et certains sont meilleurs que d'autres ; mais c'est le style du programmeur (ou son absence de style), sa clairvoyance (ou non), sa créativité (ou son absence) qui déterminent la qualité du produit final. »
Méthodes de programmation
L'invention et le perfectionnement des langages évolués allant de pair avec la prise de conscience de l'importance du logiciel et de sa difficulté, la question des langages de programmation, initialement posée en fonction du processeur, fut de plus en plus posée en fonction du programmeur. Pour écrire le plus vite possible des programmes comportant le moins d'erreurs possible, il faut disposer de langages adaptés. La linguistique de la programmation, c'est-à-dire la recherche dans le domaine de la conception, de la réalisation et de l'utilisation des langages de programmation, devint une des branches principales de la science informatique. La puissance limitée des premiers ordinateurs avait orienté cette recherche vers la conception de langages faciles à traduire, donc à compiler, ce qui facilitait la tâche de l'ordinateur. Dès les années 1960 la préoccupation principale devint la facilité à écrire des programmes aussi corrects et aussi lisibles que possible. L'évidence s'est en effet imposée qu'un programme est lu beaucoup plus souvent par des êtres humains, tels que son ou ses auteurs, ceux qui en assureront la maintenance ou qui devront le modifier, que par un compilateur. Les réalisations techniques marquantes de ce courant de pensée furent les langages Algol-60, Algol-68, PL/1, Pascal et Ada, les chercheurs les plus en vue, Edsger Dijkstra, C.A.R. Hoare, Peter Naur, Donald Knuth, Alan J. Perlis... La première qualité attendue d'un langage est, bien sûr, l'équivalence turingienne, c'est-à-dire l'aptitude à exprimer sans ambiguïtés tout algorithme formalisé par une machine de Turing, mais ces chercheurs ont ajouté à cette exigence l'expressivité et la lisibilité.
L'expressivité doit être entendue à la fois comme la puissance d'expression, la capacité à exprimer une opération complexe par un formalisme aussi simple que possible, et comme la qualité de l'expression, le fait que le texte du formalisme suggère facilement sa signification au lecteur.
La linguistique de la programmation se préoccupe des aspects morphologiques et syntaxiques des langages, mais aussi des problèmes soulevés par la rédaction de textes assez longs, soit des méthodes de construction de programmes, dont il sera question à la section suivante de ce chapitre.
Méthodes de construction de programmes
Nous avons décrit ci-dessus le processus élémentaire de la programmation, celui qui consiste à écrire les instructions ou les expressions qui vont composer un programme. Un grand logiciel est constitué de centaines de milliers ou de millions de lignes de texte, le nombre de lignes étant souvent assez proche du nombre d'instructions ou d'expressions élémentaires, auquel il convient d'ajouter les lignes de commentaire qui sont du texte en langage humain, destiné à faciliter la lecture du programme.
Écrire un programme d'un seul tenant qui compterait des centaines de milliers de lignes serait très difficile, y retrouver et en corriger les erreurs serait une entreprise pratiquement impossible. Aussi a-t-on élaboré des méthodes pour découper de grands programmes en unités plus petites, plus faciles à écrire et à mettre au point séparément, puis réunies pour composer des ensembles plus importants, un peu comme un livre est découpé en parties, chapitres et sections, avec une table des matières et un index pour aider à s'y retrouver. Ces unités de programme peuvent être appelées sous-programmes.
Le premier problème à résoudre pour permettre le découpage des programmes en sous-programmes est d'organiser la circulation des données entre les sous-programmes selon des règles qui respectent le principe d'équivalence turingienne. Toujours dans l'idée de rechercher clarté, lisibilité et expressivité, des pistes nouvelles ont été explorées pour structurer l'information de façon à faciliter la tâche des humains, qu'ils en soient rédacteurs ou lecteurs.
La programmation structurée
Le premier courant de pensée qui associa la recherche d'une syntaxe claire et expressive à une organisation logique et commode des unités de programme fut la programmation structurée des années 1970, dont les leaders Dijkstra, Niklaus Wirth et Hoare étaient issus du courant Algol. Cette école fut représentée en France par Jacques Arsac et Bertrand Meyer.
Pour réaliser un programme, il semble logique d'adopter une démarche « de haut en bas » (top-down) : étant donné le problème à résoudre, je le divise en sous-problèmes plus élémentaires et faciles, que je divise eux-mêmes en sous-problèmes, jusqu'à ce que j'obtienne une collection de problèmes simples, dont je programme les solutions sous forme de sous-programmes qu'il ne me reste plus qu'à assembler. On reconnaîtra ici l'influence du Discours de la Méthode de René Descartes. Mais dans le cas de la construction d'un système informatique cette règle est plus facile à énoncer qu'à appliquer, parce qu'elle suppose connu le problème à résoudre, or c'est souvent là que gît la principale difficulté. Aussi la démarche inverse, de bas en haut (bottom-up), est-elle utilisée également : je réalise des programmes qui modélisent un aspect partiel du problème, je vérifie que le résultat est satisfaisant, ce faisant je découvre sans doute des aspects du problème qui avaient échappé à la spécification. En fait, programmer un problème aide à le comprendre, et les approches de haut en bas et de bas en haut sont utiles toutes les deux.
En réalité la principale difficulté de la programmation réside dans la détermination de l'objet du programme à écrire. Paul Graham l'exprime ainsi : « En programmation, comme dans beaucoup d'autres domaines, la difficulté n'est pas tant de résoudre les problèmes que de choisir les problèmes à résoudre ». Une approche fructueuse pourra consister à programmer des fonctions générales, dont on sait qu'elles seront utiles de toute façon, sans se préoccuper de l'objectif précis à atteindre. Une fois ces fonctions disponibles, elles constitueront une bibliothèque de composants destinés à résoudre toute une série de problèmes de bas niveau (accès aux bases de données, affichage sur écran graphique, analyse des messages introduits par les utilisateurs), qui faciliteront grandement l'écriture de logiciels de plus haut niveau dont l'auteur aura l'esprit libéré de ces questions et pourra ainsi mieux penser au problème général. L'approche bottom-up revient en fait à construire d'abord, au moyen d'un langage de programmation général, un langage spécialisé doté d'opérations spécialement adaptées au problème traité, puis à traiter le problème dans ce langage ad hoc ; les langages de la famille Lisp — Scheme sont particulièrement bien adaptés à cette démarche, puisque l'on a pu écrire qu'il s'agissait de langages de programmation programmables.
La programmation structurée fut l'aboutissement des premiers efforts pour appliquer à l'activité de programmation une démarche intellectuelle systématique, en garantissant certains aspects de la cohérence formelle du programme et la permanence des propriétés de cohérence et d'équivalence turingienne lorsqu'un programme est divisé en sous-programmes. Les langages Pascal, Ada et Modula furent conçus selon les principes de la programmation structurée, avant de recevoir des extensions destinées à les adapter au modèle de la programmation par objets. Les principes de la programmation structurée peuvent être considérés comme un acquis de la science de construction de programmes.
La programmation par objets
Après la programmation structurée vint un autre courant significatif : la programmation par objets, inventée en Norvège à la fin des années 1960 par l'équipe de Simula (Ole-Johan Dahl et Kristen Nygaard), illustrée par les langages Smalltalk (Alan Kay à partir des années 1970), Eiffel (Bertrand Meyer, années 1980) et C++ (Bjarne Stroustrup) pour finalement connaître la consécration avec Java. Les langages de la famille Lisp et Scheme possèdent une approche objet qui leur est propre avec le modèle CLOS (Common Lisp Object System). L'idée de la programmation par objets consiste à « encapsuler » un ensemble de données liées entre elles (par exemple, l'ensemble des données relatives à une même personne dans une base de données) avec les sous-programmes destinés à les traiter au sein d'une entité nommée objet3. Tous les objets relatifs à des personnes, pour poursuivre avec cet exemple, appartiennent à la classe Personne, qui constitue une sorte de modèle de ces objets analogues, qui sont nommés des instances de la classe Personne. Les sous-programmes associés aux objets sont appelés des méthodes, et s'ils sont les mêmes pour tous les objets de la classe ils figureront une seule fois pour toute la classe. La notion de classe est une extension de la notion de type [7] que l'on trouve en programmation structurée. Une nouvelle classe peut être obtenue par héritage d'une classe plus générale : ainsi, comme un élève est un cas particulier de personne, je peux construire la classe Élève à partir de la classe Personne, en héritant de tous les attributs de Personne, tels que date et lieu de naissance, adresse, etc. et en lui ajoutant des attributs spécifiques propres à la situation d'élève : classe, première langue, appartenance à l'association sportive ou au ciné-club, etc.
Cette façon de structurer et de hiérarchiser l'information permet de mieux garantir la cohérence des données et des traitements, et ainsi d'engendrer automatiquement des sous-programmes standard qui tirent parti des règles de construction imposées aux objets. La hiérarchie des traitements n'est pas réalisée par des appels de sous-programmes, mais de la façon suivante : un objet envoie à un autre objet un message qui lui demande d'exécuter telle ou telle de ses méthodes.
Pour la programmation structurée comme pour la programmation par objets, le progrès dans la réalisation des programmes découle d'une meilleure organisation de l'information, d'une réduction du désordre (de l'entropie) dans les données et les sous-programmes. La première méthode s'applique principalement à l'organisation de l'information sur les traitements (le texte du programme), la seconde met l'accent sur l'organisation des données : en fait les deux approches sont complémentaires et la seconde a bénéficié des acquis de la première.
Pour apprécier les qualités et les défauts de tel ou tel langage de programmation, il convient d'avoir conscience des objectifs poursuivis par ses concepteurs, qui peuvent différer d'un langage à l'autre. Ainsi des langages comme Perl ou APL ont été conçus en visant la vitesse d'écriture maximum : ils sont concis et laconiques, pleins d'abréviations qui réduisent le nombre de caractères à écrire, mais cela donne un texte à peu près illisible qui rend très aléatoire la recherche d'une erreur dans un programme. À l'inverse, Ada a été conçu d'après un cahier des charges (émis par le Department of Defense américain, le DoD) qui mettait l'accent sur la réduction des coûts de maintenance du logiciel : écrire un programme Ada syntaxiquement correct est plus laborieux que de l'écrire en Perl, mais une fois que la syntaxe est correcte, les erreurs à l'exécution sont rares, et la structuration inhérente au langage facilite modifications et corrections ultérieures.
Excès dans la pensée
Il y a eu beaucoup de verbiage autour de l'aptitude supposée du modèle objet à « représenter naturellement le monde réel » : il faut beaucoup de naïveté pour croire à une telle assertion, à supposer même qu'elle ait un sens. Parmi ces fadaises, il a été beaucoup question d'un objet véhicule, construit par composition d'un objet carrosserie, d'un objet moteur et de quatre objets roue. Il était ensuite loisible de disserter sur le point de savoir si l'objet tracteur appartenait à la classe Véhicule ou à la classe Matériel-Agricole. En fait, l'objet informatique tracteur est une pure abstraction destinée à résumer pour les besoins de tel ou tel système d'information quelques données que nous pouvons éventuellement posséder sur un tracteur réel, piloté dans ses champs par un vrai paysan, ou en cours de fabrication dans une usine, ou objet d'une procédure d'immatriculation, ou d'un dossier de prêt bancaire. Cet objet tracteur sera selon nos décisions arbitraires, sans doute liées aux objectifs visés par le système d'information que nous construisons, une instance de la classe Matériel-Agricole ou de la classe Véhicule, ou encore de la classe Immobilisation, et le lien entre lui et le tracteur réel est une pure convention. Dans tout cela il n'y a que de l'information sur des choses, mais pas de choses du tout, et le grand avantage de l'information par rapport aux choses, justement, c'est qu'elle est abstraite, et que l'on peut en faire ce que l'on veut sans autre effort que le dire ou l'écrire, c'est-à-dire sans avoir à produire d'effet physique.
Où gît la difficulté de la programmation
La programmation et la construction de grands programmes ne sont pas des disciplines faciles. Et il serait vain d'espérer maîtriser la seconde sans avoir au préalable acquis la première. Les cursus de Génie logiciel, destinés à l'acquisition de la seconde de ces disciplines, voient affluer des étudiants qui n'ont jamais écrit une ligne de programme de leur vie, mais qui voudraient bien, avec un diplôme au titre ronflant et un petit costume anthracite, devenir informaticiens en chef. Cette prétention est bien sûr ridicule, ce qui ne l'empêchera peut-être pas d'être satisfaite d'ailleurs.
Il existe un champ de recherche relatif à la programmation par l'utilisateur final ; il concerne les procédés qui permettent de rendre la programmation accessible dans une certaine mesure à des personnes dépourvues d'une véritable formation dans ce domaine. Les résultats obtenus par ces chercheurs indiquent que ce qui est difficile dans la programmation, ce n'est pas d'écrire une expression ou une petite séquence d'instructions qui vont réaliser une opération même assez complexe. La meilleure preuve en est la façon dont les utilisateurs les plus variés arrivent à se servir d'un tableur : même sans être programmeurs, beaucoup arrivent asez bien à programmer des formules assez complexes dans les cases d'un feuille de calcul. L'usage de logiciels statistiques ou de bases de données en montre d'autres exemples.
Là où les choses deviennent plus difficiles, c'est lorsqu'il s'agit de combiner plusieurs actions pour réaliser un programme plus vaste. Organiser un texte assez long qui doit décrire des situations où il y aura des choix à faire et des actions différentes selon les choix, répéter des actions pour en appliquer l'effet à des données variées en qualité et en quantité, c'est vraiment là que gît la difficulté — accompagnée en fait d'une autre difficulté tout aussi grande : la maîtrise des entrées et sorties d'un programme. Découper un programme en sous-programmes, organiser des données abondantes et variées d'une façon adaptée aux traitements qu'elles auront à subir, constituent des arts savants dont la maîtrise requiert un apprentissage théorique et une expérience pratique. Les méthodes à objets accroissent la puissance de ces procédés, mais pas forcément leur simplicité.
Un langage de programmation n'est pas seulement un moyen de demander à l'ordinateur le résultat d'un calcul : rédiger le texte d'un programme est aussi un moyen de noter et d'organiser ses idées, puis de les partager avec d'autres personnes. Pour permettre la rédaction harmonieuse de programmes éventuellement volumineux et complexes, un langage doit être pourvu des mécanismes suivants :
Rôle de l'abstraction
Abstraction : Action d'abstraire, opération intellectuelle par laquelle, dans un objet, on isole un caractère pour ne considérer que ce caractère ; résultat de cette action. (Dictionnaire d'Émile Littré)
Nous venons d'en parler, le processus d'abstraction, et le calcul sur les entités abstraites qui en résultent, sont au cœur de la problématique informatique. Programmer un problème du monde réel, qu'il s'agisse de mécanique quantique ou de comptabilité, consiste toujours à en identifier les éléments programmables pour ne plus considérer qu'eux, dont on construira un modèle abstrait, objet du programme. Il convient de s'interroger sur la nature et le statut de l'abstraction.
L'abstraction, dont j'emprunte à Émile Littré la définition ci-dessus, permet d'extraire d'un univers concret plus ou moins foisonnant des modèles d'objet auxquels la pensée pourra plus facilement s'appliquer, et par là elle est au cœur de la démarche scientifique. Elle permet aussi de créer des classes ou des catégories d'objets. Ainsi au sein de la classe [8] des arbres je peux ne m'intéresser qu'à certaines caractéristiques, notamment celles du feuillage, et créer les sous-classes « conifères » et « feuillus ». Si mes définitions sont bien construites, je pourrai formuler des énoncés relatifs aux conifères en général, et ces énoncés pourront s'appliquer aux pins, aux sapins, aux épicéas, etc.
Chacun de nous fabrique des abstractions tous les jours, ne serait-ce que pour classer les personnes qu'il rencontre. Mais cette activité instinctive, naturelle, nous est masquée par notre éducation qui nous transmet de l'abstrait (les théories mises au point par des « génies ») et qui nous détourne de la pratique (explicite et lucide) de l'abstraction. D'autre part, le raisonnement abstrait systématique est une élaboration culturelle, transmise par l'éducation, et selon sa formation et ses aptitudes chaque individu possédera un entraînement plus ou moins grand à ce type de raisonnement. La programmation des ordinateurs exige un niveau d'accoutumance au raisonnement abstrait plutôt élevé, tel que peuvent en posséder des personnes ayant reçu une formation scientifique, et c'est ce qui fait que de telles personnes pourront éprouver moins de difficulté pour aborder cette activité, même si leur stock de connaissances ne leur confère pas un avantage décisif.
Les études scientifiques peuvent conférer à ceux qui en ont bénéficié une autre tournure d'esprit favorable : l'habitude de considérer le savoir et les connaissances comme des éléments de communication et d'échange, par opposition à la tradition artisanale encore très présente dans les métiers, pour laquelle les savoir-faire sont des secrets de fabrique. Edsger Dijkstra a rapproché dans un article célèbre cette situation de la création, à partir du XIIe siècle, des universités, qui dispensaient publiquement des savoirs qui auparavant étaient la propriété privée et secrète d'entrepreneurs de la science. Parmi les méthodes de construction de programmes que nous évoquerons, celles qui donnent les meilleurs résultats reposent notamment sur des échanges intenses de connaissances, et les développeurs qui ne seraient pas enclins à ceux-ci auraient du mal à s'adapter à celles-là.
Hormis cet entraînement très général au raisonnement abstrait, qui peut être acquis au cours d'études scientifiques, mais aussi tout autrement, par la pratique du dessin industriel ou de la linguistique, par exemple, rien dans les cursus secondaires français actuels ne prépare réellement à l'acquisition des bases de la programmation, et il n'y a donc aucune raison de restreindre l'accès des premiers cycles à orientation informatique aux titulaires de baccalauréats scientifiques.
Si la France avait voulu prendre au sérieux l'informatique et la formation des informaticiens, elle aurait suivi les recommandations formulées par Jacques Arsac il y a au moins vingt-cinq ans en créant un CAPES et une agrégation d'informatique (ce sont les diplômes qui permettent d'enseigner dans les établissements secondaires). Il faudrait apprendre à programmer tout comme on apprend à parler l'anglais : parce que c'est utile, parce que sans cela il y a beaucoup de choses que l'on ne peut ni comprendre, ni faire. Au lieu de cela on a préféré saupoudrer les cursus de quelques cours de sensibilisation clinquants et démagogiques.
Les illusions de la spécification
Les sections précédentes ont évoqué les inventions des langages évolués, de la programmation structurée et de la programmation par objets, qui toutes ont représenté des progrès dans l'art de la programmation en améliorant la productivité des programmeurs, la justesse des programmes et la facilité à les modifier et à les corriger en cas d'erreur.
Ces améliorations concernent l'activité des programmeurs : il n'en reste pas moins que la programmation, même facilitée par des langages bien conçus et des méthodes simplificatrices, reste une activité hautement complexe, qui demande de grandes capacités d'abstraction et beaucoup de temps pour un résultat finalement assez incertain.
Un modèle de division du travail
Nous avons écrit plus haut que la détermination de l'objet du programme à écrire était la principale difficulté de la programmation, et nous ajoutons ici que cette détermination doit être écrite dans le programme même, c'est d'ailleurs pour cela que c'est si difficile. Un aphorisme du folklore informatique en donne une idée : « Avec les ordinateurs, ce qui est ennuyeux, c'est qu'ils font ce qu'on leur demande, pas ce qu'on aurait voulu. »
Le coût économique de cette difficulté a logiquement engendré la recherche de moyens de la contourner. Que la difficulté intellectuelle réside dans la programmation, perçue comme l'étape de fabrication du produit final, était difficile à comprendre pour des managers habitués au processus industriel. Dans l'industrie mécanique, la difficulté intellectuelle réside au bureau d'études, où des ingénieurs hautement qualifiés conçoivent les objets à réaliser. Une fois la conception terminée, ils disposent d'un excellent outil pour transmettre les consignes de réalisation aux ouvriers : c'est le dessin industriel, ou le programme de machine à commande numérique qui lui a généralement succédé. Comme nous l'avons vu au chapitre précédent, nous pouvons dire que le système industriel taylorien organise la séparation stricte de la conception et de la fabrication. La conception effectuée par les ingénieurs se concrétise dans des dessins (ou aujourd'hui des programmes de machines à commande numérique) qui permettent aux régleurs des ateliers de paramétrer les machines de telle sorte que les opérateurs (c'est ainsi qu'aujourd'hui on nomme les ouvriers spécialisés) puissent fabriquer les pièces sans aucune marge de manœuvre. La transmission des consignes est sans ambiguïté aucune (du moins en théorie).
Essais de division du travail en informatique
Les managers qui ont cherché à organiser le travail informatique se sont tous plus ou moins inspirés de ce modèle industriel : ils ont cherché à inventer le procédé qui serait à la programmation ce que le dessin industriel ou la CAO sont à la fraiseuse, à l'étau-limeur ou à la machine à commande numérique.
Le degré zéro de l'informatique taylorienne
Dans les années 1960-1970 la division du travail était entre les programmeurs qui écrivaient des programmes d'un côté, et de l'autre les analystes qui produisaient des organigrammes, c'est-à-dire des schémas censés représenter l'enchaînement des opérations élémentaires du programme, que les programmeurs n'auraient plus qu'à « coder ». L'emploi dans ce contexte des termes coder, codage et codeur vise à dévaloriser l'acte de programmer, à suggérer qu'il n'est qu'une opération mécanique dont l'intelligence serait toute contenue dans l'organigramme produit par les analystes du service études, et que les programmeurs du service production n'auraient qu'une tâche mécanique de transposition à accomplir. D'ailleurs, pour joindre l'acte à la parole et donner à cette façon de voir une valeur autoréalisatrice, on s'empressa de recruter des programmeurs sous-qualifiés et de les entasser dans des ateliers taylorisés. Le résultat fut les millions de lignes de Cobol au style dit « en plat de spaghettis » qui encore aujourd'hui assurent une bonne partie de la gestion des banques et des compagnies d'assurance.
J'ai eu l'occasion de collaborer avec un collègue qui travaillait dans un tel contexte au début des années 1980, au sein d'un établissement financier. Il me cita l'exemple du programme qui créait le fichier quotidien des compensations inter-bancaires, destiné à permettre à l'établissement de se faire payer les chèques tirés sur d'autres banques qu'il avait reçus en paiement de ses clients. Le montant quotidien de l'opération se chiffrait en millions de francs. Au moins une fois par semaine le programme échouait, ce qui obligeait à financer le retard de paiement au prix de l'argent au jour le jour. Autant dire que le coût du dysfonctionnement était colossal, équivalent au salaire de dizaines de programmeurs. Mais corriger l'erreur était proprement impossible, parce qu'elle était enfouie dans un programme monolithique énorme dont le texte source en Cobol était perdu depuis longtemps et dont l'organigramme disponible correspondait à une version périmée ; en outre le programmeur qui en était l'auteur et qui aurait peut-être pu intervenir avait quitté la société. Toute intervention aurait pu déclencher une catastrophe encore plus grave.
Cette anecdote, loin d'être exceptionnelle, reflétait la situation standard de l'informatique de gestion jusqu'aux années 1990, et il s'en faut de beaucoup que ce cas appartienne au passé.
Il faut ajouter que l'outil prétendu de conception, l'organigramme, était particulièrement indigent. Il consistait à aligner des rectangles et des losanges censés représenter les actions successives du programme et ses embranchements, c'est-à-dire qu'au mieux il était redondant par rapport au texte du programme, et la plupart du temps il était faux. Trop détaillé pour donner une vision d'ensemble, il ne l'était pas assez pour permettre une transcription automatique en texte de programme.
Première solution palliative : externaliser
L'ampleur des dégâts provoqués par cette organisation du travail fut telle que chacun chercha des palliatifs. Les entreprises qui avaient tenté d'assurer elles-mêmes maîtrise d'ouvrage et maîtrise d'œuvre se trouvaient à la tête de logiciels inadaptés, difficiles à maintenir et bientôt périmés, ainsi que d'effectifs importants de personnels à la qualification et au potentiel d'évolution incertains. Les ingénieurs commerciaux des sociétés de prestations de service n'eurent guère de difficulté à les convaincre que ce n'était pas la méthode qui était mauvaise, mais le fait même d'entreprendre soi-même le travail d'informatisation, et qu'il serait bien plus judicieux de confier cette mission à des entreprises spécialisées.
La légende a longtemps couru, et court encore, en France, que la France posséderait une puissante industrie du logiciel. Cette illusion est produite par le chiffre d'affaires important des Sociétés de Services et d'Ingénierie Informatiques (SSII), interprété par des statisticiens et des économistes peu informés des réalités de l'informatique comme celui d'une illusoire industrie du logiciel. En réalité l'activité réelle de beaucoup de ces SSII est assez peu différente de celle des agences de personnel intérimaire, à tel point que certaines ont dû affronter les tribunaux pour éviter de justesse la qualification de leur activité en service d'intérim, ce qui aurait entraîné des conséquences lourdes et défavorables en matière de droit du travail et de fiscalité. Ces SSII, loin de créer de la plus-value en mettant des logiciels nouveaux sur le marché, vendent essentiellement du service. L'analyse de leur chiffre d'affaires, certes exceptionnellement élevé si on le compare aux valeurs observées dans les autres pays de l'OCDE, révèle une clientèle particulièrement abondante et assidue dans le secteur de l'administration publique, qui a accueilli avec un enthousiasme particulier l'idée de se débarrasser de toute compétence informatique. Cet objectif « incompétence totale » est d'ailleurs aujourd'hui pratiquement atteint, puisque dans les DSI la plupart des personnes formées à l'informatique deviennent des gestionnaires de contrats et ne maîtrisent plus du tout les techniques utilisées par les fournisseurs — lesquels sont d'autant plus à l'aise pour dicter leur loi ; si ces personnes dotées de compétences refusent le « projet professionnel » qui leur est ainsi proposé, elles sont repoussées vers la périphérie du dispositif.
Plusieurs facteurs concourent à cet enthousiasme dans l'éradication de la compétence interne des entreprises. Traditionnellement, les milieux dirigeants de l'administration française considèrent la compétence technique comme un attribut indigne d'eux, bon pour des tâcherons. En être dépourvu est une condition nécessaire pour accéder aux plus hautes responsabilités. Le lecteur pourra trouver des portraits pris sur le vif de tels dirigeants sur le site de Michel Volle, comme par exemple ici. Comme les dirigeants des plus grandes entreprises françaises se recrutent dans la haute administration (issus de l'ENA : Conseil d'Etat, Inspection des Finances, Cour des Comptes etc. ; issus de l'X : Corps des Mines, des Ponts-et-Chaussées, etc.) cette culture de l'incompétence irrigue également celles-ci. Dans ce contexte, dire à des dirigeants qu'ils n'ont pas besoin d'être compétents, ni de posséder trop de compétence dans leur entreprise, en tout cas pas parmi leurs cadres dirigeants, ne peut que les conforter dans leur penchant traditionnel.
Il faut dire pour être équitable que les informaticiens ont aussi souvent abusé de leur pouvoir, qui devenait considérable, et qu'ils ont contribué eux-mêmes de façon importante à scier la branche sur laquelle ils étaient assis. Pour une entreprise, détenir des compétences n'est pas une fin en soi ; ceux qui les détiennent doivent les faire évoluer pour tenir compte des innovations techniques autant que des évolutions de l'entreprise ; la présence d'une population importante d'informaticiens qui ne voulaient pas ou ne pouvaient pas s'adapter aux nouvelles orientations a souvent été une charge insupportable pour leurs employeurs, et cette expérience n'a pas peu contribué à leur pulsion d'externalisation. Nous reviendrons sur cet aspect de la question informatique.
À cette situation générale vient s'ajouter vis-à-vis de l'informatique ce qu'il faut bien appeler une haine particulière. Mon collègue Norbert Paquel, statisticien, économiste, spécialiste des systèmes d'information et observateur fin et exercé de l'économie française, m'a expliqué un jour que, pour que l'informatique marche bien dans ce pays, il aurait fallu que dès le début des années 1950 soit créée une école d'application de l'École Polytechnique dédiée à l'informatique, qui aurait alimenté un corps d'informaticiens de l'État, civils ou militaires. Ce corps aurait développé ses solidarités, ses implantations, ses terrains de chasse gardée et ses filières, avec ses voies traditionnelles de pantouflage, bref, l'informatique serait devenu un élément normal du système militaro-industriel français, à l'image de l'Armement, des Télécommunications ou des Ponts et Chaussées. Faute d'avoir suivi ce parcours, l'informatique n'a jamais atteint en France une respectabilité considérable, et, comme par ailleurs elle se développait et procurait aux marginaux qui choisissaient d'y faire carrière d'assez belles situations et des promotions rapides, ces succès perçus comme illégitimes engendraient envie, rancœur et animosité dans les rangs des corporations qui se considéraient elles-mêmes comme plus respectables et plus méritantes.
J'ai eu l'occasion d'observer maintes manifestations de cette détestation de l'informatique, sous des formes très diverses, une des plus curieuses étant l'annonce de la « fin de l'informatique », ou sa variante, la fin des salaires élevés pour les informaticiens. Dans la bouche de dirigeants, de telles prophéties peuvent prendre une valeur auto-réalisatrice, et effectivement, de façon récurrente, administrations et grandes entreprises, saisies par une mode panurgique, liquident leurs équipes d'informaticiens et externalisent à tout va, en proclamant haut et fort que c'est la voie de la modernité. Tout aussi régulièrement, à l'issue d'un délai que j'estime en moyenne à quatre ou cinq ans, les mêmes sont amenés à constater les résultats catastrophiques de cette politique, et, sans tambours ni trompettes, essaient de reconstituer ce qui peut l'être. Bien sûr, dans le climat social actuel, entre-temps les équipes dirigeantes ont été renouvelées au moins deux fois, ce qui dispense de toute réflexion auto-critique et de toute analyse approfondie.
Il existe une forme pseudo-savante de détestation de l'informatique : la proclamation hors contexte du paradoxe de Solow, du nom de son auteur l'économiste américain Robert Solow, qui a dit en 1982 « You can see the computer age everywhere but in the productivity statistics. » (« on voit la révolution informatique partout, sauf dans les statistiques de productivité » ; la référence écrite est dans la New York Review of Books, 12 juillet 1987). Au début des années 1980 régnait l'informatique centralisée, assez mal maîtrisée par les entreprises ; en d'autres termes les innovations apportées par l'informatique n'avaient pas encore été assimilées, et de ce fait elles n'avaient pas encore porté leurs fruits. Depuis les choses ont malgré tout changé, et d'ailleurs Robert Solow a publiquement modifié son diagnostic. Mais chez les cuistres ignorants, son ancien apophtegme voisine avec le détestable truisme sur les chercheurs qui cherchent et ceux qui trouvent. On consultera avec profit, à ce sujet, un article que Michel Volle a consacré à l'économie du système d'information, ainsi qu'un texte de Claude Rochet assorti de nombreuses références accessibles en ligne.
Le débat sur le paradoxe de Solow s'est déplacé vers la question de l'inégale aptitude des économies américaine et européenne à tirer profit des innovations informatiques, mais l'opportunité d'y avoir recours n'est plus une question depuis longtemps : sans l'informatique, l'Airbus ne peut ni être conçu, ni être construit, ni voler, ni être vendu ; les banques devraient recruter des millions d'employés si elles voulaient se passer d'ordinateurs, ainsi d'ailleurs que les administrations fiscales qui ont pu grâce à l'automatisation multiplier par plus de 10 le nombre de contribuables.
Pour en revenir à la question de l'utilité des compétences en informatique au sein de l'entreprise, il ne faudrait pas que le lecteur retire des lignes qui précèdent l'idée qu'il faille rejeter toute idée d'externalisation, bien au contraire. Il existe tout d'abord une forme d'externalisation qui est presque toujours hautement recommandable lorsqu'elle est possible et pratiquée raisonnablement, c'est le recours à des logiciels ou à des systèmes qui existent déjà, comme les progiciels : nous aurons l'occasion d'y revenir au chapitre 6. Il y a aussi des activités qu'une entreprise moderne aura tout intérêt à confier à des spécialistes extérieurs. Mais pour qu'une externalisation soit un succès, il faut avoir une idée la plus précise possible de ce que l'on veut externaliser. Il vaut mieux aussi que ce ne soit pas un élément trop stratégique du dispositif de l'entreprise, parce qu'il y aurait alors un risque de perdre le contrôle d'un élément clé. Il est souvent facile d'externaliser des choses dont la définition est assez simple, parce que très circonscrite : le nettoyage des locaux, la mise sous enveloppe et l'expédition d'envois en volume, l'entretien d'un parc automobile. Ce peut être aussi une intervention technique ponctuelle très spécialisée au sein d'une équipe qui ne possède pas cette compétence précise. Mais l'externalisation du système d'information, ou même simplement de ses composantes techniques, ne répond visiblement pas à ces critères. Les externalisations réussies concernent pour la plupart des activités qui ne demandent aucune compétence particulière ; dès lors qu'un travail révèle une complexité, l'intérêt pour une entreprise (publique ou privée) est de le capitaliser, donc de se l'approprier (knowledge management, veille, etc.)
Régie ou forfait : à bon chat, bon rat
Lorsqu'une entreprise confie un projet informatique à une société de services, situation déjà évoquée plus haut, il y a deux types de solutions pour l'organisation du travail et de sa facturation :
Les contrats au forfait ou en régie sont à la mode alternativement ; l'administration française s'interdit les contrats en régie ; en fait l'un comme l'autre système peuvent réussir ou échouer.
Si le contrat est au forfait et que le client ne dispose pas des compétences et des effectifs suffisants pour participer activement au projet, le prestataire peut être tenté d'interpréter de façon très restrictive le cahier des charges et ses propres obligations aux termes du contrat, et au contraire de manière extensive et pointilleuse les obligations du client, en termes de disponibilité des interlocuteurs, de fourniture de documents et de dates pour l'exécution de ces obligations. Si les équipes du client participent activement au travail et que l'estime réciproque règne entre les participants, ce type de dérive est moins probable et de toute façon plus limité, parce que chacun est en mesure d'apprécier le travail à faire et son volume. Mais, dans un contexte où chaque entreprise lutte pour sa survie et où, pour une société de services, avoir des employés en attente de travail (en « inter-contrat ») est une lourde charge, si le prestataire a pu mesurer l'incompétence de son client, il résistera difficilement à la tentation de gonfler les facturations en exigeant la signature d'avenants au contrat initial pour toute prestation supposée à tort ou à raison ne pas avoir été prévue par le cahier des charges.
Un responsable d'une société de services m'a déclaré franchement que les services publics jouaient fréquemment ce rôle du client incompétent, et que la facturation de services aux administrations n'avait rien à voir avec les tarifs pratiqués pour les entreprises privées. La surfacturation systématique aux dépens des administrations incapables de s'en apercevoir est considérée comme une juste compensation pour des charges sociales exorbitantes et un droit du travail trop rigide.
Si le travail au forfait comporte des inconvénients, le travail en régie n'en est pas exempt. On peut même dire qu'il est pratiquement incontrôlable si le client ne dispose pas de sa propre équipe et d'un chef de projet capable de suivre le travail au jour le jour. Il est tellement confortable d'avoir une réserve permanente de personnels en régie, un peu sous-occupés mais de ce fait assez disponibles en cas d'urgence, et d'emploi plus malléable que les personnels internes ! Cette pratique est à la limite de l'emploi intérimaire, et les clients doivent veiller soigneusement à éviter que les personnels du prestataire ne se retrouvent dans la situation de demander la requalification de leur contrat de travail à leurs dépens.
Pour conclure sur ces aspects de la sous-traitance, il semble raisonnable de dire qu'une sous-traitance modérée peut être un excellent moyen de renforcer le potentiel de l'entreprise, à condition que cette externalisation soit équilibrée par le maintien d'une véritable équipe du client, capable de conserver la compétence interne et de contrôler les prestataires, et pas juste de rédiger des cahiers des charges. L'externalisation à tout crin assortie de la liquidation des compétences internes est une erreur, et celui qui la commet ne tarde pas à être puni par la déliquescence de son système d'information, l'explosion de ses coûts, l'incohérence de ses procédures de gestion, bref par la perte du contrôle d'éléments fondamentaux du fonctionnement de l'entreprise.
L'externalisation peut être un succès si elle est menée par une entreprise compétente qui sait ce qu'elle fait ; elle saura alors choisir de bons prestataires et obtenir d'eux un travail de qualité : à bon chat, bon rat.
L'informatique est pilotée par l'offre
L'informatique est pilotée par l'offre : cette assertion peut sembler immorale, scandaleuse, mais elle est vraie.
Dans le monde idéal dont pourraient rêver les utilisateurs, c'est la demande qui devrait piloter les projets : les maîtres d'ouvrage recueilleraient auprès des stratèges et des responsables fonctionnels l'expression des besoins, qu'ils mettraient sous la forme de cahiers des charges, au vu desquels architectes et maîtres d'œuvre élaboreraient des solutions adaptées. Bref, c'est un refrain que nous avons déjà souvent évoqué et que nous entendrons encore.
Eh bien cela ne se passe pas ainsi. Les stratèges et les responsables fonctionnels n'ont cure d'exprimer leurs besoins sous une forme suffisamment élaborée et raisonnable pour être utilisable, et les cahiers de charges qui résultent de l'écoute de leurs frustrations, si ce n'est de leurs caprices, sont lourds de catastrophes à venir.
L'informaticien face au donneur d'ordres doit adopter l'attitude du médecin face à son patient : les propos de celui-ci sont des symptômes, mais ce n'est pas le malade qui établit le diagnostic ni qui rédige l'ordonnance. Formuler un besoin, c'est dans notre cas rédiger un cahier des charges, dont nous avons dit qu'il serait éminemment modifiable et évolutif. Faire ce travail de rédaction, c'est un métier, le métier d'informaticien, qui rédige en pleine conscience des possibilités techniques, même s'il s'interdit d'effectuer des choix techniques prématurés ou arbitraires.
En fait, c'est l'offre de solutions disponibles qui détermine le caractère raisonnable des besoins, simplement parce que l'évolution technique dans le domaine informatique est très rapide, alors que les structures et l'organisation des entreprises évoluent plus lentement. Il n'est donc pas aberrant de saisir l'occasion de techniques qui arrivent à maturité pour les appliquer à des problèmes que l'on aura mis en évidence justement pour cette occasion.
Cela semble mettre les choses sens dessus-dessous, mais l'observation de cas réels confirme que ce type d'opportunisme donne de meilleurs résultats que le volontarisme qui ferait fi des contraintes techniques. Quant à confier tous les pouvoirs à l'utilisateur final, c'est le moyen le plus sûr d'aller à l'échec en passant par l'explosion budgétaire.
Après l'échec...
Lorsque la taylorisation et l'externalisation aveugles ont échoué il faut chercher autre chose. Les entreprises les mieux dirigées savent que la solution réside généralement dans un savant équilibre entre le maintien d'une compétence et d'un potentiel de développement internes complétés par une sous-traitance introduite en doses bien calculées et aux bons endroits. Mais un tel équilibre ne peut être que provisoire : comme nous l'avons exposé dans l'exemple de la section 4, il viendra forcément un jour où les départements administratifs de l'entreprise auront la peau de l'informatique interne, si elle n'est pas liquidée à l'occasion d'une restructuration ou sur la foi des promesses d'une société de services désireuse de s'implanter. Et les sociétés de service ne sont-elles pas incitées par la logique de leur démarche commerciale à toujours proposer le renouvellement de l'informatique de leurs clients, même si l'utilité de ces innovations est douteuse ? Il serait d'ailleurs vain de prétendre que l'informatique interne n'a aucune part de responsabilité dans son destin, et un prochain chapitre nous montrera pourquoi et comment il est effectivement difficile à l'entreprise d'obtenir de ses informaticiens ce qu'elle est en droit d'en attendre. En tout état de cause, selon la presse professionnelle[87], en cette année 2004, l'espérance de vie professionnelle d'un directeur du système d'information dans une entreprise française privée ou même publique est de l'ordre de vingt mois, ce qui donne la certitude qu'aucun projet cohérent de quelque ampleur ne peut être mené à bien.
[1] Martin Campbell-Kelly Une histoire de l'industrie du logiciel, MIT Press (Vuibert pour la traduction française de Pierre-Éric Mounier-Kuhn), Cambridge, Massachusetts (Paris), 2003.
[2] Dans les lignes qui précèdent le mot calcul était utilisé selon l'acception mathématique de ce terme. À partir d'ici nous l'emploierons au sens informatique plus large de manipulation symbolique composée d'opérations de traduction et de réécriture, bref, de traitement de données.
[3] Le lecteur désireux d'en savoir plus sur l'histoire et la morphologie technique des processeurs et des langages pourra se reporter par exemple à mon livre consacré aux ordinateurs et aux systèmes d'exploitation.
[4] Andrew S. Tanenbaum, Architecture de l'ordinateur, Dunod (pour la traduction française), Paris, 2001.
[5] Andrew S. Tanenbaum, Systèmes d'exploitation, Pearson Education (pour la traduction française), Paris, 2003.
[6] Andrew S. Tanenbaum, Réseaux, Pearson Education (pour la traduction française), Paris, 2003.
[7] Le lecteur non spécialiste qui aurait quelques souvenirs de son programme de mathématiques de classe terminale peut voir le type comme une structure algébrique, telle que l'anneau des entiers relatifs ou le corps des réels. Un type est un nom donné à la collection des valeurs que peuvent prendre certaines entités, il est défini par les éléments suivants :
[8] Le mot classe n'est pas employé ici dans son acception botanique.