Le navigateur comme client riche, l’exemple d’AngularJS

Le monde du développement Javascript connaît une forte effervescence depuis quelques temps au point qu’il n’est plus possible aujourd’hui d’ignorer son influence. Si comme nous, vos habitudes sont plutôt centrées sur Java, vous aurez peut-être quelques difficultés à vous repérer dans cette nouvelle jungle. Comme nous avons commencé à défricher le sujet de notre côté, nous vous proposons une série d’articles qui se focalisera sur l’une des solutions qui a particulièrement le vent en poupe : AngularJS.

Au temps du Web 1.0

Traditionnellement, une application Web écrite en Java se découpait en plusieurs couches :

  • Une couche qui attaquait une base de données en général avec l’aide d’un ORM
  • Une couche qui se chargeait de la logique métier
  • Une couche cliente chargée de générer en pratique les pages HTML destinées à s’afficher dans le navigateur.

Toutes ces couches n’étaient pas nécessairement présentes en tant que telles (ou il pouvait même y en avoir un plus grand nombre), mais dans tous les cas, au final, il fallait au moins une couche cliente chargée de renvoyer les pages HTML au navigateur.

Il est vite apparu que de simples pages JSP ne pouvaient convenir à des applications dignes de ce nom et le paradigme MVC (ou des variantes) a fini par s’imposer pour les frameworks de navigation et présentation, le représentant le plus canonique étant Struts qui continue d’être utilisé malgré son âge.

Dans cette optique, le serveur avait à charge de servir des pages HTML dynamiques, en général remplies à l’aide de données provenant de la base de données. Bien d’autres frameworks sont apparus depuis Struts, mais ils reprenaient le paradigme du terminal passif qu’était le navigateur : à chaque clic de l’utilisateur, une requête était remontée vers le serveur, lequel l’analysait, puis servait la bonne page HTML correctement remplie.

Du point de vue de l’être humain qui utilisait le navigateur, l’application pouvait sembler ni très réactive, ni très rapide, et assez archaïque dans sa conception (sauts de pages en pages avec d’éventuels problèmes de retour en arrière).

La révolution AJAX

Avec l’introduction d’Ajax est apparue l’idée qu’il était plus rapide et plus agréable pour l’utilisateur de restreindre le nombre de pages à servir et de ne changer visuellement que ce qui était nécessaire en interrogeant (de manière asynchrone) le serveur pour obtenir les données à afficher sans avoir à changer le contenant, c’est à dire le reste de la page HTML.

Prenons un exemple simple : sans Ajax, lorsqu’on avait une liste paginée dans une page et qu’on voulait aller aux données suivantes, en pratique, on cliquait sur un lien et la même page était régénérée avec simplement des données différentes dans la liste. Ce qui était loin d’être optimal et intellectuellement satisfaisant.

Avec Ajax, la page n’est pas régénérée, seules les données dans la liste changent suite à un échange avec le serveur qui devient simple pourvoyeur de données. Dans la pratique toutefois, l’introduction d’Ajax est souvent restée partielle et opportuniste : on s’est retrouvé à implémenter en Javascript une part du comportement du côté du navigateur tandis qu’une autre restait portée par le serveur.

Le client léger s’enrichit

Mais en généralisant le mode Ajax, on peut concevoir une application complète écrite en HTML/Javascript/CSS, chargée une bonne fois pour toute dans le browser, à la façon d’une application desktop et dans laquelle on va naviguer en n’interrogeant le serveur que lorsqu’on a des données à afficher ou des informations qui peuvent changer l’ergonomie de l’application (droits utilisateurs, par exemple).

On retrouve finalement la logique du client lourd, telle qu’elle existait avant le web, qui avait comme gros défaut de ne pas être normalisée mais qui était autrement plus ergonomique et plus réactive qu’une application web classique. Sans compter que du point de vue de l’organisation, une fois les interfaces définies, on pouvait répartir le travail entre deux équipes, chacune connaissant bien son domaine : une qui s’occuperait de la partie cliente et l’autre de la partie serveur.

L’idée émergente était de transformer le navigateur, simple terminal passif, en client riche, sur le modèle du client lourd de naguère mais de manière plus normalisée, laissant au serveur la responsabilité de la logique métier à travers des web services (au sens le plus large du terme).

Des solutions, comme Flex ou Silverlight par exemple, sont apparues pour aller dans cette direction, mais pour de bonnes autant que de mauvaises raisons, elles n’ont eu qu’un succès mitigé. Certes elles avaient besoin d’un plug-in pour s’exécuter dans le navigateur mais le plugin Flash était alors déjà très bien implanté. Le vrai problème venait des habitudes acquises et de la réticence des acteurs de l’Open Source envers des solutions propriétaires ou semi-propriétaires.

L’émergeance des frameworks Javascript

Quoi qu’il en soit l’idée avait fait son chemin, mais il fallait la réaliser directement avec le navigateur, donc à travers un mélange de HTML, Javascript, CSS et Ajax, ce qui est assez rebutant pour un développeur Java (ou pour un développeur tout court, d’ailleurs). De surcroît l’absence de framework côté client se faisait sentir (l’équivalent de Struts côté serveur).

Progressivement, du fait des évolutions du HTML, du Javascript et des CSS, des solutions sont apparues pour répondre à ce besoin, proposant à la fois un framework de développement et une surcouche pour masquer en partie la complexité des technologies mises en œuvre.

Ceux-ci sont aujourd’hui nombreux :

AngularJS

Dans cette nébuleuse de solutions Open Source, nous allons regarder de plus près AngularJS, énième produit Google sous licence MIT. Ce dernier est très séduisant car outre sa popularité grandissante, il propose :

  • Un framework de type MVC
  • Un système de binding bidirectionnel qui est à mon sens le gros plus d’AngularJS
  • Une couche d’abstraction pour la manipulation du DOM
  • La possibilité d’ajouter des composants spécifiques HTML/DOM grâce à la notion de  » directive  » d’AngularJS
  • Un système de tests unitaires (Karma)
  • Un système de tests applicatifs (Protractor, équivalent de HttpUnit)
  • Un système unifié pour les requêtes au(x) serveur(s) (de base en JSON)
  • Une architecture modulaire et un gestionnaire de modules (Bower)

A noter que Karma, Protractor et Bower ainsi que le serveur HTTP servant au développement sont fournis par NodeJS/npm (et nécessitent donc l’installation de NodeJS sur la machine même si on ne prévoit pas de l’utiliser en tant que serveur).

Nous développerons plus en détail dans un prochain article les spécificités d’AngularJS. Toutefois dans notre optique qui est de s’adresser à des développeurs Java, nous resterons fidèle à l’idée d’un serveur JEE (ou du moins basé sur des servlets tel que Tomcat) en s’appuyant par exemple sur Jackson (versions antérieures à 2 et versions postérieures à 2) pour gérer les flux JSON de façon à ce que l’application AngularJS puisse dialoguer naturellement avec ce serveur.

Évidemment dans l’écosystème AngularJS, on préfère travailler en Javascript de bout en bout, et il existe une foultitude de dorsaux Javascript (NodeJS, Vertx, Firebase, etc …) mais ce n’est pas le scénario que nous allons privilégier ici

Enfin, si vous êtes un développeur Java qui ne connaît Javascript que de façon assez superficielle, quelques piqûres de rappel s’avéreront nécessaires. En effet, si le Javascript peut présenter pas mal de similitudes avec le Java, ce sont des apparences trompeuses et ces derniers temps, la tendance à exploiter les spécificités de Javascript se sont développées jusqu’à aboutir à des habitudes qui tranchent assez nettement avec celles connues en Java.

Analyse et veille technologique , , ,