Est-il possible de construire une architecture web agile simplement ?

Je vais vous présenter une première réflexion sur une méthode simple pour concevoir une application web agile.

D'un côté, il existe des méthodes de gestion de projet agile qui mettent l'accent sur le management, la souplesse de l'équipe, la communication accrue avec le client ; et, d'un autre côté, il y a des méthodes pour construire des architectures qui sont, quant à elles, orientées techniques ou fonctionnelles (SOA, REST, etc...).

Dans ce post, je vais tenter de proposer une première solution pour joindre ces deux mondes, que j'essaierai d'améliorer petit à petit dans de prochains articles sur le blog de Netapsys.

Qu'est-ce qu'une architecture agile ?

L'architecture agile doit tout simplement répondre aux contraintes des méthodes agiles citées plus haut. C'est à dire : la modification d'une fonctionnalité, ou même la réécriture d'une partie de l'application, ne doit pas compromettre la stabilité de l'application. Le développeur doit disposer de plus de temps pour améliorer ou faire évoluer son programme que pour le tester ou corriger des bogues.

La première étape est de modulariser son application afin de rendre son développement en phase avec les règles de l'agilité : les retards pris sur un module ne doivent pas affecter le développement d'un autre module. C'est un des principes des méthodes agile : il se peut que les priorités du client changent pendant la réalisation du projet.

Aujourd'hui, nous nous focalisons un peu trop sur l'utilisation d'outils tels que Maven, Struts, Spring et j'en oublie... Le découpage de l'application est ainsi stratifié en couches techniques tel un mille-feuilles : on commence par une couche Struts, une couche Spring , une couche Hibernate, et on recouvre avec un beau glaçage Maven.

Mille-feuilles

Qu’en est-il de la maintenance du programme? de la gestion des erreurs? de la stabilité de l'application ? Théoriquement tout fonctionne car vous avez bien sagement implémenté vos frameworks et de plus, vous avez écrit tous vos tests unitaires avec un test par classe ou par méthode.

Tout est parfait ?

Non, ce découpage rend le site difficile à maintenir. L'ajout de fonctionnalités peut impliquer de modifier toutes les couches de l'application. Pour un nouvel entrant dans l'application, se retrouver dans les couches est difficile : tout est noyé dans un monolithe bien épais, stratifié en package (au sens java) qu'il faut éplucher tel un géologue !

Repenser une partie de l'application implique de tout réécrire car les composants sont liés entre eux. Et surtout, il faut réécrire tous les tests unitaires !

Ce que je propose se fonde donc sur ma propre expérience en la matière, sur la lecture de quelques blogs sur l'architecture et sur certaines observations évoquées lors des pauses café !

Découper son application en modules

Dans un premier temps, ayons une vision systémique de notre site internet : décollons notre nez de l'écran et prenons de la hauteur. Oublions les dizaines de frameworks que nous aimerions utiliser pour construire notre application. Notre site internet n'est plus un site internet, il devient un logiciel. Nous sommes remontés d'un cran dans le niveau d'abstraction de notre conception.

Dans un deuxième temps, découpons notre projet en modules. Pour cela, nous allons utiliser un tableau pour noter les différents modules. Le tableau permet d'avoir un découpage horizontal et un découpage vertical des différentes parties de notre application.

Dans notre exemple, nous allons développer un site web simple pour gérer des garages, des voitures et des clients.

Le découpage horizontal est le plus important car il décompose les différents modules fonctionnels de votre application : dans notre exemple, nous nous retrouvons avec le découpage suivant :

tableau1.png

Chaque module communique avec un autre par des flux ou par des signaux. Un flux peut être un traitement en entrée ou en sortie d'un module. Il peut se matérialiser par un objet, un fichier, une file JMS par exemple. Un signal est un événement remonté par un module, la plupart du temps, c'est une erreur.

Ce découpage horizontal nous permettra de gérer nos modules fonctionnels indépendamment. Par exemple, un développeur peut être affecté à un module. De plus, on peut imaginer un module dans un WAR différent. Ainsi, on peut mettre à jour des modules sur un serveur de production sans impacter les autres !

Troisièmement, découpons notre application verticalement. Nous abordons l'aspect
technique. Dans cette phase, nous appliquerons les recettes bien connues d'architecture applicative.

Nous obtenons, par exemple, le tableau suivant :

tableau2.png

Tous ces modules vous sont familiers sauf un... le module superviseur. C'est le module qui récupère le flux final de la vue ou alors le signal remonté par un des modules et qui décidera quelle action effectuer. Ce module a aussi la tâche de logger dans un fichier les événements anormaux ou/et alors vers l'écran du navigateur Internet. J'ai bien séparé ce module car c'est lui qui va permettre de remonter correctement les erreurs et ainsi, aider à stabiliser rapidement l'application.

Couplage entre les modules

Le découpage des modules étant terminé, assemblons-les maintenant. Cette étape est très importante: c'est la pierre angulaire d'une bonne architecture agile.

Nous allons définir deux niveaux de couplage (restons simple... ne compliquons pas la méthode dès le début !) et déterminer la meilleure solution pour coupler nos différents modules présents dans notre tableau.

Le couplage fort à l'avantage d'être rapide à mettre en place et plus performant. Par exemple, deux modules peuvent être liés simplement par échange d'objets en appliquant des patterns (singletons, fabriques abstraites, etc...). Le problème d'un couplage fort, c'est que les deux modules doivent être présents sur le même serveur, ainsi, il n'est pas possible de mettre à jour un composant sans que l'autre soit impacté.

Le couplage faible utilise une couche intermédiaire comme par exemple l'utilisation d'un service web, de files JMS, etc. L'avantage est que nous pouvons installer, déplacer nos modules sans modifier les sources de l'application.

Plus le couplage entre les modules est faible, plus votre projet est agile !

Ainsi nous choisirons des solutions proposant un couplage fort entre les modules sur les lignes verticales de notre tableau et un couplage faible entre les modules sur les lignes horizontales.

Les tests unitaires seront focalisés avant tout sur l'échange de flux entre les modules et non sur les objets du programme : la réécriture des modules n'affectera pas les tests unitaires ! On gagne ainsi du temps de développement et on ne perd pas son temps à réécrire ces tests unitaires.

Voilà, nous avons fini de définir très simplement notre architecture agile, nous pouvons maintenant nous concentrer sur les outils à utiliser !

Dans un prochain post, j'irai un peu plus loin dans ma réflexion en vous parlant de la configuration des flux entre modules, et la mise en place de plusieurs versions d'un module en même temps (pour par exemple effectuer une mise à jour sans arrêter le site internet) et tout cela à partir d'un composant particulier : l'hyperviseur. L'hyperviseur sera le garant de la souplesse de notre application et donc... de l'agilité de notre architecture !

Un commentaire

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.