Je fais de la recherche en langages de programmation. Dans ce billet j’explique pourquoi et comment, en essayant d’être accessible pour des gens qui connaissent peu (ou mal) la programmation et/ou la recherche.

Les programmeurs et programmeuses ont inventé de nombreuses représentations symboliques des programmes qui sont exécutés par un ordinateur, représentations que l’on appelle langages de programmation. On peut les voir comme des langages utilisés pour parler avec l’ordinateur, un programme étant un texte dans ce langage, le code source. Mais il est important de se souvenir que la programmation est aussi une activité sociale: la plupart des programmes sont écrits par plusieurs personnes travaillant ensemble, et les programmes écrits par une personne seule sont souvent réutilisés, inspectés et modifiés par d’autres. Un programme transmet une intention à l’ordinateur, mais il la communique aussi à des humains.

Quand on programme, on est facilement irrité par les défauts du langage de programmation qu’on utilise; il est très difficile de concevoir un bon langage de programmation. On lui demande au moins les trois qualités suivantes :

la concision: Les tâches simples doivent être décrites par des programmes simples, pas par des programmes gros ou complexes. Les tâches complexes nécessitent des programmes complexes, mais la complexité du programme doit venir uniquement du domaine métier (les spécificités de la tâche requise), sans complexité incidente imposée par le langage de programmation. Par exemple, les premières recherches en intelligence artificielle ont révélé le besoin d’un bon support, par le langage de programmation, du backtracking (retour en arrière) : annuler une série de décisions prises pour atteindre un certain but, en cas d’échec, pour commencer à nouveau selon une méthode différente. Certains langages de programmation rendent beaucoup plus facile d’exprimer cela que d’autres.

la clarté: En lisant le texte d’un programme, il faut qu’il soit facile de comprendre l’intention des personnes qui l’ont écrit. On dit qu’un programme a un bug (un défaut de fabrication) quand sa signification (pour l’ordinateur) ne correspond pas à l’intention de ses auteurs – une erreur a été faite pendant la transcription des idées dans le texte du programme. La clarté est un composant essentiel de la sûreté (éviter les comportements inattendus et dangereux). Pour l’améliorer, certaines constructions des langages de programmation nous aident à exprimer notre intention, et les concepteurs et conceptrices de langages de programmation travaillent à concevoir des outils pour vérifier automatiquement que l’intention ainsi exprimée est cohérente avec le reste du texte du programme. Par exemple, l’un des pires problèmes de sécurité découvert en 2014 (le fait que tous les ordinateurs et téléphones Apple ne vérifiaient pas correctement l’authenticité des sites webs demandant une connection sécurisée) était causé par une ligne dans le texte d’un programme qui avait été dupliquée – écrite deux fois au lieu d’une seule. La différence entre l’intention du programmeur (vérifier l’authenticité des communications sécurisées) et le comportement réel du programme (permettant à des mauvais acteurs de se faire passer pour votre banque ou boîte email, intercepter vos paiement en ligne, etc.) était considérable, et pourtant ni les humains ni les outils automatiques qu’ils utilisaient n’avaient repéré cette erreur.

la cohérence: Un langage de programmation devrait avoir une structure très régulière, pour qu’il soit facile pour ses utilisateurs et utilisatrices de deviner comment utiliser les parties du langages qu’ils ne connaissent pas encore bien. En particuliar, la cohérence aide la clarté : retrouver l’intention derrière le texte du programme demande une bonne connaissance du langage, et plus le langage est cohérent, prévisible, plus faibles sont les risques de mécompréhension. C’est un cas particulier d’un principe de conception plus général, le principe de surprise minimale.

Bien sûr, la liste (non exhaustive) ci-dessus n’est que l’opinion informelle d’une personne pratiquant la programmation (moi-même), et non pas une affirmation scientifique établie rigoureusement. La programmation est un domaine riche qui met en jeu de nombreuses activités, donc la recherche scientifique sur les langages de programmation peut être entreprise, et devrait être entreprise, depuis de nombreux angles différents. Entre autres, les mathématiques (la formalisation), l’ingénérie, le design, les interfaces homme-machine, l’ergonomie, la psychologique, la linguistique, les neurosciences, la sociologie, et les personnes qui pratiquent la programmation ont toutes leur mot à dire sur comment concevoir de meilleurs langages de programmation.

Pour ma part, je travaille au sein d’une communauté scientifique qui utilise la formalisation mathématique comme son principal outil pour étudier, comprendre et améliorer les langages de programmation. Pour travailler sur un langage, on lui donne une sémantique formelle (ou plusieurs) en définissant les programmes comme des objets mathématiques, au même titre que les nombres ou les fonctions. La sémantique d’un langage est alors donnée par une relation (mathématique) entre les programmes et leur comportement. On peut ainsi prouver des théorèmes sur les langages de programmations eux-mêmes, ou sur les analyses et transformations de programmes.

Voir dans le détail comment la formalisation mathématique d’un langage de programmation peut guider sa conception est absolument fascinant – c’est une approche très abstraite d’une activité très concrète. Ma communauté de recherche a défini un certain nombre de propriétés qui peuvent s’appliquer ou non à la formalisation mathématique d’un langage donné (l’objet mathématique que l’on a défini pour représenter le langage), et qui capturent certains aspects de l’utilisabilité du langage. Il s’agit en quelque sorte d’un ensemble de tests pour évaluer un langage. Cet ensemble de tests évolue au fil du temps, car nous affinons notre compréhension de ces propriétés formelles et nous en proposons de nouvelles, à partir de nos expériences d’utilisation des langages existants ou expérimentaux.

Avoir une sémantique formelle d’un langage que l’on étudie est une façon de comprendre ce que les programmes de ce langage veulent dire, ce qui est une première étape nécessaire pour évaluer ou améliorer la clarté du langage – un programme ne peut pas être clair si on ne commence pas par se mettre d’accord sur ce qu’il veut dire. Construire cette formalisation est un travail difficile (technique) et chronophage, mais son pouvoir de simplification ne peut pas être surestimé. Le travail de formalisation agit comme une loupe qui grossit les irrégularités, et suggère naturellement des changements du langage qui peuvent améliorer drastiquement sa cohérence. Il nous encourage à construire (ou reconstruire) le langage autour d’un petit ensemble de concepts centraux et indépendants, ses briques de base – c’est la meilleure façon de rendre la formalisation plus facile. Il peut donc améliorer aussi la concision, puisque des concepts avancés peuvent être décrits de façon simple en combinant ces briques de base. Bien sûr, trouver les bonnes briques de base demande une connaissance du domaine métier (celui des programmes dont on veut améliorer l’écriture dans ce langage); pour avoir des idées vraiment nouvelles il faut souvent explorer avec des prototypes ou faire des études d’usage, en dehors de l’activité de formalisation. La méthode de conception de langages que je préfère, c’est donc la co-évolution d’un langage et de sa formalisation, les activités de formalisation et de programmation ayant lieu en même temps, pour informer et diriger le processus de conception.