Dans ce deuxième article, nous allons mettre en œuvre sur un petit exemple le processus simplifié que nous préconisons pour la modélisation des applications web, jusqu’à la conception détaillée sur la plateforme .NET.
Pour mémoire, ce processus (décrit dans l’article précédent) se situe à mi-chemin entre UP (Unified Process), un cadre général très complet de processus de développement, et XP (eXtreme Programming), en appliquant les principes de la modélisation agile (AM = Agile Modeling).
Nota : la description détaillée de ce processus ainsi que de sa mise en œuvre complète sur le cas de la librairie en ligne est parue récemment chez Eyrolles, dans la collection intitulée « Les cahiers du Programmeur », sous le titre : « UML 2 - Modéliser une application web ».
Le schéma général de la démarche est rappelé sur la figure ci-après, reprenant l’organisation en chapitres du livre précité.

Le cas concret servant d’illustration à notre démarche agile consiste en la modélisation d’un site web marchand, en l’occurrence une librairie. La librairie en ligne constitue en effet un exemple facile à comprendre et suffisamment représentatif des projets d’applications web. Nous nous sommes inspirés des fonctionnalités de sites existants, comme www.amazon.fr, www.fnac.com, et bien sûr celui de notre librairie préférée : www.eyrolles.com !
L’objectif fondamental de tels sites est de permettre aux internautes de rechercher des ouvrages par thème, auteur, mot-clef, etc., de se constituer un panier virtuel, puis de pouvoir les commander et les payer directement sur le Web. Dans le cadre de cet article, nous nous restreindrons à la fonctionnalité de gestion du panier virtuel.
Dans un véritable magasin, le client choisit ses articles les uns à la suite des autres, les dépose dans son panier, puis se rend à la caisse pour régler le tout. Les sites marchands tentent de reproduire ces habitudes d'achat le plus fidèlement possible. Ainsi, lorsque l'internaute est intéressé par un ouvrage, il peut l'enregistrer dans un panier virtuel, comme indiqué sur l’exemple de la figure suivante. Il doit pouvoir ensuite à tout moment en ajouter, en supprimer ou encore en modifier les quantités avant de passer commande.
L’acteur le plus important pour un site d’e-commerce est bien sûr l’internaute.
Ses cas d’utilisation principaux ont été mis en évidence par l’expression de besoins préliminaire du paragraphe précédent, à savoir :
Nous nous intéresserons plus particulièrement dans la suite de cet article au cas d’utilisation "Gérer son panier", comme illustré sur le diagramme de cas d’utilisation simplifié ci-après.
Nota : la plupart des diagrammes ont été réalisés soit à la main (c’est aussi cela la modélisation agile !), soit avec l’outil Enterprise Architect (www.sparxsystems.com).

Nous donnons ci-dessous la description textuelle détaillée du cas d’utilisation qui nous concerne (le style utilisé est celui préconisé par A. Cockburn dans son récent ouvrage de référence : « Rédiger des cas d’utilisation efficaces », Eyrolles, 2001).
Scénario nominal :
Le diagramme de séquence système d’un scénario représentatif est donné sur la figure suivante, utilisant les fragments d’interaction et les opérateurs UML 2 :

Comment identifier les concepts du domaine ? Plutôt que de partir à l’aveugle et nous heurter à la taille du problème à résoudre, nous allons prendre les cas d’utilisation un par un et nous poser pour chacun la question suivante : quels sont les concepts métier qui participent à ce cas d’utilisation ?
Par exemple, pour le cas qui nous intéresse (« Gérer son panier »), nous identifions facilement les concepts métier « Panier » et « Livre ». Nous allons modéliser ces concepts sous forme de diagrammes de classes contenant uniquement des attributs et des associations.
Le concept de panier est un concept du domaine, car dans les librairies réelles le client remplit également un panier avant de passer à la caisse. Le panier est simplement un conteneur des livres sélectionnés par le client. Cependant, nous devons prendre en compte le fait que le client peut choisir plusieurs exemplaires du même livre et que nous voulons le total du panier. Dans notre cas, le prix du panier est calculable simplement à partir du prix des livres sélectionnés, ce qui donne un attribut dérivé « /total » dans la classe Panier. Pour exprimer le fait que le panier peut contenir plusieurs exemplaires du même livre, nous allons ajouter un concept intermédiaire qui correspond à une ligne du panier et qui concerne donc un seul livre, mais avec un attribut quantité, initialisé à « 1 » par défaut.
Le diagramme de classes du domaine résultant de cette première réflexion est donné ci-après.

Dans ce paragraphe, nous allons identifier les classes d’analyse qui vont participer à la réalisation des cas d’utilisation.
Nous distinguerons trois types de classes d’analyse (comme proposé par I. Jacobson) :
Pour compléter ce travail d’identification, nous allons ajouter des attributs et des opérations dans les classes d’analyse, ainsi que des associations entre elles.
Le diagramme de classes participantes du cas d’utilisation « Gérer son panier » est donné ci-après (l’acteur est relié au dialogue qui est relié au contrôle, lui-même relié aux entités).

Les IHM modernes, en particulier celles destinées aux internautes via les applications web, cherchent à faciliter la communication avec l’utilisateur. Elles sont de plus en plus riches et puissantes. Mais cela oblige le concepteur du site à réfléchir de façon très précise au comportement attendu de tous ses éléments graphiques et pas seulement d’un point de vue visuel.
UML nous offre la possibilité de représenter formellement la navigation dans le site, au moyen d’un diagramme dynamique appelé diagramme d’états (ou éventuellement d’un diagramme d’activité). Le diagramme de navigation représente ainsi un ajout important dans l’arsenal des outils de modélisation du concepteur de site Web, puisqu’il fournit la possibilité de décrire précisément et exhaustivement les aspects dynamiques de l’interface utilisateur.
Un exemple de diagramme d’états de navigation concernant la gestion du panier est donné ci-dessous.

Dans ce paragraphe, nous allons maintenant attribuer des responsabilités précises de comportement aux classes d’analyse identifiées précédemment. Nous représenterons le résultat de cette étude dans des diagrammes de séquence de conception préliminaire. Nous construirons également une vue statique complétée sous forme de diagrammes de classes de conception préliminaire, indépendamment des choix technologiques qui seront effectués au dernier paragraphe.
L’attribution des bonnes responsabilités aux bonnes classes est l’un des problèmes les plus délicats de la conception orientée-objet. Pour chaque service ou fonction, il faut décider quelle est la classe qui va le contenir. Les diagrammes de séquence sont particulièrement utiles au concepteur pour représenter graphiquement ses décisions d’allocations de responsabilités. Chaque diagramme va ainsi représenter un ensemble d’objets de classes différentes collaborant dans le cadre d’un scénario d’exécution du système. Dans ce genre de diagramme, les objets communiquent en s’envoyant des messages qui invoquent des opérations (ou méthodes) sur les objets récepteurs. Il est ainsi possible de suivre visuellement les interactions dynamiques entre objets, et les traitements réalisés par chacun.
Par rapport aux diagrammes de séquence système, nous allons remplacer le système vu comme une boîte noire par un ensemble d’objets communicants. Pour cela, nous utiliserons dans ce paragraphe les trois types de classes d’analyse, à savoir les « dialogues », les « contrôles » et les « entités ». Le changement de niveau d’abstraction par rapport au diagramme de séquence système peut ainsi se représenter comme sur la figure ci-dessous.

Intéressons-nous au moment où l’internaute met de côté un premier livre dans son panier virtuel. Que se passe-t-il derrière le dialogue concerné ? Celui-ci passe la main à un contrôle spécialisé dans la gestion du panier. Ce contrôle a la responsabilité de créer le panier lors de la première sélection mais aussi toutes les lignes du panier au fur et à mesure. Il est également responsable d’afficher un dialogue particulier récapitulant le panier en cours et permettant à l’internaute de le modifier et de le recalculer.
Tout cela est représenté sur la figure suivante (diagramme de séquence).

Continuons maintenant en considérant un scénario dans lequel l’internaute modifie la quantité d’un ouvrage sélectionné, puis demande un recalcul de son panier.
Le contrôle reçoit une collection de quantités et la passe à l’entité panier. Celui-ci est responsable de la gestion de ses lignes. Il va donc demander à chaque ligne de se recalculer individuellement en lui passant en paramètre la quantité qui la concerne. Si cette quantité a été positionnée à zéro par l’internaute, la ligne est supprimée.

Pour terminer la gestion du panier, considérons enfin un scénario dans lequel l’internaute supprime explicitement une ligne du panier puis le vide totalement.

En partant du modèle d’analyse, nous allons affiner et compléter le diagramme de classes participantes. Pour cela nous utiliserons les diagrammes de séquence que nous venons de réaliser pour :
Que pouvons nous ajouter au diagramme de classes participantes d’analyse de notre cas d’utilisation ?
Le diagramme de classes de conception préliminaire résultant est fourni par la figure ci-après.

Nous allons maintenant incorporer dans nos diagrammes le choix d’architecture et les choix technologiques qui vont modifier les classes de conception préliminaire, les préciser, ajouter de nouvelles classes plus techniques, etc.
N’oublions pas que l’objectif principal du modèle de conception détaillée est de pouvoir être traduit directement en code !
Pour résumer, en .NET :
Comme indiqué précédemment, le dialogue GestionPanier va être implémenté par une page ASP.NET. Celle-ci va contenir du code HTML, des WebForms (pour les lignes du panier), ainsi qu’une référence à une classe C# que l’on qualifie de « CodeBehind ». Cette classe renferme un ensemble de méthodes que la page ASP.NET va invoquer pour simplifier sa tâche (un traitement un peu complexe gagne à être implémenté dans le CodeBehind et appelé par une instruction de script dans la page ASP.NET).
Cette structure de la page ASP.NET est représentée sur le diagramme de classes partiel qui suit.

Voici un exemple de page script qui gère le panier (il faudrait bien sûr peaufiner le graphisme) :

Si nous reprenons les mêmes hypothèses de scénario que précédemment, nous obtenons les diagrammes de séquence suivants :


En extrapolant le travail précédent sur les diagrammes de séquence, le diagramme de classes de conception détaillée autour de la gestion du panier est le suivant.

Le code C# de la classe « Panier » est donné sur le listing suivant :
namespace LogiqueMetier.Gestion{
using LogiqueMetier.Catalogue.Livre;
using System.Collections;
public class Panier {
private double tot ;
public double total {
get { return tot; }
}
private IList lesLignesPanier = new ArrayList();
public Panier() { }
public void recalculer(IList quantites) {
total = 0;
int i = 0;
foreach (LignePanier ligne in lesLignesPanier){
ligne.recalculer(quantites[i]);
total += ligne.prixTotal;
}
}
public void ajouterLigne(Livre l) {
// Ne pas ajouter de ligne s'il en existe déjà une pour ce livre
foreach (LignePanier ligne in lesLignesPanier){
if (ligne.livreConcerne.Equals(l)){ return; }
}
lesLignesPanier.Add(new LignePanier(l));
}
public void supprimerLigne(Livre l) {
foreach (LignePanier ligne in lesLignesPanier) {
if (ligne.livreConcerne.Equals(l)){
lesLignesPanier.Remove(ligne);
break;
}
}
}
public void viderPanier() {
lesLignesPanier.Clear();
}
}
}
Le code de la page ASP.NET qui gère le panier comme sur la figure donnée plus haut est détaillé par le listing ci-après :
<%@ Page language="c#" Codebehind="GestionPanier.aspx.cs"
AutoEventWireup="false" Inherits="Addition.GestionPanier" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>GestionPanier</title>
</HEAD>
<body>
<form id="GestionPanier" method="post" runat="server">
<H1>Gestion du panier virtuel</H1>
<H3>Votre panier contient les produits suivants:</H3>
<P>
<asp:Repeater id="Repeater1" runat="server"
DataSource='<%# Session["panier"] %>'>
<HeaderTemplate>
<table border="1">
<TR>
<TD>Réf. Produit</TD>
<TD>Titre</TD>
<TD>Editeur</TD>
<TD>Quantité</TD>
<TD>Prix unitaire</TD>
<TD>Prix total</TD>
<TD>Modification</TD>
<TD>Suppression</TD>
</TR>
</HeaderTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
<ItemTemplate>
<TR>
<%-- Le client doit pouvoir modifier la
quantité aisément, dans le panier --%>
<FORM action="/controleur?cmd=modifierQuantité&produit=<%#
DataBinder.Eval(Container, "DataItem.Livre.Code")%>"
method="POST">
<TD><%# DataBinder.Eval(Container,
"DataItem.Livre.ISBN")%></TD>
<TD><%# DataBinder.Eval(Container,
"DataItem.Livre.Titre")%></TD>
<TD><%# DataBinder.Eval(Container,
"DataItem.Livre.Editeur")%></TD>
<TD>
<INPUT type="text" value="<%#
DataBinder.Eval(Container, "DataItem.Quantite")%>">
</TD>
<TD><%# DataBinder.Eval(Container,
"DataItem.PrixUnitaire")%></TD>
<TD><%# DataBinder.Eval(Container,
"DataItem.PrixTotal")%></TD>
<TD><INPUT type="submit" name="Modifier Quantité"></TD>
<%-- Le client doit pouvoir supprimer la ligne courante --%>
<TD><A href="/controleur?cmd=supprimerLigne&produit=<%#
DataBinder.Eval(Container, "DataItem.Livre.Code")%>">
Supprimer ligne</A></TD>
</FORM>
</TR>
</ItemTemplate>
</asp:Repeater></P>
</form>
<HR>
<%-- Le client doit pouvoir passer à la phase d'achat ou au devis--%>
<H3>
Souhaitez-vous <A href="/controleur?cmd=commander">passer commande</A> ?
<BR>
ou tout simplement
<A href="/controleur?cmd=demandeDevis">demander un devis gratuit</A>?
</H3>
<HR>
<%-- Le client doit pouvoir vider son panier d'un coup --%>
<H3>
Souhaitez-vous
<A href="/controleur?cmd=viderPanier">vider complètement votre panier</A> ?
</H3>
</body>
</HTML>
Nous avons mis en œuvre sur un exemple partiel de librairie en ligne le processus agile que nous préconisons pour la modélisation d’applications web.
A partir de cas d’utilisation UML et de modèles d’analyse du domaine, nous avons progressivement ajouté des informations de plus en plus proches des choix d’implémentation, en prenant comme cible la plateforme .NET. Nous avons pour cela utilisé principalement le diagramme de séquence UML, ainsi bien sûr que le diagramme de classes.
Nous avons ainsi montré qu’il est possible avec une démarche systématique mais simple d’aboutir de façon efficace à du code résultant des différents diagrammes UML précédents dans un environnement .NET et C#. Il est à noter qu’une grande partie du travail pourrait également servir à une implémentation sur une cible technique différente, telle qu’un environnement Java ou PHP, par exemple.
Vous trouverez toutes les explications détaillées concernant les diagrammes UML ainsi que la démarche dans l’ouvrage paru récemment aux éditions Eyrolles.
Premier article sur la démarche agile au service des applications web : http://dotnetguru.org/...
"UML2 - Modéliser une site application web", Pascal Roques, Eyrolles 2006 (dans la collection "Les Cahiers du Programmeur").
