Étude de cas A — Modifier une règle de tarification sans créer de dette invisible
Une équipe Commerce doit introduire une remise de fidélité : au-delà d'un seuil annuel d'achats, un client reçoit 5 % de réduction sur les produits éligibles. La demande paraît locale. Le calcul de prix existe déjà, le client est identifié et l'interface affiche un total. L'équipe pourrait ajouter une condition dans le service de panier et un test nominal.
Cette lecture serait insuffisante. Le prix est aussi calculé pendant la confirmation, dans un job de réconciliation, sur des commandes importées et dans le détail de facture. Les remboursements s'appuient sur le montant encaissé, et des partenaires reçoivent un événement de commande contenant les montants. Une erreur peut générer une perte financière, une facture incohérente ou un écart difficile à réparer après la clôture.
Découvrir avant de choisir la solution
La première fiche de comportement définit quatre invariants : une remise ne dépasse jamais le montant des lignes éligibles ; le total encaissé est celui qui apparaît sur la facture ; une commande garde la décision de prix qui lui a été appliquée ; un remboursement ne recalcule pas la règle sur la base du statut actuel du client. Ces invariants révèlent une hypothèse cachée : le statut de fidélité peut changer après une commande.
L'équipe cartographie ensuite le flux. Le moteur de prix décide le montant ; la confirmation le persiste ; la facturation et les remboursements lisent ce montant figé ; l'événement CommandeConfirmée l'expose à des consommateurs externes. Le statut de fidélité, en revanche, est possédé par un autre domaine. Il serait donc dangereux de faire recalculer le prix historique par un lecteur éloigné.
| Risque | Décision prise | Preuve associée |
|---|---|---|
| Règle ambiguë | Écrire des exemples et les invariants métier | Tests de décision et revue avec Finance |
| Réduction multiple | Centraliser l'ordre des règles de prix | Cas de combinaison et propriétés de plafond |
| Historique modifié | Persister la décision de remise dans la commande | Test de remboursement après changement de statut |
| Consommateur d'événement | Ajouter le champ de façon compatible | Test de contrat et suivi de l'adoption |
| Erreur de déploiement | Exposer par cohorte | Métrique de remise et rapprochement journalier |
Concevoir une transition, pas seulement une condition
Le modèle introduit une décision de prix explicite : montant éligible, règle appliquée, taux et montant de remise. Il ne stocke pas seulement un booléen isLoyal, car ce booléen ne pourrait pas expliquer un montant historique ni survivre à une évolution de règle. La commande reste la source de vérité sur ce qui a été vendu ; le domaine Fidélité reste propriétaire du statut qui autorise une future remise.
Le schéma est ajouté de manière compatible. Le code de lecture tolère les commandes anciennes sans remise ; le nouveau chemin d'écriture reste désactivé. L'équipe exécute alors le calcul en parallèle : elle enregistre la remise qui aurait été appliquée, sans modifier encore le montant payé. Cette étape répond à la question la plus risquée : les données de fidélité et l'éligibilité produit donnent-elles des résultats attendus sur le trafic réel ?
Les écarts observés ne sont pas tous des bugs. Certains comptes historiques utilisent une devise non prise en charge par la première version ; certains produits sont éligibles dans le catalogue mais exclus par un contrat partenaire. L'équipe documente ces décisions au lieu de forcer les données à correspondre au code. Elle ajoute une exception de domaine explicite et reporte les devises non supportées avec un message produit honnête.
Produire des preuves complémentaires
Les tests de décision couvrent les seuils, plafonds, arrondis, combinaisons de coupons et remboursements. Un test de contrat protège le nouveau champ de l'événement sans imposer aux consommateurs de l'utiliser. Une intégration avec un environnement de paiement vérifie que le montant persisté est celui débité. Enfin, le rapprochement quotidien compare le montant attendu, le montant encaissé et le montant facturé ; il est conservé après l'activation car il protège une propriété financière durable.
L'équipe évite un anti-pattern courant : ajouter un test E2E pour chaque combinaison de produits, devises et remises. Cette suite serait lente et ne rendrait pas le calcul plus lisible. Les combinaisons sont traitées par des tests de domaine rapides, tandis que quelques parcours de paiement confirment l'intégration essentielle.
Livrer et apprendre
La remise est activée d'abord pour les collaborateurs, puis pour une cohorte de clients dans une devise et une région. Les signaux suivis sont le taux de remise, l'écart de rapprochement, le taux d'échec de paiement, le temps de calcul et les tickets de support. Le seuil d'arrêt est explicite : tout écart financier non expliqué, ou une hausse de refus de paiement au-delà du bruit historique, désactive le flag pour les nouvelles commandes et déclenche l'investigation.
Après plusieurs cohortes, l'équipe constate que la règle de priorité entre promotions est devenue la partie la plus difficile à expliquer. Ce n'est pas un défaut du déploiement ; c'est un apprentissage de domaine. Elle transforme cette règle en politique de prix nommée, avec des exemples partagés par Commerce et Finance. Le changement initial a donc produit plus qu'une remise : il a rendu le système de tarification plus cohérent pour les évolutions suivantes.
À retenir
Une règle de tarification est un changement de données, de contrats, d'exploitation et de confiance utilisateur. L'approche sûre ne consiste pas à tout tester partout ; elle rend explicites les invariants, fige les décisions qui doivent l'être, compare avant d'exposer et conserve les signaux qui permettent de détecter une divergence financière.