Le concept d’interface de programmation d'applications (API) s'applique partout, des outils en ligne de commande au code d'entreprise, en passant par les microservices et les architectures « cloud-native ». Les développeurs de logiciels utilisent cette interface pour interagir de manière programmatique avec des composants ou des ressources logicielles en dehors de leur propre code. Une définition encore plus simple est de dire que l’API est la partie d'un composant logiciel accessible à d'autres composants. À moins d’écrire chaque ligne de code à partir de zéro, le développeur interagira avec des composants logiciels externes, et chacun d'entre eux aura sa propre API. Même si le développeur écrit tout son code à partir de zéro, une application bien conçue devrait avoir des API internes pour faciliter l’organisation du code et rendre ses composants plus réutilisables. Qu'il s'agisse de programmes simples ou de considérations plus avancées en matière de conception et d'architecture, le concept d’interface de programmation d'applications (API) est essentiel dans le développement logiciel. Cet article permet de mieux comprendre les API et leur utilisation dans le développement logiciel.
Les API et le développement logiciel
L’API est la partie d'un logiciel accessible à d'autres programmes. C’est la zone externe d'un composant logiciel. C'est pour cette raison que l’on peut faire référence à la surface API d'un programme. Comme le montre la figure 1, la surface API représente la couche extérieure du programme ou du composant, un peu comme la paroi d'une cellule.
Un composant d'application avec son API. (crédit : IDG)
Quand un programme est utilisé par un autre, le premier est appelé fournisseur et le second client. L’API correspond à la partie du fournisseur accessible aux clients. Cet arrangement se retrouve dans presque tous les types d’applications logicielles et les types de systèmes. Ce qui est constant, c'est que l'API sert aux clients à faire des appels au fournisseur. L'API définit une gamme connue d'entrées (input) autorisées et de sorties (output) associées au composant. Autrement dit, l'API définit le protocole de communication avec un composant. Tous les logiciels, sauf les plus triviaux, utilisent des capacités fournies par d'autres composants. Un programme logiciel appelle l'API d'un composant pour accéder à ses capacités. Comme le montre la figure 2, outre l'utilisation d'autres composants, la plupart des logiciels sont utilisés en tant que composants par d'autres programmes.
Plusieurs composants interagissant via leurs AP. (crédit : D.R.)
API Vs interface utilisateur
On trouve des similitudes entre les API et les interfaces utilisateur, ou UI. C'est tout à fait logique, car, dans les deux cas, il s'agit d'interfaces. Cette dernière est un moyen d'interagir avec les éléments internes d'un système. En général, le rôle de l'interface est de simplifier et de concentrer les capacités internes sous une forme utile pour le client. La différence entre les API et les interfaces utilisateur réside dans le fait qu'elles s'adressent à différents types de clients. Sur un ordinateur portable, l'interface utilisateur se compose de périphériques d'entrée, comme un clavier et une souris, et de périphériques de sortie, comme un écran et un clavier. Le client est la personne qui utilise l'ordinateur portable. Outre le système d'exploitation, de nombreux programmes fonctionnant sur l'ordinateur portable présentent également une interface utilisateur, avec laquelle l'utilisateur peut interagir via les périphériques d'entrée et de sortie de la machine. Par exemple, le navigateur web présente un ensemble d'éléments visuels sur l'écran qui peuvent être contrôlés à l'aide de la souris et du clavier.
API et navigateur web
Regardons maintenant ce qui se passe au niveau d’un navigateur web. Ce dernier sert à ouvrir diverses pages web qui pour la plupart contiennent du code JavaScript. Le navigateur exécute le code JavaScript pour afficher la page. Pour fonctionner, le programme JavaScript doit avoir accès aux capacités du navigateur. Dans ce cas, le programme JavaScript est le client de l'API et le navigateur est le fournisseur de l'API. Le navigateur est un fournisseur qui offre des fonctionnalités de navigation web auxquelles le programme JavaScript accède via une interface de programmation, l'API du navigateur. Par exemple, si l’on tape F12 et que l’on ouvre une console JavaScript, on peut créer un petit programme JavaScript pour interagir avec l'API de son navigateur. Si l’on entre le code de la liste 1 dans la console, on pourra provoquer certaines actions.
Liste 1. Suivi de la souris dans la console du navigateur
À noter qu'une fois que l’on a commencé à voir l’output de la console, on peut désactiver ce paramètre en tapant :
L'intérêt de cet exemple, c’est que l'objet window fait partie de l'API du navigateur. De même, la fonction (ou méthode) onmousemove est un membre de l'objet window. Elle fait donc partie de l'API de l'objet window. Ainsi, une fois que l’on est dans le code, on peut voir que les API sont partout. Si l’on souhaite utiliser les fonctionnalités d'un composant, on peut y accéder par l'intermédiaire de l'API du composant.
Les API imbriquées
Autre observation : les API existent à différents niveaux d'un programme et s'imbriquent les unes dans les autres. L'API de la fenêtre est en quelque sorte imbriquée dans l'API du navigateur. Si l’on s’intéresse de plus près à la manière dont le navigateur fonctionne, on pourra se familiariser avec d’autres types d'API. Par exemple, on peut se demander comment fait le navigateur pour connaître la position de la souris ? Pour connaître la position de la souris, le navigateur s'enregistre auprès du système d'exploitation via une API. Le système d'exploitation charge alors un pilote de souris, lequel inclut une API standardisée pour fournir des informations en continu sur ce que fait la souris. (Si l’on va plus loin, on pourra voir que le pilote lui-même s'appuie sur des interfaces matérielles et logicielles de bas niveau, ce qui représente un troisième type d'interface avec l'interface utilisateur UI et l'API).
Les API dans les librairies, les paquets et les modules
La console du navigateur est un contexte spécialisé dans la mesure où toutes les librairies sont préchargées par l'environnement d'exécution. Le plus souvent, les librairies sont explicitement chargées par le programmeur. Le mode de chargement varie selon le langage de programmation, mais chaque fois que l’on voit import, include ou require dans un output, cela signifie que le programme en cours utilise l'API d'un autre programme. Tous les programmes, sauf les plus basiques, sont constitués d'expressions et de constructions au niveau du langage (comme les ifs, les boucles et les opérateurs) utilisées en conjonction avec des appels aux API trouvées dans d'autres paquets. À son tour, chaque programme est également un composant qui peut potentiellement être inclus et utilisé par d'autres programmes. Les modules, les paquets et les librairies relèvent tous de la même notion, au sens large : ce sont des collections de code qui peuvent être incluses. La somme de leurs parties visibles publiquement - classes, objets, méthodes, fonctions, variables, etc. - représente la surface de l'API dans cette collection.
Les API distantes et les microservices
Au niveau le plus élevé, on peut diviser les API en deux types : les API locales et les API distantes. Les API distantes sont utiles dans la mesure où elles ne nécessitent pas de mises à jour du code sur les appareils clients, où elles peuvent être mises à l'échelle de manière indépendante et où elles présentent une forme d'API standardisée que tout client peut appeler à condition d'y être autorisé. En général, on pourrait dire que les API distantes (également connues sous le nom de services) sont fortement découplées et offrent un protocole standard (HTTP/S sur TCP) qui fonctionne quelle que soit la pile d’implémentation qui les sous-tend.
Par exemple, on peut mettre en place cette interaction rapide avec une API distante, en entrant le code de la liste 2 dans la console JavaScript :
Liste 2. Appel de l'API du Seigneur des Anneaux
Si l’on exécute ce code, on obtiendra un journal de console, quelque chose comme : « Gollum a dit : Ils sont jeunes. Ils sont tendres. Ils sont gentils. Oui, ils le sont. Mangez-les. Mangez-les ! » Ce qui s'est passé, c'est que l’on a créé un programme JavaScript qui a utilisé l'API du navigateur (plus précisément, l'API « fetch ») pour lancer un appel HTTP vers le serveur qui se trouve à l'adresse https://the-one-api.dev. Il s'agit d'une API REST, ce qui signifie qu'elle respecte certaines conventions d’architecture.
Microservices et passerelles API
Une architecture de microservices utilise essentiellement des API distantes pour des activités traditionnellement réalisées par des API locales. Une architecture de microservices décompose une application en composants disponibles à distance. Le concept de passerelle API est spécifique à l'architecture de microservices. Dans une passerelle API, un point de contact unique est défini sur le réseau pour orchestrer les itinéraires vers des services spécifiques. Cela permet de bénéficier de certains avantages (comme l'authentification et la limitation du débit entre les services) et, en tant que tel, fonctionne comme une sorte d'interface des interfaces.
Les API distantes sont partout
L'internet est fondamentalement un univers d'API distantes en interaction. Tout ce qui s'exécute sur un appareil est une API locale. Les serveurs sont des collections d'API locales qui concourent à fournir une API distante. Les clients sont des collections d'API locales qui travaillent ensemble pour consommer des API distantes. Le middleware est un ensemble d'API locales qui concourent à fournir une API distante et travaillent ensemble pour consommer d'autres API distantes.
Les API et le (bon) design logiciel
Sur toutes les plateformes et dans tous les langages, il existe différentes manières de contrôler ce qui est visible et la façon dont le code client l'utilise. La conception d'API accorde une grande attention à l'idée de dissimulation d'informations, une notion capitale pour faciliter la maintenance d’un logiciel. Le bon design d’un logiciel en dépend. L'idée est d'écrire des composants logiciels qui font tout ce qui leur est demandé avec le plus petit point de contact possible. Les développeurs s’attachent à fournir uniquement les informations les plus essentielles sur le fonctionnement interne d'un composant. Ce concept s'applique à tout, depuis la plus petite fonction, dont la signature est une API en miniature, jusqu'à de puissants services distants.
Les bonnes API sont à l'opposé du code spaghetti. Dans un code spaghetti, le flux d'exécution et de dépendance est très difficile à suivre, ce qui rend le code difficile à maintenir et à déboguer (c'est la raison pour laquelle GOTO est considéré comme nuisible). Dans une bonne conception d'API, les composants logiciels se comportent comme des composants mécaniques. Ils effectuent une tâche particulière derrière une interface bien comprise. On peut traiter le composant comme une entité unique. L'alternateur d'une voiture ne fait qu'une chose : il crée une charge. S'il tombe en panne, le mécanicien peut isoler cette pièce. Tout aussi important, le reste de la voiture n'a besoin que de savoir que la courroie passe autour de la poulie de l'alternateur. Dans cette analogie, la poulie et les bornes électriques de l'alternateur constituent l'API de l'alternateur. Bien entendu, l'isolation n'est jamais parfaite. Même dans le cas d'un alternateur, la courroie et le tendeur interagissent de manière importante. Les développeurs essaient de créer de bons composants, sous-systèmes et architectures afin de garder la main sur les principaux antagonistes des logiciels : les forces de l'entropie et de la complexité. C’est en concentrant la complexité dans des composants et en rendant leurs interfaces et protocoles aussi simples que possible que l’on arrive à faire que les systèmes logiciels sont beaucoup plus faciles à gérer.
Une bonne API fait un bon logiciel
Les API sont essentielles à la bonne conception des logiciels, et elles s'incarnent de diverses manières dans les différentes couches des logiciels. Quand on écrit un logiciel, il est utile de considérer le code que l’on écrit comme un composant potentiellement réutilisable dans d'autres systèmes. Il est important de prendre en compte les caractéristiques de l'API de son composant. Si c’est le cas, on pourra probablement se concentrer sur un ensemble limité de fonctionnalités et réfléchir à la manière dont la surface de l'API interagira avec d'autres composants. Il faut penser en termes de séparation des problèmes et essayer de n'exposer que les informations strictement nécessaires sur le composant. L'utilisation d'API bien conçues permet de composer le logiciel à partir de composants logiquement distincts. Ces composants peuvent être maintenus dans un isolement relatif et la fonctionnalité qui les sous-tend sera potentiellement réutilisable entre différentes applications.