AXOPEN

Architecture des applications web en 2015

Introduction

Plus l’informatique avance et plus le choix d’une architecture web se complexifie. Faisons le point sur l’architecture des applications web en 2015.

Un peu d’histoire sur l’architecture web

Revenons d’abord un peu en arrière vers les débuts d’internet. A l’époque, il était très facile de choisir une architecture parmi les quelques technologies web existantes. Il suffisait en somme de choisir sa technologie serveur, soit in fine PHP ou Java.

On a ensuite vu arriver de nombreux frameworks côté serveur : Symphony ou Zend pour le PHP, Java EE ou Spring pour le Java. Le but était de rendre le développement plus facile pour les développeurs en organisant le code sur différentes couches applicatives et en proposant des fonctionnalités built-in avec un niveau d’abstraction élevé. Il suffisait ainsi d’apprendre le langage de programmation, les différentes couches imposées par le framework et les principales fonctionnalités fournies. L’intégralité du traitement s’effectuait côté serveur, la page HTML était générée puis transmise au navigateur. L’architecture restait donc simple.

Le javascript commençait alors à être utilisé (avec parcimonie) pour améliorer l’ergonomie. Puis l’Ajax est arrivé et à tout bouleversé. Il est petit à petit devenu évident qu’il n’était pas utile de changer de page à chaque clic (et ainsi tout recalculer côté serveur), alors qu’on pouvait ne mettre à jour que des morceaux de la page HTML. Avec Ajax, Javascript a pris tout son sens et de nombreux développeurs, souvent réticents, ont du se rendre à l’évidence : le traitement côté client ne doit plus être négligé. Suite à cette évolution de raisonnement majeure, moult frameworks Javascript ont vu le jour pour répondre au besoin toujours croissant de structurer le développement côté client.

Profil de l’architecture web idéale

Bien que les architectures applicatives soient en constante évolution, nous prenons le parti de décrire ce qui pour nous est l’architecture rêvée pour une application web en 2015. Dans cette architecture, nous ne prenons pas en compte des considérations telles que le référencement ou le mobile.

Comme nous l’avons dit, une architecture applicative web moderne ne peut se contenter d’exister côté serveur. Il y a donc en réalité deux architectures symbiotiques à définir.

Côté serveur, une application web doit réunir les qualités suivantes :

  • une structure en couches minimaliste : le strict nécessaire, ni plus ni moins. Il est nécessaire d’organiser le code de son application, mais il est contre-productif de s’embarrasser d’une architecture plus complexe que le travail à effectuer ne l’exige.
  • une approche orientée services : plutôt que systématiquement retourner l’intégralité de la page HTML à chaque réponse HTTP, une application web doit permettre de limiter les transferts de données au strict minimum : soumission partielle de formulaires, mise à jour de la seule partie de HTML concernée, voire seulement des données (avec prise en charge en Javascript côté client). Il ne s’agit donc plus d’appeler telle ou telle page mais d’invoquer tel ou tel service ultra spécialisé.
  • des services stateless : trop d’applications web succombent à la tentation de garder l’intégralité des données utilisateur en cours en session. Il en résulte des systèmes gourmands en ressources et là encore contre-productifs. Dans la majorité des cas, identifier l’utilisateur est suffisant (et encore, s’il s’agit d’une application connectée). Récupérer les quelques informations utiles dans une base de données est souvent plus rapide que naviguer dans une map de sessions pléthorique pour en extraire ces mêmes informations. Sans parler des risques de télescopage si un utilisateur ouvre la même page dans deux onglets différents pour des actions différentes.
  • des performances irréprochables : il n’est pas déraisonnable de demander à une application web de toujours répondre en quelques dizaines de millisecondes, et dans tous les cas de ne jamais dépasser une seconde de temps de réponse (à supposer bien sûr que l’utilisateur dispose d’une connexion décente). Les technologies actuelles permettent des traitements ultra rapides côté serveur et les débits de connexion sont énormes, il n’y a donc pas d’excuse pour des performances qui laissent à désirer.
  • une résistance à la montée en charge : c’est sans doute le point le plus difficile à évaluer autant qu’à mettre en oeuvre. Une application web devrait pouvoir dépasser sans ciller (même si elle ralentit un peu) la barre symbolique des 10 000 connexions. Si certains serveurs web le font (comme Nginx), les applications ne gèrent pas encore ce problème. Qu’elles fonctionnent en CGI, FastCGI ou qu’elles soient portées par des serveurs d’applications, on reste sur une gestion du type 1 requête = 1 thread qui mène inévitablement au déni de service passé un certain seuil. L’application parfaite devrait donc gérer ses connexions selon un pattern reactor ou proactor, qui lui permette de résister à la charge.

Côté client, on peut donc attendre les propriétés que voici :

  • la gestion des appels aux services distants : si l’application serveur fournit des services spécialisés, le client doit pouvoir les invoquer et gérer les réponses.
  • la légèreté de l’architecture : le principe des services asynchrones implique une certaine quantité de Javascript. Inutile pour autant d’amalgamer une quantité néfaste de plugins récupérés aux quatre coins du web. Pour les plus sceptiques et les néophytes, il convient de se former au Javascript pour être à même de distinguer l’utile du superflu et de concevoir une architecture légère et efficace. N’oublions pas que par définition nous ne connaissons pas la puissance de la machine qui exécutera notre code.
  • la fluidité de navigation : pas d’excès d’effets graphiques, pas de surcharges des fonctionnalités de base du navigateur (précédent, clic droit, tab…). Une certaine mode consiste à concevoir des applications sur une seule page : si l’exercice est intéressant, on notera tout de même que cela prive l’utilisateur des indicateurs classiques de navigation comme l’URL.
  • une empreinte minimaliste : si on ne peut empêcher (et d’ailleurs on ne le souhaite pas) le navigateur de mettre nos ressources statiques en cache, inutile pour autant de les multiplier. Idem pour les cookies. Enfin, si l’on peut se réjouir de la possibilité de créer des bases de données côté client, la pertinence d’y recourir est plus que douteuse dans l’écrasante majorité des cas. On préférera ne pas polluer la machine de l’utilisateur et garder sagement nos données côté serveur.

Exposer des services web en JSON

A présent que nous avons le profil de notre application « parfaite », quel peut être le meilleur moyen d’exposer des services web ?

Il semble que la mode des web services SOAP ait fait long feu (mais restent utilisés pour des appels ou le besoin de structuration de données reste fort), ces derniers ayant été supplanté dans le coeur des architectes par les services JSON. Il ne s’agit pas d’un effet de mode mais simplement du pragmatisme le plus simple : les performances sont bien meilleures et les services bien plus simples à mettre en oeuvre.

A la lourdeur du XML de SOAP succède la représentation de données ultra optimisée du JSON. De plus, si l’on peut recourir aux plugins les plus élaborés pour exposer des services JSON, on peut aussi se contenter de dialoguer en HTTP avec un content-type JSON. Si la facilité de parsing du JSON côté serveur est très liée à la technologie choisie, la problématique est absente côté client puisque le JSON est déjà le format des objets Javascript.

Un framework client type AngularJS

La contrainte de la légèreté de l’architecture côté client force à penser que le recours à un framework n’est pas la meilleure solution puisque par définition il fournira des fonctionnalités dont nous n’aurons pas l’usage mais dont le code sera tout de même acheminé.

Toutefois, il faut reconnaître que le Javascript, malgré de nombreuses qualités, n’est pas le langage le plus facile à structurer, ni le mieux connu des développeurs. Un coup de pouce sera donc souvent apprécié, et le populaire AngularJS peut être la solution. Il permet de reproduire côté client une architecture Modèle-Vue-Contrôleur avec des templates HTML, des contrôleurs métier et des appels de services asynchrones. Mais attention encore une fois à ne pas trop multiplier les traitements côté client, c’est le rôle du serveur d’en assumer la plus grosse part, et le client n’a peut-être pas une machine très puissante.

Choix technologiques

Si le choix technologique côté client revient à choisir un framework (ou pas), la question est plus complexe côté serveur.

A ce jour, aucune technologie ne paraît répondre idéalement à toutes les exigences du cahier des charges. On peut revenir sur l’opposition des deux principales technologies web, PHP et Java, mais les reproches porteront globalement sur les mêmes points : la performance (surtout PHP) et la montée en charge. Il en va de même pour ASP.NET, également sur le podium des technologies web les plus utilisées.

On peut envisager un choix plus exotique, comme ColdFusion, Ruby, Perl ou Python. Mais ces technologies plus confidentielles auront les mêmes défauts avec des qualités en moins.

Une alternative se distingue : celle du Javascript côté serveur avec NodeJS. Elle a deux qualités essentielles :

  • la facilité de manipulation des données au format JSON : puisque c’est le format natif du langage.
  • l’implémentation du pattern reactor par le puissant moteur V8 : c’est donc la seule technologie serveur qui soit théoriquement susceptible de résister à une montée en charge importante.

Mais attention toutefois à ne pas succomber trop vite à cette description séduisante. D’abord la résistance théorique à la charge est à confirmer. Quant aux performances, les essais comparatifs avec Java et PHP montrent a priori que NodeJS n’a pas à rougir, mais on manque sans doute encore de recul. Enfin, la syntaxe très imbriquée du Javascript ne se prête pas facilement à des architecture multi-tiers simples et claires. C’est évidemment possible, mais pas accessible à n’importe quel architecte ou développeur.

En somme, il n’y a pas de panacée mais des technologies ultra répandues et éprouvées sur lesquelles il sera facile de monter une architecture légère, orientée service et massivement stateless : PHP, Java et ASP.NET. Le challenger NodeJS tire toutefois son épingle du jeu, du moins sur le plan théorique : à tester pour les plus téméraires, à confirmer pour les autres.

Conclusion

Pour résumer, l’architecture logicielle web moderne se doit d’être aussi épurée que possible pour la simplicité de développement, de maintenance et pour les performances. Elle doit être orientée services, parce qu’il est toujours inutile de transporter sur le réseau un head, un header et un footer quand on veut seulement la deuxième page d’un tableau. Et elle doit être performante, simplement parce que la puissance de nos machines et la bande passante le permettent.

Quant aux choix technologiques effectifs, en attendant l’avènement d’une technologie supérieure qui détrônerait toutes les autres, ils doivent être guidés par la préférence soit vers l’optimisation des performances, avec moins de frameworks et plus d’innovation, soit vers des facilités de développement avec le recours aux technologies leaders du marché. Ceci étant dit, malgré des différences qui peuvent être significatives, il est possible de réaliser une application légère et performante avec n’importe quelle technlogie web, du moment que l’architecture est bonne.