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
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
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.