« User » n'est pas un Bounded Context — et pourtant, l'utilisateur compte

« User » n’est pas un Bounded Context — c’est le premier réflexe à corriger en formation DDD. Trop vague, trop tentant de tout y mettre. Et pourtant : nulle architecture ne saurait ignorer ses utilisateurs. La modularisation doit bien se réconcilier avec l’expérience. Voici un pattern qui tente de répondre à cette tension.
Un contexte de présentation par persona
Partons du problème : la modularisation, c’est bien, mais comme le soulignent Mathias Verraes et Rebecca Wirfs-Brock, c’est une démarche qui relève de l’espace des solutions. Autrement dit, vos utilisateurs n’en ont rien à faire. Pas plus que de vos user stories, si vous y réfléchissez bien. Pour eux, la seule chose qui compte, c’est une application utile et facile à utiliser.
Cela suppose que l’utilisateur dispose d’une interface unique lui permettant de tout faire et de passer de manière transparente d’un contexte à l’autre. Si j’achète un produit et que je souhaite la facture correspondante, il serait aberrant de devoir me connecter à une application dédiée à la facturation, car le flux de travail serait interrompu. Pourtant, en termes d’API, il est certain qu’il y aura une API dédiée à la facturation.
Cela dit bien la nécessité d’un contexte destiné à présenter l’information à chaque profil utilisateur, à chaque persona. Il présente de l’information en provenance des core contexts et possède son propre langage. Par exemple, le langage d’un front-office sera généralement un langage simplifié, intelligible au plus grand nombre, tandis que celui du back-office restera un langage spécialisé, parlé par les experts du métier. L’architecture de l’information sera probablement elle aussi très différente entre ces deux contextes.
On imagine assez bien ce que cela pourrait donner dans un service que nous connaissons tous, Doctolib : on voit d’ici les contextes « Professionnel de santé » et « Patient », points d’entrées uniques vers d’autres contextes tels que « Prise de rendez-vous », « Consultation en ligne » etc.
À chaque contexte son BFF
BFF… pour Best Friend Forever ? Pas vraiment.
Dans le cas d’une Single Page Application (SPA), appeler plusieurs APIs depuis le navigateur n’est pas idéal, pour des raisons de sécurité en premier lieu. Aussi on décide de mettre à disposition du front-end une API dédiée, à laquelle on délègue ce travail. Cela s’appelle un Backend For Frontend (BFF). Comme souvent, tout est dans le titre, mais voyons tout de même ce que cela signifie :
-
Un BFF offre à la SPA un point d’entrée unique pour des requêtes orientées écrans. Exemple : donne-moi l’historique de mes commandes avec pour chaque commande un lien vers la facture correspondante, si elle existe. Des informations en provenance de 2 contextes, donc 2 APIs, compilées en 1 seule réponse.
-
Un BFF permet de mutualiser l’authentification : dans un flux OAuth2, le BFF valide le jeton JWT et le transmet aux services avec lesquels il interagit (token forwarding) ou bien demande à l’identity provider l’émission d’un token technique « on-behalf-of » (token exchange/delegation).
Un BFF est donc essentiellement un proxy : il facilite l’interaction en lecture et en écriture avec les autres contextes, qui ignorent tout de l’utilisateur (ils ne connaissent que son rôle, porté par le token). L’ensemble SPA + BFF constitue le contexte utilisateur, et il y en a autant que de persona.
Un contexte de présentation dédié à une catégorie d’utilisateurs est une façon de prendre en compte l’utilisateur, alors qu’une démarche de modularisation pourrait avoir tendance à l’oublier. Un contexte de présentation n’est donc pas un contexte « utilisateur ». Quand le premier est un pattern valide en DDD, le second, synonyme de couplage à grande échelle, reste un anti-pattern absolu.