Optimistic UI

Quand j'ai testé Meteor, j'ai découvert un concept que je ne connaissais pas : l'Optimistic UI. C'est le meilleur truc que j'ai pu extraire de cette expérience et j'ai décidé de l'appliquer autant que possible. Mais de quoi s'agit-il ?

UI classique


UI Classique 2015-10-08 12:01Zicon_512x512Layer 1Action utilisateurRequête vers le serveurRéponse du serveurModification de l’interfaceAffichage d’un message d’erreurOK 200ERROR 500

Voici comment sont conçues la très grande majorité des applications, qu'elles soit web ou pas. Un utilisateur fait une action, il clique sur un bouton par exemple. Une requête est alors envoyée au serveur. En attendant que le serveur réponde, l'UI ne change pas, ou au mieux, si le développeur a estimé que la requête serait trop longue, elle affiche un élément graphique de chargement. Puis, une fois que la requête a abouti, l'interface change.
Cette implémentation a le mérite d'être certaine d'être synchro avec le serveur. Les données de l'interface afficheront toujours exactement la même chose que ce qu'on a dans la base de données. L'inconvénient, c'est que l'utilisateur doit attendre après avoir fait son action, et l'utilisateur n'aime pas attendre.

Alors on peut installer de plus gros serveurs pour accélérer les requêtes, optimiser le code au maximum… ou opter pour une autre implémentation.

Optimistic UI


Optimistic UI 2015-10-08 12:01Zicon_512x512 2Layer 1Action utilisateurRequête vers le serveurRéponse du serveurModification de l’interfaceAnnulation de la modification de l’interfaceERROR 500

L'interface optimiste n'attend pas le retour du serveur et part du principe que tout fonctionne à merveille par défaut. Ici, notre utilisateur va donc faire son action, et immédiatement, l'interface va refléter le résultat de l'action comme si elle avait été effectuée avec succès. L'utilisateur peut continuer à faire d'autres actions pendant que le serveur renvoie sa réponse. Si la réponse est effectivement bonne, alors on ne fait rien de plus. Si elle est mauvaise, on remet l'interface en place et on affiche un message d'erreur à l'utilisateur.

Cette implémentation permet d'avoir une interface extrêmement réactive, l'utilisateur peut enchainer ses actions sans attendre et sans frustration. Par contre, il faut bien faire attention à correctement implémenter cette interface et ne pas non plus l'utiliser à mauvais escient. Par exemple, certaines requêtes ont besoin de connaitre la réponse du serveur pour modifier son interface. On peut déduire la réponse coté client, mais le plus souvent, cela consiste à dupliquer la logique métier des deux cotés. Mais pour des actions simples qui ne retournent pas de données modifiées, il n'y a aucune raison de se priver. Il faut aussi que le serveur assure et renvoie le moins d'erreurs possible sous peine de rendre l'utilisateur confus à force de trop nombreuses modifications de l'interface.

Exemples

Voici une liste d'éléments qui ont chacun un bouton pour les supprimer. Lors de la suppression, je simule un backend très lent (2 secondes) et qui renvoie une erreur une fois sur 2.

Ce premier exemple est implémenté de façon classique : lorsqu'on clique sur le bouton de suppression, on affiche une roue de chargement et on attend la réponse. Quand la réponse arrive, on modifie l'interface.

Ce second exemple est optimiste : l'élément est supprimé immédiatement quand on clique sur le bouton d'action. En cas d'erreur, il est remis dans la liste et une erreur est affichée.

Hadrien

Hi, I'm a french Javascript Lead Developer, Web Architect from Toulouse, France. I've worked for 12 years for many projects with YUI, AngularJS, Aurelia.io and now React and React native.

Toulouse, France https://hadrien.eu