bloomua - Fotolia

Les six grandes contraintes d’une architecture REST

Si la conception d’une architecture REST n’est pas nécessairement difficile, il existe certaines règles non négociables en matière d’approvisionnement en ressources. En voici six que tous les architectes devraient connaître.

L’expression « contraintes architecturales » désigne les caractéristiques qu’une architecture doit posséder pour correspondre à la définition d’un modèle particulier, tel que REST. En adhérant aux règles spécifiques et sous-jacentes qui forment la base de ces contraintes architecturales, il devient beaucoup plus facile de comprendre exactement ce qui rend quelque chose « RESTful » – et d’éviter les problèmes qui donnent des maux de tête aux nouveaux venus dans ce style d’architecture.

Malheureusement, de nombreux architectes continuent d’autoriser des pratiques qui violent les principes REST, tout en croyant maîtriser la conception RESTful. Cependant, ils seraient bien inspirés d’apprendre qu’il n’y a aucun moyen de contourner les exigences de base qui définissent ce modèle d’architecture.

Examinons les six contraintes fondamentales de l’architecture REST que chacun devrait utiliser pour guider une mise en œuvre basée sur REST. Détaillons pourquoi elles sont si importantes, ainsi que les pratiques tactiques de développement et de conception qu’elles impliquent.

Interface uniforme

La première contrainte de l’architecture REST que nous allons examiner est celle de l’interface uniforme. Dans une approche RESTful, il est utile de conceptualiser et de classer les services individuels comme des ressources d’application qui exposent leur propre interface client. Il est important que ces ressources soient suffisamment petites en matière de portée et de volume de données pour qu’une seule interface puisse aisément les gérer. Enfin, REST exige que les mécanismes d’interface que ces ressources emploient, pour exposer leurs capacités, se comportent de manière cohérente avec toutes les autres interfaces qui exhibent des services connexes.

Il s’agit d’une contrainte assez facile à respecter, à condition que les architectes fassent l’effort de considérer ces ressources comme des « noms » – en d’autres termes, des entités uniques qui acceptent les entrées et interprètent les appels sous la forme d’instructions procédurales pour une certaine opération (qui pourraient être traitées comme des « verbes »). Il s’agit d’un principe fondamental de la programmation orientée objet. Si l’on simplifie, les services sont des objets qui prennent des commandes. Pour s’en souvenir, il suffit de penser à l’envoi d’actions à des objets, et non d’objets à des actions.

Notez qu’il est également important pour les architectes de rester cohérents en matière de définition des ressources et de conception des API, afin que les ressources ne s’alignent pas par erreur et ne partagent pas de données avec la mauvaise API ou interface client.

Modèle client-serveur

La prochaine contrainte à aborder est le modèle client-serveur, qui exige que le couplage entre une ressource RESTful et les API associées n’existe que dans l’interface côté client. Ces ressources sont libres d’évoluer indépendamment, mais l’interface doit rester intacte.

Ce couplage léger permet de réduire les relations de dépendance mal gérées qui provoquent des pannes et compliquent les processus de mise à jour, ce qui est essentiel lorsque les développeurs créent fréquemment des ressources et des clients de manière isolée. Il est également plus facile pour les équipes logicielles de collaborer au niveau où le développement back-end rencontre la conception front-end, car il y a moins de risque que les programmeurs effectuent une modification qui casse ou altère soudainement la fonctionnalité de l'interface.

Stateless

Nous allons maintenant examiner la contrainte Stateless. Le comportement stateless est une caractéristique particulièrement critique des architectures basées sur REST. Cela signifie que le serveur qui fournit les ressources applicatives ne stocke pas d’informations entre les requêtes et n’impose pas de séquence de traitement pour les appels et les requêtes. Le résultat de chaque requête doit être hiérarchisé uniquement en fonction de son contenu et de l’opération spécifiée – et non en fonction de comportements antérieurs concernant des séquences d’événements ou des ordres d’opérations.

Cette propriété est la clé pour l’évolutivité et la résilience des services, car elle signifie que toute instance d’une ressource répond à une requête de la même manière, indépendamment des calendriers de traitement généraux. Cependant, la conception stateless est compliquée à réaliser, en particulier lorsque les requêtes fréquentes contiennent des quantités importantes de données liées à l’état. La façon la plus simple de l’aborder, si possible, est d’éviter complètement de stocker les données internes entre les requêtes de ressources, y compris la séquence spécifique des appels et des requêtes.

Mise en cache

La contrainte qui semble dérouter le plus les architectes est l’exigence de mise en cache. Essentiellement, une architecture est antémémorisable (cachable) si la réponse d’un serveur peut être stockée dans un dépôt intermédiaire et, idéalement, abstrait. En cas de besoin, ce dépôt peut offrir ces réponses en cache pour un point d’emplacement de réutilisation et garantir – pour une période déterminée, au moins – que le comportement de ces réponses ne changera pas.

Il n’est pas nécessaire que tout puisse être mis en cache pour satisfaire à cette contrainte, mais chaque réponse qui peut l’être facilement et à un coût raisonnable doit être identifiée. De plus, le cache doit être capable de servir de nouvelles requêtes chaque fois qu’il peut gérer en toute sécurité des charges de travail lourdes à la place du serveur.

Si les réponses du serveur et les ressources qu’il fournit ne font pas l’objet de mises à jour programmées ou de changements de fonctionnalités, il est prudent d’inclure cette information dans les réponses du serveur au client. De cette façon, les systèmes d’application aux abois peuvent s’appuyer sur le cache en cas de retard dans les réponses ou de panne du serveur.

Modèle de système multicouche

La cinquième contrainte de l’architecture REST est le modèle de système en couches, selon lequel une application doit pouvoir définir les ressources en les affectant à des couches de fonctionnalité, chaque couche correspondant à une capacité de service unique et partagée. Dans certains cas, ces capacités peuvent être quelque chose de simple, par exemple des activités de répartition de charge. Dans d’autres cas, la strate peut abriter un processus plus complexe qui exige plusieurs serveurs et éléments logiciels, comme le traitement des données volumineuses.

Comme c’est le cas pour la contrainte de mise en cache évoquée précédemment, il n’est pas nécessaire de segmenter chaque service RESTful en sa propre strate. Au lieu de cela, il suffit de se concentrer sur la capacité à prendre pleinement en charge le modèle en couches lorsque cela est requis. Heureusement, la mise en œuvre d’un tel modèle est relativement simple, à condition que l’architecture soit conçue pour le gérer.

Le code à la demande

Le code à la demande est la dernière contrainte, et la seule parfois considérée comme facultative. Cette pratique stipule que, lorsqu’elles répondent à des requêtes, les ressources RESTful doivent être prêtes à fournir du code qui sera interprété côté client plutôt que côté serveur (ou quelque part entre les deux). Le fait de pousser du code côté client permet de distribuer le travail lorsque l’exécution côté serveur risque de provoquer des défaillances ou des problèmes de performance.

Pour mettre en pratique ce modèle, il faut connaître un peu les capacités d’exécution du code des clients qui accèdent à une ressource. Pour ce faire, le serveur doit identifier les capacités spécifiques du client afin de s’assurer que le code s’exécutera réellement comme prévu de ce côté-là. Il utilise généralement un langage de programmation universel que la plupart des composants applicatifs associés prennent en charge et comprennent lors d’un échange de code.

Pour approfondir sur Architectures logicielles et SOA