Apprenez une méthode pratique pour transformer des récits utilisateurs, entités et workflows en un schéma de base de données clair, et comment le raisonnement IA peut aider à détecter les manques et règles.

Un schéma de base de données est le plan de la façon dont votre appli va se souvenir des choses. En termes pratiques, c’est :
Quand le schéma colle au travail réel, il reflète ce que les gens font vraiment — créer, relire, approuver, planifier, assigner, annuler — plutôt que ce qui paraît net sur un tableau blanc.
Les récits utilisateurs et les critères d’acceptation décrivent des besoins concrets en langage simple : qui fait quoi, et ce que « fait » signifie. Si vous les utilisez comme source, le schéma a moins de chances d’oublier des détails clés (comme « il faut tracer qui a approuvé le remboursement » ou « une réservation peut être replanifiée plusieurs fois »).
Partir des stories vous garde aussi honnête sur la portée. Si ce n’est pas dans les stories (ou le workflow), traitez‑le comme optionnel plutôt que de construire en catimini un modèle compliqué « au cas où ».
L’IA peut vous aider à aller plus vite en :
L’IA ne peut pas de façon fiable :
Considérez l’IA comme un assistant puissant, pas comme le décideur.
Si vous voulez transformer cet assistant en accélérateur, une plateforme vibe‑coding comme Koder.ai peut vous aider à passer des décisions de schéma à une appli fonctionnelle React + Go + PostgreSQL plus vite — tout en vous laissant le contrôle sur le modèle, les contraintes et les migrations.
La conception de schéma est une boucle : brouillon → tester contre les stories → trouver les données manquantes → affiner. L’objectif n’est pas un premier résultat parfait ; c’est un modèle que vous pouvez rattacher à chaque story et dire en toute confiance : “Oui, on peut stocker tout ce dont ce workflow a besoin — et on peut expliquer pourquoi chaque table existe.”
Avant de transformer des exigences en tables, clarifiez ce que vous modélisez. Un bon schéma commence rarement à partir d’une page blanche — il commence par le travail concret que font les gens et la preuve dont vous aurez besoin ensuite (écrans, sorties, cas limites).
Les récits utilisateurs sont le titre, mais ils ne suffisent pas seuls. Rassemblez :
Si vous utilisez une IA, ces entrées ancrent le modèle. L’IA peut proposer des entités et champs rapidement, mais elle a besoin d’artefacts réels pour éviter d’inventer une structure qui ne correspond pas à votre produit.
Les critères d’acceptation contiennent souvent les règles de base de données les plus importantes, même quand elles ne mentionnent pas explicitement des données. Cherchez des formulations comme :
Des stories vagues (« En tant qu’utilisateur, je peux gérer des projets ») cachent plusieurs entités et workflows. Un autre écueil fréquent est l’absence de cas limite comme annulations, réessais, remboursements partiels ou réaffectation.
Avant de penser aux tables ou aux diagrammes, lisez les stories et surlignez les noms. En écriture de spécifications, les noms pointent généralement sur les « choses » que votre système doit retenir — elles deviennent souvent des entités dans votre schéma.
Un modèle mental rapide : les noms deviennent des entités, tandis que les verbes deviennent des actions ou workflows. Si une story dit « Un manager assigne un technicien à un travail », les entités probables sont manager, technicien, et job — et « assigne » indique une relation à modéliser.
Tous les noms ne méritent pas leur propre table. Un nom est un bon candidat quand il :
Si un nom n’apparaît qu’une fois, ou ne fait que décrire autre chose (« bouton rouge », « vendredi »), ce n’est peut‑être pas une entité.
Une erreur commune est de transformer chaque détail en table. Utilisez cette règle :
Deux exemples classiques :
L’IA accélère la découverte d’entités en scannant les stories et en retournant une liste provisoire de noms, groupés par thème (personnes, éléments de travail, documents, lieux). Un prompt utile : « Extrais les noms qui représentent des données à stocker et groupe synonymes/duplications. »
Traitez la sortie comme un point de départ, pas comme la réponse. Posez des questions de suivi comme :
L’objectif de l’Étape 1 est une liste courte et défendable d’entités que vous pouvez rattacher aux stories réelles.
Une fois les entités nommées (comme Order, Customer, Ticket), la tâche suivante est de capturer les détails dont vous aurez besoin plus tard. Dans une base, ces détails sont des champs (aussi appelés attributs) — les rappels que le système ne doit pas oublier.
Commencez par la story, puis lisez les critères d’acceptation comme une checklist de ce qui doit être stocké.
Si une exigence dit « Les utilisateurs peuvent filtrer les commandes par date de livraison », alors delivery_date n’est pas optionnel — il doit exister en tant que champ (ou être dérivé de manière fiable d’autres données stockées). Si on dit « Afficher qui a approuvé la demande et quand », il vous faudra probablement approved_by et approved_at.
Un test pratique : Quelqu’un aura‑t‑il besoin de cette donnée pour afficher, rechercher, trier, auditer ou calculer quelque chose ? Si oui, elle appartient probablement à un champ.
Beaucoup de stories contiennent des mots comme « statut », « type » ou « priorité ». Traitez‑les comme des vocabulaires contrôlés — un ensemble limité de valeurs autorisées.
Si l’ensemble est petit et stable, un champ de type enum suffit. S’il peut croître, nécessite des libellés ou des permissions (ex. catégories gérées par admin), utilisez une table de lookup séparée (ex. status_codes) et stockez une référence.
C’est ainsi que les stories deviennent des champs fiables — recherchables, reportables et difficiles à mal saisir.
Quand vous avez listé les entités (User, Order, Invoice, Comment, etc.) et esquissé leurs champs, l’étape suivante est de les relier. Les relations sont la couche « comment ces choses interagissent » implicite dans vos stories.
Un‑à‑un (1:1) signifie « une chose a exactement une autre chose ».
User ↔ Profile (souvent fusionnable sauf raison de séparation).Un‑à‑plusieurs (1:N) signifie « une chose peut avoir plusieurs autres choses ». C’est le plus courant.
User → Order (stocker user_id sur Order).Plusieurs‑à‑plusieurs (M:N) signifie « plusieurs choses peuvent être liées à plusieurs choses ». Nécessite une table supplémentaire.
On ne stocke pas une « liste d’IDs produits » proprement dans Order sans créer des problèmes (recherche, mise à jour, reporting). Créez une table de jointure représentant la relation.
Exemple :
OrderProductOrderItem (table de jointure)OrderItem inclut généralement :
order_idproduct_idquantity, unit_price, discountRemarquez que les détails de la story (« quantity ») appartiennent souvent à la relation, pas à l’une ou l’autre entité.
Les stories vous disent aussi si une connexion est obligatoire ou parfois absente.
Order a besoin d’un user_id (ne doit pas être nul).phone peut être vide.shipping_address_id peut être vide pour les biens numériques.Si la story implique qu’on ne peut pas créer l’enregistrement sans le lien, traitez‑le comme requis. Si la story dit « peut », « peut être » ou donne des exceptions, traitez‑le comme optionnel.
Quand vous lisez une story, réécrivez‑la comme un jumelage simple :
User 1:N CommentComment N:1 UserFaites cela pour chaque interaction. À la fin, vous aurez un modèle connecté qui reflète la manière dont le travail arrive — avant d’ouvrir un outil ER.
Les stories disent quoi veulent les gens. Les workflows montrent comment le travail circule, étape par étape. Traduire un workflow en données est une des façons les plus rapides de détecter les problèmes « on a oublié de stocker ça » — avant de construire quoi que ce soit.
Écrivez le workflow comme une suite d’actions et de changements d’état. Exemple :
Ces mots en gras deviennent souvent un champ status (ou une petite table “state”), avec des valeurs autorisées claires.
En parcourant chaque étape, demandez : « Que faudra‑t‑il savoir plus tard ? » Les workflows révèlent couramment des champs tels que :
submitted_at, approved_at, completed_atcreated_by, assigned_to, approved_byrejection_reason, approval_notesequence pour des processus multi‑étapesSi votre workflow inclut des attentes, escalades ou transferts, vous aurez généralement besoin d’au moins un timestamp et d’un champ « qui le détient maintenant ».
Certaines étapes de workflow ne sont pas seulement des champs — ce sont des structures de données :
Fournissez à l’IA : (1) les stories et critères, et (2) les étapes du workflow. Demandez‑lui de lister chaque étape et d’identifier les données requises pour chacune (état, acteur, timestamps, sorties), puis de surligner toute exigence qui ne peut pas être supportée par les champs/tables actuels.
Sur des plateformes comme Koder.ai, ce « contrôle des lacunes » devient pratique : vous ajustez vite les hypothèses de schéma, régénérez le squelette et avancez sans détour lourd par la génération manuelle de boilerplate.
Quand vous transformez des stories en tables, vous ne vous contentez pas d’énumérer des champs — vous décidez aussi comment les données restent identifiables et cohérentes dans le temps.
Une clé primaire identifie de façon unique un enregistrement — pensez‑y comme à la carte d’identité permanente de la ligne.
Pourquoi chaque ligne en a besoin : les stories impliquent des mises à jour, des références et de l’historique. Si une story dit « Le support peut voir une commande et émettre un remboursement », il faut un moyen stable de pointer vers la commande — même si le client change d’email, que l’adresse est modifiée ou que le statut change.
Dans la pratique, c’est souvent un id interne (numérique ou UUID) qui ne change jamais.
Une clé étrangère permet à une table de pointer en sécurité vers une autre. Si orders.customer_id référence customers.id, la base peut garantir que chaque commande appartient à un client réel.
Cela correspond à des stories comme « En tant qu’utilisateur, je peux voir mes factures. » La facture n’est pas flottante ; elle est rattachée à un client (et souvent à une commande ou un abonnement).
Les stories contiennent souvent des exigences d’unicité cachées :
Ces règles évitent les doublons gênants qui apparaissent plus tard comme « bugs de données ».
Les index rendent rapides les recherches comme « trouver un client par email » ou « lister les commandes par client ». Commencez par des index alignés sur vos recherches les plus fréquentes et sur les règles d’unicité.
À différer : l’indexation lourde pour des rapports rares ou des filtres spéculatifs. Capturez ces besoins dans les stories, validez le schéma, puis optimisez selon l’usage réel et les requêtes lentes observées.
La normalisation vise une chose simple : empêcher les doublons contradictoires. Si le même fait peut être enregistré à deux endroits, tôt ou tard il y aura des désaccords (deux orthographes, deux prix, deux adresses « courantes »). Un schéma normalisé stocke chaque fait une fois, puis y fait référence.
1) Repérez les groupes répétés
Si vous voyez des motifs comme “Phone1, Phone2, Phone3” ou “ItemA, ItemB, ItemC”, pensez à une table séparée (ex. CustomerPhones, OrderItems). Les groupes répétés rendent la recherche, la validation et la mise à l’échelle difficiles.
2) Ne dupliquez pas le même nom/détails dans plusieurs tables
Si CustomerName apparaît dans Orders, Invoices et Shipments, vous avez plusieurs sources de vérité. Gardez les détails client dans Customers et stockez seulement customer_id ailleurs.
3) Évitez plusieurs colonnes pour la même chose
Des colonnes comme billing_address, shipping_address, home_address peuvent être acceptables si ce sont vraiment des concepts différents. Mais si vous modélisez « plusieurs adresses de types différents », utilisez une table Addresses avec un champ type.
4) Séparez les lookup des textes libres
Si les utilisateurs choisissent dans un ensemble connu (statut, catégorie, rôle), modélisez‑le de manière cohérente : enum contraint ou table de lookup. Cela évite “Pending” vs “pending” vs “PENDING”.
5) Vérifiez que chaque champ non‑ID dépend de la bonne chose
Un bon réflexe : dans une table, si une colonne décrit autre chose que l’entité principale, elle appartient probablement ailleurs. Ex. : Orders ne devrait pas stocker product_price sauf si cela signifie « prix au moment de la commande » (un snapshot historique).
Parfois vous dupliquez volontairement :
L’essentiel est d’en faire un choix intentionnel : documentez quelle colonne est la source de vérité et comment les copies sont mises à jour.
L’IA peut repérer des duplications suspectes (colonnes répétées, noms de champs similaires, statuts incohérents) et suggérer des séparations en tables. Les humains choisissent encore les compromis — simplicité vs flexibilité vs performance — selon l’usage réel du produit.
Une règle utile : stockez les faits qu’on ne peut pas recréer de façon fiable ; calculez tout le reste.
Données stockées = source de vérité : lignes, timestamps, changements d’état, qui a fait quoi. Données calculées = produites à partir de ces faits : totaux, compteurs, flags comme “en retard”, agrégats.
Si deux valeurs peuvent être calculées depuis les mêmes faits, préférez stocker les faits et calculer le reste. Sinon, vous risquez des contradictions.
Les valeurs dérivées changent quand leurs entrées changent. Si vous stockez à la fois les entrées et le résultat dérivé, il faut les garder synchrones à chaque workflow et cas limite (modifs, remboursements, changements rétroactifs). Une mise à jour ratée et la base raconte deux histoires différentes.
Ex. : stocker order_total et aussi order_items. Si quelqu’un modifie une quantité ou applique une remise et que le total n’est pas mis à jour parfaitement, la finance voit un nombre et le panier un autre.
Les workflows montrent quand vous avez besoin de la vérité historique, pas seulement de la vérité courante. Si les utilisateurs doivent savoir « quelle était la valeur à l’instant T », stockez un snapshot.
Pour une commande, vous pouvez stocker :
order_total capturé au paiement (snapshot), car taxes, remises et règles de prix peuvent changer plus tardPour l’inventaire, le « niveau d’inventaire » se calcule souvent depuis des mouvements (réceptions, ventes, ajustements). Mais si vous avez besoin d’une piste d’audit, stockez les mouvements et éventuellement des snapshots périodiques pour le reporting.
Pour le suivi de connexion, stockez last_login_at comme fait (timestamp d’événement). « Actif dans les 30 derniers jours ? » reste calculé.
Prenons une application de tickets de support familière. Nous passons de cinq récits utilisateurs à un petit modèle ER (entités + champs + relations), puis nous le vérifions sur un workflow.
Des noms ressortent, donnant les entités :
Avant (erreur fréquente) : Ticket a assignee_id, mais rien n’empêche qu’un client soit enregistré comme assignee.
Après : l’IA le signale et vous ajoutez une règle pratique : assignee doit être un User avec role = “agent” (implémentée via validation applicative ou contrainte/politique en base, selon votre stack). Cela évite des « assignés aux clients » qui faussent les rapports.
Un schéma est « terminé » quand chaque récit utilisateur peut être satisfait par des données que vous pouvez stocker et requêter de façon fiable. Le contrôle le plus simple : prenez chaque story et demandez‑vous : “Peut‑on répondre à cette histoire depuis la base, de façon fiable, pour tous les cas ?” Si la réponse est « peut‑être », votre modèle a une lacune.
Réécrivez chaque story en une ou plusieurs questions de test — choses que vous attendez d’un rapport, d’un écran ou d’une API. Exemples :
Si vous ne pouvez pas exprimer une story comme une question claire, la story est floue. Si vous pouvez l’exprimer mais pas y répondre via le schéma, il manque un champ, une relation, un statut/événement ou une contrainte.
Créez un petit jeu de données synthétique (5–20 lignes par table clé) incluant cas normaux et cas gênants (doublons, valeurs manquantes, annulations). Jouez les stories avec ces données : vous repérerez vite des problèmes comme « on ne peut pas dire quelle adresse a été utilisée au moment de l’achat » ou « on n’a nulle part où stocker qui a approuvé le changement ».
Demandez à l’IA de générer des questions de validation par story (y compris les cas limites et scénarios de suppression) et de lister les données nécessaires pour y répondre. Comparez cette liste à votre schéma : tout écart devient une action concrète, pas une impression floue qu’“il manque quelque chose”.
L’IA accélère la modélisation, mais elle augmente aussi le risque de fuite d’informations sensibles ou d’ancrage d’hypothèses erronées. Traitez‑la comme un assistant très rapide : utile, mais à encadrer.
Partagez des entrées assez réalistes pour modéliser, mais assainies pour être sûres :
invoice_total: 129.50, status: "paid")Évitez tout ce qui identifie une personne ou révèle des opérations confidentielles :
Si vous avez besoin de réalisme, générez des échantillons synthétiques qui respectent formats et plages — ne copiez jamais des lignes de production.
Les échecs de schéma viennent le plus souvent de « tout le monde supposait » des choses différentes. À côté de votre modèle ER (ou dans le même repo), tenez un court journal de décisions :
Cela transforme la sortie IA en connaissance d’équipe plutôt qu’en artefact isolé.
Votre schéma va évoluer avec de nouvelles stories. Protégez‑le en :
Sur des plateformes comme Koder.ai, profitez de garde‑fous (snapshots, rollback) quand vous itérez sur le schéma, et exportez le code source quand vous avez besoin d’une revue traditionnelle.
Commencez par les stories et surlignez les noms qui représentent des choses que le système doit mémoriser (par ex. Ticket, User, Category).
Promouvez un nom en entité quand il :
Gardez une liste courte que vous pouvez justifier en citant des phrases spécifiques des stories.
Utilisez un test « attribut vs entité » :
customer.phone_number).Un indice rapide : si vous aurez « plusieurs » de ces éléments, il vous faut probablement une autre table.
Traitez les critères d’acceptation comme une checklist de stockage. Si une exigence dit que vous devez filtrer/afficher/contrôler quelque chose, il faut le stocker (ou pouvoir le dériver de manière fiable).
Exemples :
approved_by, approved_atRéécrivez les phrases des stories en phrases de relation :
customer_id dans orders)order_items)Si la relation elle‑même a des données (quantité, prix, rôle), ces données appartiennent à la table de jointure.
Modélisez le M:N avec une table de jointure qui contient les deux clés étrangères et les champs propres à la relation.
Schéma type :
ordersproductsParcourez le workflow étape par étape et demandez : “Que faudrait‑il prouver que ceci a eu lieu plus tard ?”
Ajouts courants :
submitted_at, closed_atCommencez par :
id)orders.customer_id → customers.id)Ajoutez ensuite des index pour les recherches fréquentes (ex. , , ). Différez l’indexation spéculative jusqu’à l’observation de requêtes lentes.
Faites un contrôle de cohérence rapide :
Phone1/Phone2, éclatez en une table enfant.Dénormalisez plus tard uniquement avec une raison claire (performance, reporting, clichés d’historique) et documentez la source de vérité.
Stockez les faits qu’on ne peut pas re-créer de façon fiable ; calculez le reste.
Bon à stocker :
Bon à calculer :
Si vous stockez des valeurs dérivées (ex. ), définissez comment elles restent synchrones et testez les cas limites (remboursements, modifications, expéditions partielles).
Utilisez l’IA pour des brouillons, puis vérifiez contre vos artefacts.
Prompts pratiques :
Garde‑fous :
delivery_dateemailorder_items avec order_id, product_id, quantity, unit_priceÉvitez de stocker « une liste d’IDs » dans une colonne : requêter, mettre à jour et garantir l’intégrité devient compliqué.
created_by, assigned_to, closed_byrejection_reasonSi vous devez savoir « qui a changé quoi quand », ajoutez une table d’événements/audit au lieu d’écraser un champ unique.
emailcustomer_idstatus + created_atorder_total