Cet article est la transcription d’une intervention donnée à ParisJS en octobre 2015, sur les liens entre la complexité métier et l’expérience utilisateur.
Aujourd’hui je voudrais vous parler de « comment gérer la complexité métier ». J’ai appelé ça « Happy Path et Sad Path », mais ça veut juste dire « Le chemin où tout se passe bien, et celui où on butte dans tous les cas spéciaux », et où on doit vraiment gérer la complexité.
Au début on présentait Captain Train en disant « c’est un site pour acheter ses billets de train, super rapidement ». Historiquement il a été conçu comme une alternative au site de l’opérateur historique : plus rapide, plus simple.
Aujourd’hui l’ambition est plus large : Captain Train vend des billets dans toute l’Europe. Mais on a toujours cette attention à la simplicité et à la rapidité.
La question est : comment conserver cette rapidité malgré la complexité ?
Je ne vais pas parler de performances chiffrées, mais plutôt de l’impression de simplicité. La frontière entre « rapide » et « simple » est très floue – et souvent, quand une tâche est simple, qu’on n’a pas le cerveau encombré de plein de choses, on va plus vite pour faire cette tâche. Et on en garde un meilleur souvenir.
Happy Path
Sur Captain Train, le Happy Path (celui où tout se passe bien pour l’utilisateur) est très rapide. Une dizaine de clics tout au plus pour acheter un billet de train.
En pratique ça se fait en cinq écrans (en comptant large) :
1 - La recherche
2 - La réservation
3 - Le panier
4 - Le paiement
5 - Le billet
Ça a l’air simple.
Sad Path
Mais tout ne se passe pas toujours aussi bien. Il y a des erreurs, des avertissements, des problèmes, de la complexité métier. C’est le cas dans tous les domaines que vous pouvez rencontrer : le train, la presse, la restauration, l’astronomie, la chirurgie, tous les domaines.
Pour continuer sur l’exemple du train, on va faire un tour de tout ce à quoi vous échappez la plupart du temps, mais qui peut arriver.
Pour commencer, au moment de la réservation, il y a beaucoup de choses qui peuvent se passer.
Par exemple, parfois le train ne part pas de la gare que vous avez demandée.
(Ou il n’arrive pas à la gare demandée, c’est possible aussi.)
Dans ce cas on vous prévient, quand même.
Jusqu’ici, c’est d’une complexité raisonnable.
Cette fois-ci vous décidez de prendre un train OUIGO (vous savez, les TGV low-cost). À bord des OUIGO, les bagages sont payants. Une cause fréquente de réclamations est que l’utilisateur monte dans le train avec trop de bagages.
Si vous n’avez pas sélectionné de bagages, on vous rapelle que vous ne pourrez avoir qu’un bagage « cabine ».
Pour faire une réservation, OUIGO requiert absolument la date de naissance des voyageurs.
Donc au moment où vous voulez réserver, si on n’a pas votre date de naissance, on vous la demande (et on s’en souvient pour les prochaines fois).
OUIGO requiert également le numéro de téléphone. Pareil, si on ne l’a pas on le demande, et on s’en souvient pour les prochaines fois.
J’ai séparé les dialogues pour la démo, mais en vrai si on a besoin de toutes ces informations en même temps, on va même compacter le processus, et les demander en une seule fois dans le même dialogue.
Et ça y est, c’est bon, on peut réserver.
Autre possibilité : vous réservez un train allemand, ou italien. Ça se passe encore un peu différemment. Les trains allemands et italiens demandent des documents d’identification, pour justifier de votre identité à bord du train, en plus du billet.
Donc avant de réserver, on vous demande si vous voulez utiliser votre carte bancaire pour vous identifier, ou votre carte d’identité.
Oh, et la Deutsche Bahn demande une adresse, aussi. Pareil, si on ne l’a pas, on la demande et on s’en souvient pour les prochaines fois.
Ah, et si vous choisissez de présenter votre carte d’identité, la DB demande le numéro de la carte. Et l’adresse indiquée sur la carte d’identité, aussi. Pareil, on la demande, on s’en souvient pour les prochaines fois.
On arrive enfin au Panier, juste avant le paiement. Là encore il peut se passer des choses.
Par exemple vous cliquez sur « Payer », mais vous avez déjà acheté un billet identique. C’est à dire un billet pour le même trajet, le même jour, avec les mêmes personnes qui voyagent.
On est sympa, on prévient, et on vérifie que c’est bien ça que vous voulez, quand même.
Autre problème qui peut arriver : vous allez payer deux fois le même billet.
Ça a l’air bête, mais ça peut arriver quand on fait une recherche, puis qu’on revient plus tard, on en fait une autre, on paye – et paf le billet de la recherche précédente était en fait là aussi.
Pareil, on vous demande de vérifier.
Si vous persistez, vous arrivez enfin au paiement.
Normalement ça se passe bien. Mais si votre banque nous demande de vous authentifier plus sérieusement, vous allez voir le décevant dialogue de confirmation 3D-Secure, celui qui vous envoie un SMS sur votre téléphone mobile.
Il y a pas mal d’abandons d’achat à cet étape, parce qu’il y a beaucoup de possibilités que ça ne fonctionne pas, d’une manière ou d’une autre. Ce dialogue joue donc sur plusieurs choses :
- Rester dans le contexte de l’application (pas de popup ou d’iframe plein écran),
- Afficher un message un peu léger pour dédramatiser,
- Indiquer qui est probablement à blâmer en cas d’erreur bizarre (c’est souvent votre banque),
- Afficher ce dialogue le moins souvent possible (si on a vraiment confiance dans votre paiement, on vous épargne le 3D-Secure).
Ça y est, le paiement s’est bien passé. Vous avez votre billet.
Enfin presque. À ce stade, votre billet est payé, mais pas encore émis. On prétend que vous l’avez déjà, mais ce n’est pas complètement vrai, c’est « en cours ».
Par exemple, si on a vraiment des doutes sur votre paiement, malgré le 3D-Secure, on va jeter un œil manuellement, quand même, avant de vous générer un billet qui vaut de l’argent. Ça nous permet de lutter contre la fraude.
En tout cas on vous informe de ce qui se passe, et de combien de temps ça va prendre.
Une fois qu’on est raisonnablement confiant dans votre paiement, l’émission est lancée.
Normalement ça prend moins d’une minute – mais parfois les systèmes de réservation de la SNCF ou de la DB ont des hoquets, et il faut attendre quelques heures que ça revienne.
Alors pareil, on indique ce qui se passe.
On a réussi à émettre votre billet, mais catastrophe, le serveur qui permet de récupérer les e-billets en PDF est en rade.
Allez, on vous informe, quand même.
Ça y est, on a enfin récupéré votre e-billet en PDF.
Enfin vos billets : ici il y a deux passagers, et ce transporteur génère un PDF par passager. Donc deux PDF. Mais ça dépend.
Et puis parfois le mode de retrait est différent. Par exemple si vous prenez un train TER, le e-billet n’est souvent pas disponible. Dans ce cas il faut retirer un billet cartonné à une borne en gare.
C’est inhabituel, donc on a intérêt à l’indiquer clairement.
Tout ça dans un message d’une seule ligne. Pour info, il y a plus d’un millier de combinaisons différentes de ce message. Ça dépend :
- du transporteur (SNCF, ou Thalys, Trenitalia, DB…)
- du mode d’émission du billet (e-billet ou cartonné)
- du programme de fidélité (carte Grand Voyageur, ou autre…)
- de l’application (application web, ou mobile, ou email)
Contraintes métier
Toutes ces problématiques sont liées au train : ce sont nos contraintes métiers. Mais tout le monde a ses propres contraintes métier (même si ce n’est pas le métier du train).
Comment gérer la complexité qui vient des contraintes métier d’une manière générale ? Comment éviter de tout complexifier juste à cause de quelques contraintes métier ?
Déterminer ce qu’on voudrait faire est plutôt facile :
- Collecter les informations progressivement (mais oui !),
- Prévenir les confusions fréquentes (bien sûr),
- Informer en cas d’erreur (évidemment).
Ce sont des choses plutôt évidentes, nous voulons tous ça.
Éviter l’effet sapin-de-Noël
Mais si on n’y prend pas garde, on répond à des besoin évidents par des solutions évidentes : pour chaque confusion possible, rajouter un avertissement ; pour chaque cas spécial, rajouter un « if » dans le code.
Par exemple sur Captain Train on aurait pu mettre des dialogues systématiques pour :
- Définir les documents d’identification,
- Récapituler la commande avant le paiement,
- Attendre l’émission (avec un petit indicateur de chargement et tout).
Mais ça détériore l’expérience utilisateur, et ça rend le code de moins en moins maintenable.
Garder simple ce qui est simple
Ce qu’on veut vraiment, ce ne sont pas les solutions naïves, c’est garder simple ce qui est simple – et gérer au cas-par-cas quand ça se complique.
-
Partir du cas optimiste : imaginer comment les choses devraient être dans le cas le plus simple – et éviter de ralonger ce chemin.
-
Rajouter des étapes seulement quand c’est nécessaire : avoir une grande granularité sur les informations demandées, demander seulement les informations manquantes, s’en souvenir.
-
Contextualiser les messages d’avertissement et d’erreur.
Pour rebondir sur ce dernier point, on essaie de résister à la tentation d’avoir des messages d’erreurs génériques, comme par exemple :
« Ce train ne part pas de la gare demandée. » 😕
À la place on utilise toutes les informations du contexte pour afficher un message pertinent : quelle était la gare demandée initialement, quelle est celle finalement remontée, et est-ce que c’est tout près ou vraiment loin :
« Ce train ne part pas de Paris, mais de Massy-Palaiseau, à 30km de Paris. » 😌
Autre exemple :
« Pour faire cette opération, contactez votre administrateur. » 😕
Allons bon, qui est mon « administrateur », déjà ? Et si j’arrive à le joindre, je lui demande d’effectuer quelle opération ?
« Pour ajouter un passager, contactez Delphine ou Jean-Luc. » 😌
Certains messages d’avertissement ou d’erreur sont générés à partir de 5 ou 10 bouts de phrases, et 50 lignes de code. Pour un seul message. C’est du travail, mais ça en vaut la peine.
Des promesses, toujours des promesses
Il y a quelques patterns qu’on utilise régulièrement pour améliorer l’expérience utilisateur :
- Chaîner les dialogues avec des promesses,
- Tester les erreurs en priorité,
- Faire des tests utilisateurs.
Le premier pattern concerne le code. Une des manières de ne pas avoir à rajouter des « if » à chaque cas spécial est d’encapsuler les séquences de plusieurs dialogues dans des promesses.
Par exemple, quand on clique sur le bouton « Ajouter au Panier », on construit cette chaîne de promesses :
function addToCartClicked() {
return luggagesDialog.prompt().then(() => {
return birthdateDialog.prompt();
}).then(() => {
return identificationDialog.prompt();
}).then(() => {
return book();
});
}
Si le dialogue n’a pas besoin d’être affiché, la promesse est résolue immédiatement, et on passe au dialogue suivant.
Par contre, s’il est nécessaire d’afficher un dialogue, la promesse sera résolue seulement au moment où l’utilisateur cliquera sur “OK”. Et si à une étape l’utilisateur clique sur “Annuler”, la promesse est rejetée, et toute les étapes suivantes sont court-circuitées.
Un autre exemple, quand on clique sur le bouton « Payer » :
function payButtonClicked() {
return similarTicketDialog.prompt().then(() => {
return duplicateTicketDialog.prompt();
}).then(() => {
return invalidCouponDialog.prompt();
}).then(() => {
return payDialog.prompt();
});
}
Ça correspond exactement à notre cas d’usage : rajouter des dialogues optionnels sur le chemin, tout en maintenant le code lisible.
Tester les cas d’erreur en priorité
Les messages d’erreur sont les premiers à souffrir quand on refactore, ou que l’API change, etc.
Le Happy Path est le plus fréquent, il est utilisé en permanence : s’il casse, ça se verra forcément. Les cas d’erreurs, c’est plus compliqué. Finalement, pour les tests d’intégrations il vaut mieux tester les cas d’erreur en priorité. On n’est pas encore très bon élèves là dessus, mais on essaie.
visit('/pay');
click('Payer');
andThen(function() {
assert.present('Le paiement a été refusé');
});
Tests utilisateurs
Les tests utlisateurs nous ont permis de clarifier certains éléments de l’interface. Parce que épurer, c’est bien, mais parfois on a besoin de rendre les choses plus évidentes, au contraire.
Par exemple il a fallu qu’on aille dans un café faire des tests utilisateurs pour voir que les gens avaient du mal à trouver comment ajouter des passagers, ou comment ajouter une carte de réduction.
Alors on a rendu ça plus clair, sur le fond et sur la forme. D’abord en signalant un peu mieux l’ajout de passagers, avec un bouton « + », purement visuel, qui n’apporte rien fonctionnellement, si ce n’est un signal « Pour ajouter, c’est par ici. »
Ensuite en signalant mieux la possibilité d’ajouter des cartes de réductions.
Pour résumer ce qui peut vous être utile :
-
Maitrisez vos contraintes métiers : ça permet de simplifier le cas le plus fréquent, et de demander des opérations supplémentaires au moment où vous en avez vraiment besoin.
-
Une interface simple aura l’air rapide à l’utilisation, parce qu’elle diminue la charge cognitive. (Et pour moi c’est orthogonal aux performances brutes.)
Merci.
Le Projet de loi sur la Surveillance est aujourd’hui examiné par la commission des lois,
et par l’Assemblée Nationale dans deux semaines. C’est donc pile le moment de dire à votre député·e ou votre sénateur·rice tout le bien que vous pensez de ce projet de loi.
Vous pouvez trouver le contact de vos représentants parlementaires à partir de votre code
postal sur nosdeputes.fr et
nossenateurs.fr. Et je vous met aussi en dessous une copie de ce que j’ai envoyé à ma députée. N’hésitez pas à reprendre ce texte si ça peut vous être utile.
Madame la députée,
Le projet de Loi relatif au Renseignement, aujourd’hui en cours d’examen en commission des lois, est inscrit à l’ordre du jour de l’Assemblée Nationale à partir du 13 avril.
Comme vous le savez, l’objectif de projet de loi est de légaliser un certain nombre de pratiques des services de Renseignement. Ces services effectuent depuis plusieurs années des opérations de surveillance, collectes d’informations, mises sur écoute, etc. illégalement et sans contrôle de l’autorité judiciaire.
Ce projet de loi est dénoncé par les membres de la société civile. Citons par exemple :
- l’ARCEP (Autorité de Régulation des Communications Électroniques et des Postes)
- le Conseil National du Numérique
- la CNIL
- le Conseil de l’Europe
- Amnesty International
- la Ligue des Droits de l’Homme
- Reporters sans Frontières
- l’Union Syndicate des Magistrats
Parmi les personnes ayant exprimé une opposition, on trouve également :
-
Marc Trédicic, juge anti-terroriste
(qui parle d’un projet de loi donnant « des pouvoirs exorbitants » aux services de renseignement)
-
Alain Marsaud, ancien juge anti-terroriste
(qui considère qu’« avec un tel texte, toutes les oppositions, même politiques, peuvent être surveillées. »)
Ce projet de loi contient également des dispositions illégale au regard du droit international — comme le souligne le Haut-Commissariat aux Droits de l’Homme des Nations Unies.
En tant que citoyen, ce qui m’inquiète le plus est l’aspect généralisé de cette surveillance. Il ne s’agit pas de surveiller quelques personnes suspectes. Ce projet de loi permettrait de mettre « sur écoute » non seulement l’ensemble d’un groupe (parti politique, association, syndicat) mais également l’ensemble de la population française (via l’analyse des données transitant sur Internet).
Cette surveillance pourrait se faire sans contrôle de l’autorité judiciaire. Seule la justice est garante du droit — et dans le cadre de ce projet de loi aucun magistrat n’aurait de contrôle sur la légitimité des écoutes.
Voulons-nous d’une société où, chaque fois que nous composons un numéro de téléphone ou que nous ouvrons un navigateur web, une petite voix nous rappelle que ce que nous allons faire est surveillé et pourra être retenu contre nous ?
Aujourd’hui, ce projet loi n’offre pas les garanties nécessaires au maintien d’un état de droit plutôt que d’une société de surveillance. Je vous demande, Madame la députée, de soutenir les amendements assurant le contrôle des services de renseignement par l’autorité judiciaire et de rejeter les dispositions visant à une surveillance généralisée (plutôt que ciblée sur les personnes suspectées).
Pour en savoir plus, je vous invite à consulter les analyses rédigées par l’association La Quadrature du Net, disponibles ici : https://wiki.laquadrature.net/PJL_relatif_au_renseignement
Je vous priée d’agréer, Madame la députée, l’expression de ma considération distinguée,
<Signature>
Amis lecteurs du flux RSS de ce blog, si tout se passe bien, vous n’avez rien remarqué.
Mais si vous accéder à ces pages via le Web, il y a quelques changements visibles, et une
nouvelle tête pour ce vieux blog.
Jusqu’ici, les articles étaient servis par un Dotclear version 1 datant de 2006.
La grande époque, celle où Dotclear se différentiait de Wordpress et de SPIP par son
interface d’administration accessible via /ecrire/
, et où les forums pestaient contre
les extensions PHP5 nécessaires pour installer Dotclear 2 et manquantes chez OVH.
2006, ça fait un bail. Dotclear 1 a courageusement tenu la durée jusque ici, mais je savais
qu’un jour il faudrait prendre le temps de passer à quelque chose de plus pérenne. Et enfin
la grande migration a eu lieu, vers le truc à la mode du moment, jekyll
. Juste une liste
de fichiers texte et des pages statiques ; sans PHP, sans commentaires. Simple, transportable.
Attends, je t’ai perdu, là. Un blog ?
Aujourd’hui Twitter est plus efficace que jamais pour partager de l’information ou son
humeur du moment, et Instagram bien plus efficate pour poster ses photos de chats. Et les
commentaires comme espace de discussion ont montrés leur limites.
Alors, pourquoi prendre le temps de maintenir un blog en 2015 ?
Principalement parce qu’il me semble important d’avoir sous la main un espace d’expression public qui
ne dépende pas d’un medium privé. Dans quelques années, lorsque les réseaux sociaux à la mode
auront été remplacés par d’autres, cet espace sera toujours là. Je n’ai pas à craindre que
les textes ou les images que je publie contreviennent aux Conditions d’Utilisation d’une
plateforme de publication. Plus pérenne, plus libre, pas de question à me poser, pas
d’autocensure.
D’autre part, si l’information se diffuse très bien sur Twitter, elle a souvent pour source
un article, un reportage, un texte plus long hébergé quelque part. Et j’ai envie d’investir
ces espace où on peut commenter un article en plus de 140 caractères, ou écrire des bouts de
réflexion plus cotonneuses.
Où me trouver
Alors voilà, je vais continuer à poster irrégulièrement ici des
bouts d’idées ; ça parlera de ce qui importe dans ma vie. De technique, bien sûr, mais
aussi d’événements, de projets, de réflexions diverses.
Je suis donc ici : vous pouvez jeter de temps en temps un œil à ce site, ou vous abonner
au flux RSS.
Il y a également une liste d’articles partagés que j’alimente fréquemment ; c’est accessible
sur Delicious ; vous pouvez également vous abonner au flux RSS de cette liste.
Et enfin vous me trouverez aussi en train de discutailler sur
Twitter, ou de pousser du code sur
GitHub.