ans 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 sites
Web marchands, 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), une approche minimaliste à la mode centrée sur le code.
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 paraîtra
prochainement chez Eyrolles, dans une nouvelle collection intitulée « Les
cahiers du Programmeur », sous le titre : « Modéliser un site
e-commerce ».
Merci aux éditions Eyrolles (www.eyrolles.com) de nous avoir
autorisés à publier des extraits du livre à paraître dans ces deux articles.
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
e-commerce. 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 Web 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 :
·
Rechercher des ouvrages,
·
Gérer son panier,
·
Effectuer une commande.
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.

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).
Préconditions : néant.
Scénario nominal :
1.
L’Internaute enregistre les
ouvrages qui l’intéressent dans un panier virtuel (voir le cas d’utilisation Rechercher
des ouvrages).
2.
L’Internaute demande l’accès
à son panier.
3.
Le Système lui affiche l’état
de son panier. Chaque ouvrage qui a été préalablement sélectionné est présenté
sur une ligne, avec son titre, son auteur et son numéro ISBN. Son prix unitaire
est affiché, la quantité est positionnée à « 1 » par défaut, et le
prix total de la ligne est calculé. Le total de la commande est calculé par le
Système et affiché en bas du panier avec l’indication des frais de port.
4.
L’Internaute valide son
panier en demandant à effectuer une commande.
Extensions
3-4a. Le panier est
vide
1.
Le système affiche un message
d’erreur à l’Internaute (« Votre panier est vide ! ») et lui
propose de revenir à une recherche d’ouvrage.
4a. L’Internaute
modifie les quantités des lignes du panier, ou en supprime.
1.
L’Internaute revalide le
panier en demandant le recalcul du total
2.
Le Système met à jour le
total calculé du panier et le cas d’utilisation reprend à l’étape 4 du scénario nominal.
4b. L’Internaute
effectue une nouvelle recherche d’ouvrage (voir le cas d’utilisation
correspondant).
Le cas d’utilisation reprend à l’étape 1 du scénario nominal.
Exigences
non-fonctionnelles
Le panier de l’internaute est sauvegardé pendant toute la
durée de sa visite sur le site Web.
Le diagramme de séquence système
d’un scénario représentatif est donné sur la figure suivante :

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 la 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 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) :
·
les « dialogues » qui
représentent les moyens d’interaction avec le système,
·
les « contrôles » qui
contiennent la logique applicative
·
et les « entités » qui sont
les objets métier manipulés.
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.
·
Les « entités » vont seulement
posséder des attributs. Ces attributs représentent en général
des informations persistantes de l’application.
·
Les « contrôles » vont seulement
posséder des opérations. Ces opérations montrent la logique de l’application, les règles
métier, les comportements du système informatique.
·
Les « dialogues » vont posséder des
attributs et des opérations. Les attributs vont représenter des champs de
saisie ou des résultats. Les résultats seront distingués en utilisant la
notation de l’attribut dérivé. Les opérations représenteront des actions de
l’utilisateur sur l’IHM.
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 sites Web marchands, 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’activités. Le diagramme d’activités 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’activités de navigation
concernant la gestion du panier est donné ci-dessous.

Remarquez comment nous avons ainsi représenté la règle métier
importante consistant à interdire l’accès à la commande dans le cas où le
panier est vide.
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
d’interactions UML (séquence ou collaboration). 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 d’interactions sont particulièrement utiles au concepteur pour
représenter graphiquement ses décisions d’allocation 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
collaborants. 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).

Pour illustration, le diagramme de collaboration correspondant est
également donné ci-après. Notez l’utilisation de la notation graphique UML
permettant de représenter une collection d’objets (multi-objets « les :
LignePanier »), ainsi que la numérotation décimale des messages
indiquant leur imbrication.

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 du domaine et des classes participantes, nous allons affiner
et compléter le diagramme de classes. Pour cela nous utiliserons les diagrammes
d’interactions que nous venons de réaliser pour :
·
Ajouter ou préciser les opérations dans les classes
(un message ne peut être reçu par un objet que si sa classe a déclaré
l’opération publique correspondante).
·
Ajouter des types aux attributs et aux paramètres et retours des opérations.
·
Affiner les relations entre classes :
associations (avec indication de navigabilité), généralisations ou dépendances.
Que
pouvons nous ajouter au diagramme de classes participantes d’analyse de notre
cas d’utilisation ?
·
Tout d’abord, nous avons détecté deux dialogues
supplémentaires : l’un correspondant à l’erreur « Panier vide »,
l’autre permettant d’afficher le devis pour impression par l’internaute.
·
Ensuite les diagrammes d’interaction nous amènent à
ajouter un certain nombre d’opérations aux classes existantes, par exemple ajouterLigne(id)
à ControlPanier et à l’entité Panier. Nous avons vu que le
dialogue ResultatRecherche peut appeler ControlPanier comme
d’ailleurs tous les dialogues qui possèdent le bouton « Mettre dans le
panier » associé à au moins une référence d’ouvrage. Le contrôle passe
toujours par le panier et n’accède pas directement aux lignes.
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 :
·
Le « dialogue » est réalisé par les pages ASP.NET
: l'idée est également
d'insérer des instructions de script dans des pages HTML (le langage peut être
C# ou VB.NET). Les pages ASP.NET peuvent contenir des WebForms, espèces
de TagLibs qui génèrent des vues en HTML et qui permettent également de
placer des contraintes (composant validators) sur les champs de saisie
utilisateur. Ces contraintes sont vérifiées côté serveur par défaut, mais un
module JavaScript permet de pré-valider le tout côté client à condition
d'utiliser InternetExplorer.
·
le « contrôle » est implémenté soit par des
classes associées aux ASP.NET (classes CodeBehind), soit par des
classes supplémentaires déployées dans l’application web (dans le "moteur
d'ASP" : IIS).
·
les « entités » sont représentées par des classes
de l’application web, ou par des Serviced Components (que l'on
installe dans le serveur d'applications MTS).
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) :
·
affichage de la liste des lignes ;
·
pour chaque ligne, possibilité de modifier la quantité ou
de supprimer la ligne ;
·
possibilité à la fin de vider le panier, ou de demander un
devis / passer une commande.

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 d’interactions, 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.total;
}
}
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 de sites e-commerce.
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 les diagrammes d’interactions UML (séquence et collaboration),
ainsi bien sûr que les diagrammes 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 avec Struts, par exemple.
Vous
trouverez toutes les explications détaillées concernant les diagrammes UML
ainsi que la démarche dans l’ouvrage à paraître aux éditions Eyrolles.
Auteur : Pascal Roques
Copyright :
Juin 2002 - DotNetGuru ©
Ressources
« Modéliser
un site e-commerce », Pascal Roques, Eyrolles 2002 (à paraître en Septembre
dans la nouvelle collection « Les cahiers du programmeur »).
http://www.dotnetguru.org
(Premier article sur la démarche agile au service du e-business)