Capitaliser sur du code ; ça c’était avant
On ne le dira jamais assez : chaque projet informatique est unique. Il subsiste cependant des points communs d’un projet à l’autre. Des points que nous pouvons identifier pour anticiper les problématiques, et ainsi monter une solution qui bénéficie, de proche en proche, des expériences passées. On essaie donc de « capitaliser », comme les vils financiers, pour ne pas avoir à réinventer la roue.
Parmi les façons classiques de capitaliser, dans le monde du logiciel, il y a :
- la reprise de composants logiciels existants. Soit par la reprise de binaires, soit par l’inclusion du code source existant au sein du projet. Il peut s’agir de l’utilisation de librairies existantes et éprouvées libres,… ou pas (jquery, winnovative pour la génération de rapports office, etc.)
- la façon, la méthode d’assemblage de ces différents composants. Typiquement, sur une application web, nous allons identifier un front-end et un backend. On sait que l’on va devoir organiser le code de façon à bien séparer les deux parties, on peut alors construire des « templates » de projet, afin de préparer en amont la future organisation du code. Aujourd’hui, de nombreux outils proposent de préconstruire cette organisation (django en python, ou rails en ruby, par exemple).
Au final, le schéma d’une architecture d’application web se retrouve souvent sous la forme :
- client JS + HTML
- serveur web avec du code serveur type C#, Java, Python, Ruby, WhatElse,…
- base de données PostRacle MySQLServer, EtTantD’autres…
Ensuite, il y a plein de façon de séparer les couches logiques : mais ça de nos jours, tout bon dev connaît ça par coeur : l’authentification (basic http, authentification par session/cookie, oauth, open id, etc.) , la méthode d’accès à la base, (direct ou orm) la génération de rapport, (office, csv, etc.). Tout ce joyeux monde est inclus comme un tout à l’éxecutable sous la forme de librairies internes. La partie runtime ne fait donc pas vraiment l’objet de séparation particulière, si ce n’est une organisation dans la façon de concevoir ces packages / namespaces, ou autre.
Bon, bien, bien. Et puis un jour, on se prend ça dans les dents.
Dans son article, Steve Yegge, programmeur et blogueur embauché par Amazon, puis Google, décrit la façon de s’organiser d’Amazon. Chaque équipe expose ses données au sein d’un annuaire de services web. Et chaque service peut être utilisé par son créateur (comme une librairie) mais aussi par les autres équipes de la communauté.
Œuvrez pour l’humanité, exposez vos services (web)
Pour faire rapide, pour faire de l’architecture orienté service, il ne suffit pas de dessiner de jolis crobards dans un coin du tableau
blanc et annoncer « bin yaka faire de l’ORM truc much Linq-Hibernate-machin chouette, et les exposer avec du REST/SOAP ! ça va régler pas mal de problèmes, non ? ».
Non. Ce type d’architecture nécessite de lever un peu les yeux du guidon et de voir chaque projet comme faisant partie d’un tout. Le tout pouvant être traduit comme l’entreprise, la communauté, (dans le cas d’Amazon, l’humanité). L’idée étant de prendre un peu de hauteur, et de se demander comment s’organiser (pas organiser son code, s’organiser, nous, les gens) pour séparer toutes les fonctions d’une application sous forme de services (web principalement, mais on pourrait imaginer d’autres protocoles plus rigolos) et comment en faire bénéficier la communauté : les développeurs, les clients, et tous si affinité. La finalité d’une telle architecture peut être dans un petit cadre restreint partager des données entre les acteurs et lorsque la communauté est énorme, on peut aussi se servir de cette architecture pour en monayer l’accès. Bienvenue dans l’ère du ouèb 2.0. Tadam…
Un exemple typique : l’authentification / identification et la gestion de l’utilisateur de ces droits. Cette fonction se retrouve dans quasiment tous les projets. Et bien si vous n’avez pas envie de développer votre couche d’authentification, vous pouvez, en utilisant le service commun, utiliser celle qui a déjà été développée, hébergée, et éprouvée par d’autres, et bénéficier ainsi de ce que la communauté a fait pour vous. Et on généralise ça non seulement aux utilisateurs humains (utilisateurs d’applications), mais aussi pour authentifier des applications (dans le cas de OAuth, cet usage est même central : c’est exactement ce qu’il se passe lorsque vous autorisez l’accès à certaines de vos données à une application dans le Play Store de Google, en utilisant le service d’authentification de Google.).
L’architecture orientée service, c’est généraliser ce principe à toute fonctionnalité que l’on pourrait exposer au monde extérieur, d’une façon ou d’une autre.
On pense alors à tout un tas de services différents :
- service d’authentification
- service de monitoring
- service de génération de rapports (Excel / word)
- service de récupération de données métiers (exemple : utiliser les API distantes de l’OpenData chez IGN…)
- service d’annuaire des services
- service d’accès à une base de données…
- …
Ces services peuvent s’utiliser les uns les autres. Par exemple, pour générer tel rapport, le service de génération de rapport peut très bien demander au service d’authenfitication / identification s’il a le droit de le faire pour tel compte, et au passage, il envoie des données au service de monitoring pour lui faire part de cette demande et la faire apparaître dans les statistiques du système global.
Pour faire beau, ce genre d’architecture se trouve en général sous la forme d’une offre PAAS (Plateforme As A Service). Octave Klaba, CTO d’OVH en a fait d’ailleurs une longue promotion lors de son dernier Summit.
La façon d’utiliser ces APIs est souvent du REST, mais peut aussi être en SOAP. Les formats sont divers et variés en fonctions des usages et des préférences de chacun : JSON, XML, CSV, YAML, que sais-je… Conséquence : les différentes applications ne sont pas développées uniquement pour le ou les clients du projet cible. Elles sont au départ développés par et pour les développeurs qui en ont besoin, puis l’offre est « ouverte » vers l’extérieur. C’est le principe de « eat your own dog food ». Les développeurs se servent de leur logiciel avant même de le vendre.
Structurellement, chaque service clé serait donc en mesure d’offrir ses fonctions non pas à une seule application ni à un seul client mais à toute demande identifiée et authentifiée, voire à toute demande publique dans le cadre de l’OpenData. Les conséquences d’un tel choix d’architecture sont les suivantes :
- grande simplification potentielle des applicatifs pour se concentrer sur le spécifique.
- chaque service central devient alors critique car plusieurs applications vont en dépendre.
- le couplage entre les différents services pose aussi la question de la gestion du versionning et de leur cohabitation.
Autant de sujets qui ne sont pour la plupart du temps pas abordés ni résolus lors du développement d’applications monolithiques classiques. Dans le cadre d’une telle démarche, le métier se transforme. Lorsqu’un service est mis en place, au lieu de le voir par le trou de la serrure dans un contexte restreint et spécifique, il faut partir du principe que la demande extérieure peut-être très importante, soumis à des demandes émanant de contextes et d’usages différents, et ce en permanence. Le monitoring fait donc lui aussi partie des concepts clés pour mener à bien une telle architecture.
Structurellement faite pour grandir et renforcer les liens
Lorsque l’on code une appli, pour un nouveau projet, la question du dimensionnement est structurante. Si votre projet est fait pour gérer 10 utilisateurs, et écrire 100 enregistrements par jour en base de données, la question du volume est anecdotique. Par contre, si votre service est utilisé par des milliers de bons hommes qui effectuent 100 appels par seconde, on sent bien que la question de la scalabilité (capacité à gérer une grande quantité d’utilisateurs)va être centrale.
De part le découpage en services web dont la fonction est très restreinte, une autre caractéristique structurelle d’une architecture oriéntée service est que l’infrastructure a « envie » de grandir par nature, car cette dernière est utilisée par tous. La scalabilité fait donc partie des gènes d’une plateforme orientée service.
La mise en commun de services implique chacun dans la bonne santé du système au global. On transforme un cercle vicieux (1), en un cercle vertueux (2) dans lequel chaque nouveau développeur se transforme en « devops » et contribuera par le simple usage à l’enrichissement et à l’amélioration des services communs, ne serait-ce que par la remontée de bugs des services des copains. Ajouter de nouveaux services, les rendre utilisables par tous, les inclure dans une démarche de gagnant/gagnant et de capitalisation des développements _et_ de l’opérationnel (le fameux concept « devops »)
Le défi lancé par la mise en place d’une telle architecture est donc passionnant. Il sort du cadre d’un seul projet, en se posant des questions touchant au fonctionnement global de l’infrastructure logicielle et de l’interaction technique et humaine entre les projets de la communauté.
Footnotes
(1) en tant qu’adminsyss je ne veux pas que le système grossisse car je ne pourrai plus le gérer s’il est trop gros avec trop de cas spécifiques à gérer
(2) en tant que devops, plus de monde utilise mon service plus je suis content car ce dernier vis et est partagé dans ma communauté :).
Crédit image d’en-tête : Vincent Astier
Les derniers articles par jboucher (tout voir)
- Le développement logiciel, un art atemporel ? - 13 janvier 2016
- Introduction à une architecture orientée services - 4 novembre 2015