Impedance Mismatch : pourquoi votre modélisation legacy tue votre expérience omnicanale et API

Mettez vous à la place de Martin. Martin est dans le tram, smartphone en main. Il veut changer d'assurance habitation. Il commence le parcours sur votre nouvelle application mobile, entre son adresse, choisit une formule... puis s'arrête. Il ne connaît pas l’année exacte de la construction de celle-ci, et hélas c’est une donnée obligatoire pour finaliser le devis.

Dans un monde idéal, Martin sauvegarde et reprend ce soir sur son ordinateur portable, ou appelle le service client pour qu'un agent finisse avec lui dans la plus pure logique cross-canal.

Dans la réalité de beaucoup d'entreprises, Martin est bloqué. Pourquoi ? Parce que votre système Legacy (typiquement un backend en Cobol/Oracle ou PacBase/DB2), gardien du temple, refuse d'enregistrer un contrat si le champ ANNEE_CONSTRUCTION est vide. Le premier réflexe de vos développeurs et développeuses pour palier le problème pourrait être de renseigner un 0 ou un -1 en base, polluant ainsi votre qualité de données pour toujours ou compromettant une logique sous-jacente dont ils ou elles n'auraient hélas pas connaissance.

Ce problème a un nom : l'Impedance Mismatch. A l’instar de l’électricité ou de la biologie, il exprime la résistance d’un modèle orienté objet ou domaine à rentrer dans un modèle relationnel. Il matérialise la difficulté d’aligner la fluidité d'un processus conversationnel (le Digital) et la rigueur transactionnelle d'un système d'enregistrement (le Legacy).

La solution n'est pas de tordre le Legacy, ni de faire des "hacks" en front. Une des solutions est plutôt architecturale : c'est la Réification du Processus.

Le Piège du Modèle Canonique

L'erreur fondamentale est de vouloir exposer votre modèle de données interne universel (le modèle canonique) directement au monde extérieur.

Le propre des processus digitaux est d’être simple, cantonné, situationnel ! Dans le contexte agence physique historique, un assureur demanderait à Martin s’il est déjà sociétaire et vient pour un sinistre (le contexte de gestion) ou s'il vient pour s'équiper. Le conseiller interrogerait donc son futur client sur la nature du produit ou service auquel Martin souhaite souscrire : une assurance vie (un produit d’épargne) ou une assurance IARD, par exemple multirisques habitation (MRH). Il pourrait ensuite apporter des nuances, ou questionner : assurance auto, moto, bateau, habitation ? Particulier ou professionnel ? Quelle est la valeur des biens et quelle est la franchise acceptable ?
Le système du conseiller en assurance a été pensé pour tous ces usages en même temps, et tant mieux. Mais ici le contexte de l’usager – un prospect web – est bien plus simple, voire volontairement restreint au cas d’usage le plus courant : la souscription d'une assurance habitation classique.

D’une manière plus générale, c’est la source de ce problème d'Impedance Mismatch. La modélisation des années 1990 - 2010, guidée par la SOA et une farouche volonté de mutualisation nous enjoignait de faire abstraction de l’usage, d’être agnostique du contexte, d'être complet et générique … bref canonique ! Les architectures plus modernes et les philosophies de modélisation telles que Domain-Driven Design (DDD) sont différentes sur ce point : l’usage et le contexte sont rois. Le même mot revêt différentes significations dans des contextes différents et donc une modélisation différente car il porte intrinsèquement des contraintes différentes.

Donc, si votre API comprend un endpoint ressemblant à POST /contrats et attend un JSON de 200 lignes parfaitement valide respectant toutes les contraintes d'intégrité de votre base Oracle, vous créez un couplage fort avec une complexité inutile pour ce cas d’usage. Vous demandez à l'utilisateur de faire le travail de validation à la place du système. Au passage, vous interdisez ainsi toute sauvegarde d'étape intermédiaire d’un brouillon de souscription ou une intention de demande de devis.

Comme le souligne Eric Evans, vous essayez de forcer un modèle unique pour deux Bounded Contexts (Contextes Bornés) radicalement différents :

  1. Le Contexte d'Acquisition (vente): Besoin de souplesse, d'états partiels ;
  2. Le Contexte de Gestion (réglementaire) : Besoin de rigueur, d'ACIDité.

La Solution : la Ressource "Souscription"

Pour résoudre cela, nous devons appliquer le principe de Réification : transformer un concept abstrait (le fait de souscrire) en une ressource tangible manipulable via une API.

Au lieu de manipuler un Contrat (le but final), nous allons manipuler une intention, la Souscription (le chemin pour y arriver).

Ossature de la ressource composite

Entrons dans le détail. Plutôt que d'envoyer un énorme JSON représentant peu ou proue l’intégralité de schéma de base de données, une approche moderne et élégante - RESTful, niveau 2 ou 3 - consiste à éclater cette ressource Souscription en sous-ressources fonctionnelles, par l’exemple l’état civil, le bien à assurer et les services annexes. Cela permet une granularité fine dans la mise à jour et la validation. Notons au passage que le simple fait de demander à Martin notre prospect, ses coordonnées, nous permet de le recontacter ultérieurement même s’il ne termine pas sa démarche.

Imaginons que cette ressource soit stockée sur un modèle NoSQL (Document Store) pour absorber la variabilité du schéma sans migration de base de données à chaque nouvelle offre commerciale.

Voici à quoi ressemble la conversation entre le Front (Digital) et le Back (BFF/Process API).

1. Initialisation de l'intention

Le processus démarre, on ne crée pas de données métier, juste un conteneur.

POST /api/v1/souscriptions
{
  "id": "sub_88a9-f4e2",
  "status": "BROUILLON",
  "links": {
    "civil": "/api/v1/souscriptions/sub_88a9/etat-civil",
    "bien": "/api/v1/souscriptions/sub_88a9/bien-assure",
    "services": "/api/v1/souscriptions/sub_88a9/services"
  }
}
Response : 201 Created

2. Enrichissement progressif (L'étape du bien)

C'est ici que la magie opère. Martin indique qu'il vit à Bordeaux. Il ignore l'année de construction ? Peu importe. Le modèle Document accepte l'absence de champ ou des valeurs partielles.

PUT /api/v1/souscriptions/sub_88a9/bien-assure
{
  "type": "APPARTEMENT",
  "adresse": {
    "ville": "Bordeaux",
    "code_postal": "33000"
  },
  // L'année de construction est manquante, le backend l'accepte
  "annee_construction": null 
}
Response : 201 Created

Côté Backend : La donnée est persistée telle quelle dans le stockage temporaire. Aucune règle bloquante du Legacy n'est invoquée.

3. Omnicanalité et Reprise Agent

Martin est donc rentré chez lui.

Situation N°1 : il consulte ses dossiers et finalise lui-même la démarche sans avoir à tout ressaisir, car vous avez su juguler le frein psychologique de “fatigue décisionnelle”, à savoir refaire le choix des options, en lui garantissant la bonne expérience. Taux d'acquisition, +1 !

Situation n°2 : il appelle le service client, si ce n’est pas l’inverse. Le conseiller accède au dossier via son Backoffice. Martin est content, il n’a pas à tout ré-expliquer limitant un autre biais cognitif, l’aversion à la perte. Ce parcours sans couture contribue indéniablement à son expérience client. 

D’un point de vue technique, l’application de l'agent fait un simple GET /api/v1/souscriptions/sub_88a9/bien-assure et lui permet de voir les données saisies. Il demande l'année de construction, la saisit et le système met à jour la sous-ressource. Le contexte est partagé en temps réel.

4. Validation Contextuelle ("Dry Run")

Dans la situation n°1 ou notre protagoniste tente de souscrire lui-même depuis son canapé aux alentours de 00h30, comment le système peut-il savoir si le dossier est complet sans essayer de le créer dans le Legacy, fermé au transactionnel pour laisser les fameux “batchs de nuit” tourner ? C’est simple : on sollicite une vérification dans ce nouveau contexte, qui renverra une ressource de validation dédiée. C'est l'approche prônée par les architectures Task-Based UI.

POST /api/v1/souscriptions/sub_88a9/valider
HTTP/1.1 422 (Unprocessable Entity)
Content-Type: application/problem+json
{
 "type": "https://api.mamutuelle.fr/probs/validation-error",
 "title": "La souscription n'est pas éligible à la finalisation",
 "status": 422,
 "detail": "Il manque des informations obligatoires pour transformer cette intention en contrat.",
 "instance": "/api/v1/souscriptions/sub_88a9/valider",
 "violations": [
    {
      "type": "missing-field",
      "pointer": "/adresse-voie",
      "title": "Type de voie manquante",
      "detail": "Vous devez préciser le type de voie dans votre adresse"
    }
  ],
 "is_ready_for_contract": false
}

Cette validation vérifie la cohérence interne de la demande, indépendamment des contraintes techniques du stockage final. En suivant la RFC 9457 - Problem Details, ceci permet également de mettre en évidence les champs ou sections présentant des problème.

Avis très personnel, je n’ai aucun scrupule, dans ces conditions, à mettre un verbe en dans l’URL de la ressource. Ceci correspond particulièrement bien à la notion de commande sur l'agrégat souscription. Si vous lui préférez une ressource d’intention, comme validation, qu’à celà ne tienne !

La vraie question architecturale est alors : pourquoi valider aussi tôt alors que le système Legacy devra de toute façon revalider à l'intégration ?

La réponse tient en trois lettres : SLA (Service Level Agreement). Dans le cas de Martin, votre zone de vente Digital doit fonctionner 24/7. Votre Core IT (Legacy), lui, est peut-être fermé la nuit pour les batchs, ou indisponible le week-end. Idéalement vous avez déjà découplé les systèmes via du Messaging pour régler cette asymétrie.

Mais si vous envoyez des données invalides dans le tuyau à 22h00 et que le Legacy les rejette à 08h00 le lendemain, l'expérience client est désastreuse. Martin pense être assuré, mais son dossier est en échec.

Trois stratégies s'offrent alors à vous pour gérer ce risque :

Stratégie 1 : l'optimisme (faible contrôle préalable)

C'est la stratégie du "Laissez-passer". Le système digital ne vérifie que le format (JSON valide) et envoie le tout.

  • Avantage : zéro couplage, mise en œuvre immédiate.
  • Risque : si le système legacy rejette le dossier (règle métier non respectée), le message finit dans une Dead Letter Queue (DLQ). Cela impose une gestion manuelle ou un processus "compensation", quel qu’il soit.

C’est un compromis qui peut s’avérer pertinent, mais à réserver aux processus très simples sans règles métier strictes.

Stratégie 2 : le backporting (la duplication)

Vous réécrivez tout ou partie des règles du mainframe dans un langage moderne et supporté, dans votre couche digitale, votre back for front.

  • Avantage : réponse immédiate à l'utilisateur.
  • Risque : la dérive. Le jour où les acteurs métiers changent une règle dans le canal historique, mais oublient de prévenir l’équipe qui gère le canal web, vous avez une divergence. Vous acceptez des dossiers qui seront rejetés plus tard.

C’est ce qui apportera la meilleure expérience avec un coût limité, si tant est que vous maitrisiez encore l’ancien système. Les contrôles de forme sont évidemment les premiers, mais une fois commencé, difficile de faire la part de choses entre intégrité (année non nulle, supérieure au 01/01/1970, au hasard) et contrôle de cohérence (10 ans c’est du neuf).

Ce ne devrait néanmoins être envisagé que sur une durée limitée ou pour des règles immuables (Lois physiques, Mathématiques).

Stratégie 3 : l'externalisation des règles (Shared Kernel ou DMN)

Au lieu de dupliquer la logique ou de l'ignorer, on l'extrait. Les règles de validation (éligibilité, calcul de risque, cohérence produits) sont sorties du code Legacy et modélisées dans un standard exécutable : soit avec un pattern de type Shared Kernel (si vos technologies sont compatibles, et c’est un gros si) soit avec DMN (Decision Model and Notation).

  • Avantage : réponse immédiate et aucun risque de dérive c'est une Single Source of Truth
  • Risque : plus une limite qu’un risque, ceci nécessite de disposer de ce type d’outillage et de pouvoir y accéder avec votre Legacy.

Vous créez donc un "Service de Décision" stateless.

A l'exécution :

  1. Le canal web appelle ce service via API (< 100-500ms) pour valider le dossier de Martin en temps réel.
  2. Le canal agence (s'il est modernisé ou via un wrapper) appelle ce même service lors de l'intégration finale.

C’est une excellente cible d'architecture : la logique fonctionnelle est définie une seule fois, par exemple au travers de tables de décision. Qu'elles soient consommées par l’application mobile, le  site web ou le batch de nuit, les règles métiers sont identiques et fournissent le même résultat. De plus, les moteurs DMN modernes (comme Zeebe ou Kogito) sont désormais cloud-native et passent à l’échelle aisément pour absorber la charge du parcours numérique.

Le Commit : le passage vers le Legacy

C'est l'étape finale. C'est le seul moment où nous allons traduire notre ressource souple Souscription vers le modèle rigide Contrat du Legacy.

Selon Udi Dahan (pionnier de CQRS/SOA), c'est ici que nous respectons le principe "Don't Create Aggregate Roots". L'utilisateur ne crée pas le contrat directement ; il soumet une demande validée que le système va traiter, demande qui va porter un certain nombre de règles et de vérifications (le “vrai métier”, le gardien du temple).

POST /api/v1/souscriptions/sub_88a9/soumettre

Le backend :

  1. verrouille la ressource Souscription ;
  2. adapte les données (mapping & transformations) ;
  3. réalise un certain nombre de vérifications (cf stratégie ci-dessus) ;
  4. appelle les services transactionnels du Legacy  ;
  5. renvoie l'ID du contrat final en cas de succès.

Ça y’est ! Martin est assuré … d’être assuré ;)

Pourquoi c'est indispensable ?

En adoptant cette architecture et cette stratégie de réification :

  1. Vous découplez les cycles de vie : votre app’ mobile peut évoluer toutes les semaines, votre mainframe tous les 6 mois. La ressource Souscription de votre API sert de tampon, un Anti-Corruption Layer temporel en somme.
  2. Vous garantissez la qualité des données : seuls les dossiers complets et valides entrent dans votre système de gestion. Fini la compromission de la qualité des données, sans trop sacrifier le tunnel de conversion client.
  3. Vous offrez une vraie expérience omnicanale : l'état brouillon n’est plus une bidouille maladroite mais un vrai statut, accessible par le client et l'agent.

Ne laissez donc plus votre schéma de base de données dicter l'expérience de vos utilisateurs. Réifiez vos processus.