Prévenir les crashs liés aux données nulles : contraintes, valeurs par défaut et backfills
Évitez les crashs dus aux données nulles avec des contraintes DB, des valeurs par défaut sûres, la validation applicative et des backfills pour que les prototypes seed-data tiennent en production.

Pourquoi les données de seed cachent les problèmes de valeurs nulles
“Ça marche avec des données seed” signifie généralement que l’app a été testée avec un petit jeu d’enregistrements fait à la main, propres, complets et adaptés au chemin heureux. Chaque utilisateur a un nom, chaque commande a une adresse et chaque paramètre existe. Le code semble correct parce qu’il ne rencontre jamais le désordre réel.
L’utilisation réelle crée vite des trous. Des gens abandonnent des formulaires, des feuilles de calcul arrivent avec des colonnes vides, et des API tierces renvoient des champs seulement parfois. Même des utilisateurs soigneux font des choix qui laissent quelque chose manquant.
Les valeurs vides apparaissent souvent après le lancement lorsque :
- Un flux d’inscription permet de sauter les détails du profil, puis des pages ultérieures supposent qu’ils existent
- Un import CSV contient des emails vides, des prix manquants ou des dates incohérentes
- Un client mobile envoie un payload partiel sur une connexion instable
- Un webhook change de forme, ou un champ est null pendant une panne
- Un coéquipier édite les données manuellement et laisse un champ requis vide
Un crash dû à des données nulles arrive quand votre code attend une valeur mais ne reçoit rien. L’application tente d’utiliser un champ vide comme s’il s’agissait d’une donnée réelle et lève une erreur. Cela peut apparaître comme “cannot read property of null”, une insertion en base qui échoue, une page cassée ou un job en arrière-plan qui retente indéfiniment.
Prévenir les crashs liés aux valeurs nulles n’est pas seulement une tâche de programmation. C’est une question de règles de données. Il vous faut deux choses qui fonctionnent ensemble :
-
Empêcher que de mauvaises données soient stockées (pour que la base reste fiable).
-
Gérer les données manquantes de façon sûre quand elles sont autorisées (pour que l’app continue de fonctionner et que l’utilisateur soit guidé pour corriger).
Les prototypes générés par IA sont particulièrement vulnérables ici. L’UI suppose souvent des entrées parfaites, et la base accepte souvent n’importe quoi. C’est pourquoi un prototype peut bien faire une démo, puis casser en production la première fois qu’un utilisateur réel saute un champ ou qu’un import contient des vides.
Une fois que vous traitez les données de seed comme le “meilleur cas”, vous pouvez concevoir pour le cas normal : incomplet, incohérent et parfois erroné.
Commencez par des règles claires : que peut-on laisser manquant ?
La plupart des apps ne plantent pas parce que les données sont “mauvaises”. Elles plantent parce que l’app et la base de données ne sont pas d’accord sur ce qui est autorisé à manquer. Avant d’ajouter des contraintes ou d’écrire des migrations, écrivez les règles en anglais simple. Cette étape seule évite souvent plus de crashs liés aux nulls que n’importe quel changement de code.
Commencez par décider explicitement “obligatoire vs optionnel” :
- Email : requis pour la connexion et la réinitialisation de mot de passe, ou optionnel si vous supportez uniquement le téléphone ou SSO
- Adresse ligne 2 : optionnelle
- Bio du profil : optionnelle, mais l’UI doit gérer les états vides
- Date de naissance : optionnelle, ou requise uniquement pour des fonctionnalités avec restriction d’âge
- Nom de l’entreprise : optionnel pour les particuliers, requis pour les comptes business
Séparez ensuite trois états qui demandent un traitement différent dans l’UI, l’API et la base :
- Inconnu : vous attendiez la valeur, mais vous ne l’avez pas encore (souvent temporaire)
- Non fourni : l’utilisateur a choisi de laisser vide
- Non applicable : le champ n’a pas de sens pour cet enregistrement
Exemple : dans un flux d’inscription, profile.bio est optionnel. billing_country peut être inconnu au moment de l’inscription, mais requis avant de créer un paiement. vat_id peut être non applicable pour de nombreux utilisateurs.
Décidez ensuite ce qui doit être bloqué vs autorisé-et-géré. Bloquez quand l’app ne peut pas fonctionner ou respecter des obligations légales/sécurité sans la valeur (identifiants de connexion, rôles de permission, IDs de propriété). Autorisez-et-gérez quand vous pouvez afficher un fallback sûr (bio vide, avatar manquant) ou le collecter plus tard.
Rédigez vos règles comme une courte spécification avant de toucher au code :
“User.email est requis et unique. User.address_line_2 est optionnel. Profile.bio est optionnel et s’affiche comme vide. Payment.country est requis avant de créer une charge.”
Si vous avez hérité d’un prototype généré par IA, cette spécification est généralement ce qui manque. Les audits commencent souvent ici car ils révèlent où les nulls sont acceptables et où ils doivent être arrêtés tôt.
Contraintes BD qui empêchent les mauvaises données d’être stockées
Si vous voulez prévenir les crashs de données nulles, la base de données doit dire “non” quand l’app essaie d’enregistrer quelque chose qui cassera plus tard. Le code applicatif change souvent, mais les contraintes restent. Elles constituent un filet de sécurité fiable, surtout quand un prototype “fonctionnait” seulement parce qu’il avait été testé avec des données seed parfaites.
Utilisez NOT NULL pour les champs véritablement requis
Ajoutez NOT NULL uniquement aux champs dont votre app ne peut se passer. Un bon test est : “Un utilisateur réel peut-il compléter un flux clé si ceci manque ?” Si non, rendez-le requis au niveau de la base.
Par exemple, une table orders ne peut généralement pas fonctionner sans user_id et created_at. Si ceux-ci sont nullable, vous finirez par avoir des lignes qui semblent correctes dans l’UI mais qui cassent les rapports, les emails ou les vues d’administration.
Ajoutez des règles simples avec CHECK
Les contraintes CHECK sont parfaites pour des règles basiques et lisibles qui empêchent les valeurs pourries :
- Plages :
quantity > 0,price_cents >= 0 - Texte non vide :
trim(display_name) <> '' - Valeurs autorisées :
status IN ('draft','active','canceled') - Dates qui ont du sens :
end_date >= start_date
Ces règles empêchent des données “techniquement non nulles mais inutilisables”. Une chaîne vide dans un champ nom peut causer le même UI cassé qu’un null.
L’unicité est une autre source fréquente de surprises. Utilisez UNIQUE pour des identifiants qui ne doivent jamais dupliquer, comme email, username ou un ID d’un fournisseur externe (par exemple google_sub). Sans cela, vous pouvez vous retrouver avec deux comptes qui semblent être le même utilisateur et le code en aval choisira la mauvaise ligne.
Les clés étrangères comptent aussi. Si vous autorisez des lignes enfants sans parent (comme des profile sans user), le code qui suppose que les relations existent échouera de façon étrange. Les foreign keys évitent les enregistrements orphelins et gardent les suppressions/mises à jour honnêtes.
Les contraintes sont la dernière ligne de défense, pas la seule. Votre app doit toujours valider l’entrée et afficher des erreurs conviviales, mais la base doit faire respecter les règles pour que de mauvaises données ne passent pas via des jobs en arrière-plan, scripts admin ou correctifs rapides.
Valeurs par défaut qui rendent les données manquantes sûres (sans masquer les problèmes)
Les valeurs par défaut aident quand une valeur doit exister pour chaque ligne, mais les utilisateurs et le code ne doivent pas la fournir. Elles peuvent prévenir les crashs en rendant « vide » impossible là où « vide » n’a pas de sens.
Un bon défaut correspond au comportement réel du produit. Si vous ne pouvez pas expliquer ce que la valeur signifie à une personne du support, ce n’est probablement pas un bon défaut.
Bons défauts : ennuyeux, prédictibles et corrects
Utilisez des valeurs par défaut pour les champs inévitables et non choisis par l’utilisateur :
created_atouupdated_attimestamps- un
statusqui commence commepending,draftouactive - compteurs comme
login_countdémarrant à0 - flags simples comme
is_deleteddémarrant àfalse
Ces valeurs réduisent la surface d’erreurs, surtout dans les prototypes générés par IA où certains chemins oublient de définir des champs.
Valeurs par défaut qui cachent des bugs (et créent pire que rien)
Les défauts deviennent dangereux quand ils colmatent des relations manquantes ou des entrées requises. Ils donnent l’impression que l’app est stable tout en remplissant la base avec des absurdités.
Évitez des défauts comme :
user_id = 0ouaccount_id = 1quand le propriétaire réel est inconnuemail = ''(chaîne vide) pour contourner un email manquantprice = 0quand un prix était requis pour facturer correctementrole = 'admin'parce que l’UI n’a pas envoyé de rôle
Quand vous ajoutez ensuite des contraintes, les rapports, permissions et logique de facturation cassent de façon déroutante.
Si quelque chose peut manquer pendant un moment, utilisez un état explicite “pas prêt” (not ready yet). Par exemple, un profil peut démarrer avec status = 'incomplete' jusqu’à ce que l’utilisateur ajoute un nom et un téléphone. Cela rend l’état manquant visible, testable et facile à gérer dans l’UI.
Un scénario rapide : un flux d’inscription crée d’abord une ligne user, puis demande les détails du profil à l’écran suivant. Un défaut sûr est profile_status = 'incomplete', pas name = 'Unknown'. “Unknown” ressemble à une vraie donnée, donc personne ne la corrige.
Validation applicative : attraper les problèmes avant la base
Les crashs liés aux nulls commencent souvent avant que la base ne voie la requête. Un formulaire envoie un champ vide, un client API oublie une propriété, ou un webhook envoie un payload légèrement différent de celui que vous avez testé. La validation est votre première ligne de défense. Elle transforme une “erreur serveur mystère” en message clair et empêche de mauvaises données d’entrer dans le système.
Validez à la frontière, le plus près possible de l’entrée. Cela signifie formulaires navigateur, requêtes API et intégrations qui postent des données dans votre app (comme des prestataires de paiement ou outils d’email). Si vous acceptez des entrées à trois endroits, vous avez besoin de contrôles aux trois endroits. Le chemin le plus faible est celui qui casse en production.
La bonne validation ne se limite pas à “requis ou non”. Elle normalise aussi les données pour que vous stockiez ce à quoi vous vous attendez. Supprimez les espaces en trop, décidez si les emails doivent être en minuscules et traitez les chaînes vides de manière cohérente (souvent comme null, mais seulement si vos règles l’autorisent). Normaliser tôt évite des bugs subtils comme des comptes dupliqués parce qu’un email avait des espaces en fin de chaîne.
Quand la validation échoue, renvoyez des messages compréhensibles, pas des traces de stack. Les utilisateurs doivent savoir quoi corriger, et le support doit pouvoir reproduire le problème. Une réponse 400 avec une phrase claire bat une erreur 500.
Une approche simple qui marche pour la plupart des apps :
- Validez côté serveur pour chaque écriture, même si l’UI valide déjà
- Normalisez les champs avant sauvegarde (trim, casse, gestion des chaînes vides)
- Rejetez les champs inconnus pour que les fautes de frappe ne deviennent pas silencieusement des nulls
- Utilisez des messages d’erreur clairs liés au nom du champ
- Journalisez les échecs de validation avec assez de contexte (mais jamais de secrets)
Pour éviter la dérive des règles, centralisez la validation et réutilisez-la. Un échec fréquent dans la mise en production de prototypes générés par IA est un jeu de règles côté UI, un autre côté API et aucun côté handler de webhook. Choisissez une source de vérité unique (souvent un validateur serveur ou un schéma partagé) et faites en sorte que les autres couches s’y réfèrent.
Exemple concret : votre formulaire d’inscription exige un nom complet, mais votre client mobile n’envoie que l’email et le mot de passe. Si le serveur ne valide pas, vous pouvez créer une ligne user avec name = null, et la première page “Welcome, {name}” plante. Avec la validation serveur, la requête d’inscription échoue vite avec “Nom complet requis” et vous n’enregistrez jamais l’enregistrement cassé.
Étape par étape : ajouter des contraintes en toute sécurité dans une app existante
Pour prévenir les crashs liés aux valeurs nulles, traitez les contraintes comme un déploiement progressif, pas comme un interrupteur. L’approche la plus sûre est d’apprendre où les nulls existent aujourd’hui, réparer les anciennes lignes, puis bloquer les nouvelles mauvaises écritures.
Commencez par inventorier ce qui peut être null maintenant. Regardez vos tables, et aussi où chaque champ est utilisé : réponses d’API, rendu UI, emails, jobs en arrière-plan et exports. Une colonne inoffensive sur un écran peut planter un autre qui suppose qu’elle est toujours présente.
Un déroulé pratique :
- Trouver les zones à risque. Listez les colonnes qui autorisent les nulls et recherchez dans le code les endroits qui supposent une valeur (par exemple appeler
.toLowerCase()sur un nom). - Décider la règle. Pour chaque colonne, choisissez : doit être présente, peut manquer, ou peut manquer seulement à certains moments (comme “jusqu’à la fin de l’onboarding”).
- Backfill des lignes existantes. Mettez à jour les anciennes lignes pour qu’elles correspondent à la règle. Si vous ne pouvez pas backfiller correctement, utilisez un état temporaire clairement marqué et un plan pour collecter la valeur réelle plus tard.
- Ajouter les contraintes en petits morceaux. Changez une colonne (ou une table) par release. Gardez les migrations petites pour que les échecs soient faciles à diagnostiquer.
- Activez la contrainte, puis surveillez. Ajoutez
NOT NULL,CHECK,FOREIGN KEYou des règles d’unicité seulement après que vos données et comportements applicatifs soient prêts.
Après le déploiement, attendez-vous à quelques échecs. C’est souvent le signe que le système attrape enfin des problèmes qu’il cachait auparavant.
Ajoutez une surveillance simple autour des nouveaux points de défaillance : comptez les erreurs de validation, suivez les erreurs de contraintes BD et journalisez le payload (sans données sensibles) pour voir ce qui manque et d’où il vient. Par exemple, si vous rendez users.email non null, surveillez les pics provenant d’un chemin d’inscription spécifique ou d’une ancienne build mobile.
Ayez un plan de rollback pour les migrations qui échouent en production :
- Sachez comment annuler la contrainte (ou désactiver la vérification) rapidement.
- Gardez un script prêt pour relancer le backfill en plus petits lots.
- Assurez-vous que votre app peut gérer l’ancien et le nouveau schéma pendant un court laps de temps.
Backfills : corriger les lignes existantes sans casser les utilisateurs
Un backfill est un update planifié qui remplit les valeurs manquantes pour des lignes déjà dans la base. Il est essentiel car ajouter un NOT NULL (ou rendre une colonne requise dans votre app) échouera si les anciennes lignes ont encore des nulls. Les données seed semblent souvent parfaites. Les données réelles le sont rarement.
Avant de toucher quoi que ce soit, décidez quelle doit être la valeur correcte pour les champs manquants. Parfois un placeholder sûr suffit (comme "Unknown" pour un label d’affichage), tant que l’app le traite clairement. D’autres fois, vous avez besoin d’une vraie valeur dérivée. Par exemple, si users.timezone est manquant, vous pouvez la dériver à partir du timezone le plus fréquent dans l’organisation de l’utilisateur, ou à partir d’une région d’inscription enregistrée si vous la stockez.
Les placeholders font avancer les choses, mais ils peuvent masquer des problèmes si vous choisissez des valeurs qui paraissent réelles. Un mauvais placeholder peut fausser les tableaux de bord ou déclencher des emails avec de mauvais noms. En cas de doute, utilisez une valeur manifestement “remplie” ou ajoutez un flag séparé comme profile_incomplete = true pour la retrouver et la corriger plus tard.
Si la table est volumineuse, backfillez par lots. Les petits lots réduisent le temps de verrouillage et baissent le risque de ralentir l’app pendant les pics :
- Mettez à jour un nombre limité de lignes par exécution (par exemple 1 000 à 10 000)
- Exécutez pendant les heures creuses et arrêtez si les taux d’erreur ou la charge DB augmentent
- Rendez chaque lot idempotent (sécurisé à réexécuter)
Journalisez ce qui a changé. Le debug est plus simple quand vous pouvez répondre : “Quelles lignes ont été touchées, quand et par quelle version du script ?” Au minimum, enregistrez les comptes et les IDs. Si les données sont sensibles, loggez seulement les IDs et un résumé.
Considérez les backfills comme deux choses : un script unique et un job répétable. Le script unique corrige les nulls d’aujourd’hui. Le job répétable attrape les données qui arrivent en retard (anciens workers, imports, retries), jusqu’à ce que vous soyez sûr que tout fait respecter les nouvelles règles.
Exemple : un flux d’inscription qui plante avec des profils incomplets
Un bug courant “ça marche avec des données seed” ressemble à ceci : un utilisateur s’inscrit, une ligne account est créée, mais la ligne profile n’est que partiellement remplie. Dans les données de test, chaque utilisateur a un profil complet, donc personne ne remarque.
Scénario réaliste : votre inscription crée users puis profiles. Le profil devrait avoir display_name et status, mais le code saute parfois display_name (par exemple l’utilisateur ferme l’onglet en plein onboarding). Plus tard, l’app affiche un header de dashboard qui suppose que le nom existe.
Le crash apparaît souvent comme :
- Une erreur serveur lors du rendu d’une page (tentative de formater ou majuscule un nom null)
- Une réponse API cassée (un serializer attend une chaîne, reçoit null)
- Une erreur front-end confuse (un composant lit
profile.display_name.lengthet plante)
Pour prévenir les crashs, la base et l’app doivent s’accorder sur les mêmes règles, et les anciennes lignes doivent aussi respecter ces règles.
Plan de correction simple
Commencez par décider ce que signifie “sûr” pour une inscription incomplète. Appliquez ensuite la même intention à quatre endroits :
- Contrainte BD : exiger une ligne profile pour chaque user, et rendre
statusNOT NULL. - Défaut : définir
statuspar défaut sur quelque chose commeincomplete. - Validation applicative : si
display_nameest requis pour terminer l’onboarding, bloquer le bouton “Continuer” jusqu’à ce qu’il soit fourni, avec un message clair. - Backfill : mettre à jour les utilisateurs existants ayant
statusnull (ou des profiles manquants) pour qu’ils correspondent aux nouvelles règles.
Après la correction, l’expérience s’améliore. Au lieu d’un crash sur le dashboard, l’utilisateur voit une invite amicale “Finissez la configuration de votre profil” et un court formulaire pour ajouter le nom manquant. Votre API reste prévisible et le support reçoit moins de rapports “ça marchait hier”.
Erreurs courantes qui font revenir les crashs liés aux nulls
La plupart des équipes suivent le même schéma : l’app semble correcte avec des données seed, puis un utilisateur réel saute un champ, un import laisse des vides ou une intégration envoie des payloads partiels. Pour arrêter définitivement les crashs, il faut de la cohérence entre la base, l’app et les données existantes.
Une erreur fréquente est d’ajouter une contrainte NOT NULL trop tôt. Dans une app en production, vous avez presque toujours des lignes existantes qui ne correspondent pas à la nouvelle règle. Le résultat est une migration qui échoue, ou un correctif précipité qui retire la contrainte et vous remet là où vous étiez.
Un autre problème subtil est d’utiliser des chaînes vides comme substitut pour des données manquantes sans définir ce que cela signifie. Une chaîne vide peut vouloir dire “inconnu”, “non fourni” ou “intentionnellement vide”. Si personne ne le définit, le filtrage et le reporting deviennent compliqués, et vous avez toujours des crashs quand le code suppose que la valeur a du sens.
Des patterns qui font revenir les problèmes :
- Validation uniquement côté navigateur pendant que les appels API, scripts et webhooks peuvent encore envoyer de mauvaises charges
- Valeurs par défaut qui semblent utiles mais cassent ensuite la facturation, la fiscalité ou l’analytics
- Backfills qui ne couvrent que le chemin heureux, laissant des lignes rares intactes jusqu’à ce qu’un utilisateur les rencontre
- Tests qui ne couvrent que des entrées parfaites
- Données seed trop propres qui n’incluent jamais de nulls, de champs vides ou de relations manquantes
Les valeurs par défaut “magiques” méritent une attention supplémentaire. Si vous définissez created_at à “now” pour des lignes historiques manquantes, les graphiques de rétention seront faux. Si vous par défaut un prix manquant à 0, vous risquez de donner des fonctionnalités payantes gratuitement ou de fausser les revenus. Les défauts doivent sécuriser l’app, pas inventer des vérités métier.
Petit contrôle de réalité : un flux d’inscription peut autoriser profile.bio comme optionnel, mais plus tard un template d’email de bienvenue suppose que la bio est présente et plante. Ce n’est pas seulement un problème de base. C’est un problème de contrat entre vos règles, votre code et vos templates.
Si vous avez hérité d’un codebase généré par IA (outils comme Lovable, Bolt, v0, Cursor, ou Replit), ces erreurs apparaissent souvent ensemble : validation serveur faible, gestion incohérente des nulls et migrations jamais testées sur des données sales.
Checklist rapide et prochaines étapes
Si vous voulez prévenir les crashs liés aux valeurs nulles, traitez les données manquantes comme normales, pas rares. Une bonne correction est généralement ciblée : règles claires, quelques contraintes et un backfill réfléchi.
Checklist rapide
Commencez par écrire ce qui doit exister et ce qui peut être vide. Puis assurez-vous que la même règle est appliquée en base et dans l’app.
- Listez les champs vraiment requis pour chaque table (et chaque requête API), et définissez ce que signifie “manquant” (NULL vs chaîne vide).
- Choisissez des défauts seulement là où ils ont du sens (par ex.
status = 'draft'), et évitez les défauts qui cachent des flux cassés. - Confirmez où la validation a lieu (formulaire, API, job) et assurez-vous que les erreurs sont claires pour les utilisateurs.
- Planifiez un backfill pour les lignes existantes avant d’activer de nouveaux
NOT NULL. - Désignez un responsable pour les règles (le produit décide ce qui est autorisé ; l’ingénierie l’applique) et consignez les règles en un seul endroit.
Faites ensuite une passe rapide “mauvaises entrées”. Cela attrape les chemins surprises qui n’existaient jamais avec des données seed.
Tests rapides pour données manquantes
Exécutez ces vérifications sur les parcours utilisateurs principaux : inscription, checkout, édition de profil, imports et écrans admin ainsi que les endpoints API publics.
- Soumettez des formulaires avec des champs optionnels manquants, et avec des champs requis vides.
- Rejouez un import avec quelques colonnes vides et des espaces bizarres.
- Appelez des endpoints clés avec des clés JSON manquantes (pas seulement des clés à null).
- Chargez des pages pour des comptes anciens qui peuvent avoir des lignes incomplètes.
Pour empêcher la réapparition des problèmes, ajoutez un petit lot de tests “null et vide” pour vos endpoints et jobs critiques. Même 5–10 cas peuvent empêcher que de futurs changements réintroduisent des crashs.
Si vous traitez un code généré par IA qui se casse quand des données réelles arrivent, FixMyMess (fixmymess.ai) peut commencer par un audit de code gratuit pour trouver les chemins nuls risqués, puis appliquer des réparations ciblées comme des rollouts de contraintes, corrections de validation et backfills pour rendre l’app prête pour la production.
Questions Fréquentes
Pourquoi mon application fonctionne avec des données de seed mais plante en production ?
Les données de seed sont généralement choisies à la main pour être complètes et cohérentes, donc votre code ne voit que le « chemin heureux ». Les utilisateurs réels, les imports et les intégrations introduisent vite des champs manquants, des chaînes vides et des enregistrements partiels que votre code n’a pas été conçu pour gérer.
Quelle est la première étape pour arrêter les crashs liés aux valeurs nulles ?
Commencez par rédiger des règles en anglais simple pour chaque champ : obligatoire, optionnel, ou obligatoire seulement à certaines étapes (par exemple « avant de facturer une carte »). L’objectif est que l’application et la base de données s’accordent sur ce qui peut être manquant et quand.
Une chaîne vide, c’est à peu près la même chose que NULL ?
NULL signifie généralement « aucune valeur du tout », tandis qu’une chaîne vide est quand même une valeur et se comporte souvent différemment dans les requêtes, validations et affichages. Choisissez une seule signification de « manquant » par champ et normalisez l’entrée pour éviter d’avoir les deux formes mélangées.
Quand devrais-je ajouter des contraintes NOT NULL ?
Utilisez NOT NULL pour les champs dont le produit ne peut vraiment pas se passer, comme les identifiants de propriété, les identifiants de connexion ou les timestamps requis. Si vous n’êtes pas sûr, traitez-le d’abord comme optionnel, implémentez la gestion côté application, et n’appliquez NOT NULL qu’une fois que tous les chemins d’écriture sont couverts.
Quel type de problèmes les contraintes CHECK empêchent-elles ?
Les contraintes CHECK servent à des règles simples qui empêchent des valeurs inutilisables même si elles ne sont pas nulles : quantités négatives, plages de dates impossibles, ou texte « vide mais pas null ». Elles évitent les données qui semblent remplies mais qui cassent la facturation, les rapports ou l’UI.
Quelles valeurs par défaut sont sûres, et lesquelles sont dangereuses ?
Les valeurs par défaut conviennent aux champs qui doivent toujours exister mais ne doivent pas dépendre du client, comme les timestamps, les statuts initiaux ou les compteurs. Évitez les valeurs par défaut qui inventent la vérité métier (par exemple fixer un prix manquant à 0 ou assigner un propriétaire factice), car elles masquent les bugs et polluent vos données.
Où doit vivre la validation pour empêcher les nulls de s’infiltrer ?
Validez côté serveur pour chaque écriture, même si l’UI valide, car des scripts, webhooks, imports et anciennes versions clientes peuvent contourner le navigateur. Retournez une erreur 400 claire liée au champ afin d’échouer vite plutôt que d’enregistrer des lignes cassées et de planter ensuite.
Comment ajouter des contraintes en toute sécurité dans une application en production ?
Auditez d’abord les nulls existants, décidez la règle par colonne, backfillez les anciennes lignes pour qu’elles correspondent à la règle, puis ajoutez les contraintes en petites releases. Si vous activez une contrainte avant d’avoir nettoyé les données, la migration échouera souvent ou forcera un rollback précipité.
Qu’est-ce qu’un backfill, et pourquoi en ai-je besoin avant d’ajouter NOT NULL ?
Un backfill met à jour les lignes existantes qui violent vos nouvelles règles afin que vous puissiez appliquer les contraintes de façon fiable. Utilisez des valeurs dérivées correctes quand c’est possible ; si vous devez utiliser des placeholders, faites-les clairement « incomplets » pour qu’on ne les prenne pas pour des données réelles plus tard.
Pourquoi les prototypes générés par IA sont-ils particulièrement sujets aux crashs liés aux données nulles, et que puis-je faire ?
Les prototypes générés par IA supposent souvent des entrées parfaites et manquent d’une validation serveur cohérente, de contraintes de schéma et de valeurs par défaut sûres, donc les données réelles provoquent rapidement des crashs. Si vous avez hérité d’une appli générée par IA, FixMyMess peut commencer par un audit de code gratuit, puis appliquer des réparations ciblées (déploiement de contraintes, corrections de validation et backfills) pour rendre l’app prête pour la production en quelques jours, souvent en 48–72 heures.