Retour à la leçon·Leçon 6 sur 8·Un modèle, plusieurs sorties
Une chaîne qui échoue vaut mieux qu'une chaîne qui devine
Le même diaporama que les téléchargements, rendu sous forme de page. Lancez le diaporama pour le présenter en plein écran — les flèches ou un clic avancent d'une diapositive, Échap quitte.
Ce que couvre cette leçon
- La défaillance qui n'a pas de message d'erreur
- Sept vérifications, chacune avec une défaillance réelle derrière
- Échouez au point de défaillance, non à la fin
- Ce que fait cette plateforme
- La règle à retenir
- Rapportez-le en entier
- La suite
Notes du présentateur
L'export amont gagne une colonne, en perd une, change un code de « yes » à « Y », ou arrive avec la moitié des lignes. Une chaîne qui continue produit un nombre faux et plausible. Sept vérifications l'arrêtent, et chacune a une défaillance réelle derrière elle.La défaillance qui n'a pas de message d'erreur
- Rien n'a échoué — Le graphique est tracé, le pourcentage est plausible, le fichier est daté d'aujourd'hui, et le nombre…
- C'est le mode de défaillance pour lequel cette leçon existe — et il est bien plus courant qu'un plantage
Notes du présentateur
L'export mensuel arrive. Une colonne qui disaittruedit maintenantY. Votre conversion booléenne transforme chacune d'elles en valeur manquante, le dénominateur perd 30 %, et la chaîne s'exécute jusqu'au bout et produit un rapport. Rien n'a échoué. Le graphique est tracé, le pourcentage est plausible, le fichier est daté d'aujourd'hui, et le nombre est faux. C'est le mode de défaillance pour lequel cette leçon existe, et il est bien plus courant qu'un plantage. Un plantage se corrige le matin même.Sept vérifications, chacune avec une défaillance réelle derrière
- Une : les colonnes attendues sont présentes
Notes du présentateur
Chacune correspond à un défaut documenté dans les jeux de données de cette plateforme. Une : les colonnes attendues sont présentes.Sept vérifications, chacune avec une défaillance réelle derrière — En Python
REQUIRED = {"household_id", "district", "water_source", "round_trip_minutes"} missing = REQUIRED - set(survey.columns) if missing: raise ValueError(f"Export is missing columns: {sorted(missing)}")Sept vérifications, chacune avec une défaillance réelle derrière — En R
stopifnot(all(required %in% names(survey)))Sept vérifications, chacune avec une défaillance réelle derrière
- Deux : le nombre de lignes est dans la plage attendue
Notes du présentateur
Deux : le nombre de lignes est dans la plage attendue.Sept vérifications, chacune avec une défaillance réelle derrière — En Python
if not 2_000 <= len(survey) <= 3_000: raise ValueError(f"Expected 2,000-3,000 households, got {len(survey):,}")Sept vérifications, chacune avec une défaillance réelle derrière
- La moitié d'un export est la défaillance silencieuse la plus courante — Un téléchargement tronqué, un filtre resté…
- Trois : les codes sont les codes que vous connaissez
Notes du présentateur
La moitié d'un export est la défaillance silencieuse la plus courante. Un téléchargement tronqué, un filtre resté actif, une plage de dates décalée d'un mois — tous produisent un fichier valide avec trop peu de lignes. Trois : les codes sont les codes que vous connaissez.Sept vérifications, chacune avec une défaillance réelle derrière — En Python
KNOWN = {"piped-into-dwelling", "piped-into-yard", "public-tap", "borehole", "protected-well", "protected-spring", "unprotected-well", "unprotected-spring", "surface-water", "tanker-truck", "rainwater"} unknown = set(survey["water_source"].dropna()) - KNOWN if unknown: raise ValueError(f"Unknown water_source values: {sorted(unknown)}")Sept vérifications, chacune avec une défaillance réelle derrière — En R
setdiff(unique(survey$water_source), known)Sept vérifications, chacune avec une défaillance réelle derrière
- Un nouveau code est une décision, non une donnée — Quelqu'un a ajouté une option au formulaire et l'analyse doit…
- Quatre : l'identifiant est unique là où il doit l'être
Notes du présentateur
Un nouveau code est une décision, non une donnée. Quelqu'un a ajouté une option au formulaire et l'analyse doit décider où elle va — la faire tomber discrètement dans « autre » revient à laisser un.fillna()prendre la décision. Quatre : l'identifiant est unique là où il doit l'être.Sept vérifications, chacune avec une défaillance réelle derrière — En Python
duplicates = survey["household_id"].duplicated().sum() if duplicates: raise ValueError(f"{duplicates} duplicate household_id values")Sept vérifications, chacune avec une défaillance réelle derrière
- Le registre scolaire de cette plateforme a exactement ce défaut — deux élèves y figurent deux fois après un transfert…
- Cinq : les valeurs manquantes sont là où vous les attendez
Notes du présentateur
Le registre scolaire de cette plateforme a exactement ce défaut — deux élèves y figurent deux fois après un transfert jamais radié — et une jointure nue duplique leurs lignes. Une vérification l'aurait attrapé à la jointure plutôt que dans un coefficient. Cinq : les valeurs manquantes sont là où vous les attendez.Sept vérifications, chacune avec une défaillance réelle derrière — En Python
completeness = survey.notna().mean() if completeness["district"] < 0.99: raise ValueError(f"district is {completeness['district']:.1%} complete")Sept vérifications, chacune avec une défaillance réelle derrière
- Six : les nombres sont dans une plage possible
Notes du présentateur
Six : les nombres sont dans une plage possible.Sept vérifications, chacune avec une défaillance réelle derrière — En Python
implausible = survey[(survey["litres_per_person_day"] < 0) | (survey["litres_per_person_day"] > 200)] if len(implausible) > 20: raise ValueError(f"{len(implausible)} implausible litres values")Sept vérifications, chacune avec une défaillance réelle derrière
- Notez le seuil plutôt qu'une tolérance nulle — Onze ménages avec une erreur d'unité est un défaut documenté que cette…
- Sept : la sortie est celle que vous avez déclarée
Notes du présentateur
Notez le seuil plutôt qu'une tolérance nulle. Onze ménages avec une erreur d'unité est un défaut documenté que cette analyse traite ; deux cents est un problème nouveau. Sept : la sortie est celle que vous avez déclarée.Sept vérifications, chacune avec une défaillance réelle derrière — En Python
assert summary["n"].sum() == len(survey), "rows lost between input and summary"Sept vérifications, chacune avec une défaillance réelle derrière
- Un nombre de lignes qui change au travers d'une jointure est l'assertion la plus utile de l'analyse de programme —…
Notes du présentateur
Un nombre de lignes qui change au travers d'une jointure est l'assertion la plus utile de l'analyse de programme, parce qu'une jointure interne qui écarte un tiers des données ressemble exactement à une jointure interne qui n'en écarte aucune.Échouez au point de défaillance, non à la fin — En Python
def load_survey(path: pathlib.Path) -> pd.DataFrame: survey = pd.read_csv(path) check_columns(survey) check_rows(survey) check_codes(survey) return survey # nothing downstream runs on a bad fileÉchouez au point de défaillance, non à la fin — En R
load_survey <- function(path) { survey <- readr::read_csv(path) check_columns(survey); check_rows(survey); check_codes(survey) survey }Échouez au point de défaillance, non à la fin
- Vérifiez à la frontière — là où les données entrent, et après chaque jointure — Une vérification en fin de chaîne vous…
- Levez une erreur, n'avertissez pas — Un avertissement dans un journal que personne ne lit équivaut à aucune…
Notes du présentateur
Vérifiez à la frontière — là où les données entrent, et après chaque jointure. Une vérification en fin de chaîne vous dit que quelque chose ne va pas ; une vérification à la frontière vous dit quoi. Levez une erreur, n'avertissez pas. Un avertissement dans un journal que personne ne lit équivaut à aucune vérification, et le journal n'est pas lu précisément les jours chargés où l'export casse.Ce que fait cette plateforme
Vérification Attrape Schéma Zod Un champ manquant ou du mauvais type Références inter-collections Un chemin pointant vers un cours qui n'existe pas Fichiers hors d'un répertoire de langue Une entrée sans langue Parité de traduction Une entrée publiée dans une seule langue Cohérence sujet-secteur Un sujet étiqueté hors de son secteur Synthétique uniquement Un jeu de données non déclaré synthétique Ossature du programme Un cours publié absent de la carte du cursus Notes du présentateur
Sept vérifications font échouerastro build, délibérément, et elles ont la même forme.Ce que fait cette plateforme
- Quatre autres s'exécutent dans
pnpm testplutôt que dans la compilation — parce qu'elles ont besoin denode:fset… - L'une d'elles vérifie une relation que le graphe de références ne peut structurellement pas atteindre — Les règles de…
- Toute règle du type « chaque X a au moins un Y » exige un test de cette forme — Un graphe de références est le mauvais…
Notes du présentateur
Quatre autres s'exécutent danspnpm testplutôt que dans la compilation, parce qu'elles ont besoin denode:fset que la compilation pré-rend dans un worker Cloudflare qui n'en a pas. C'est une contrainte réelle qui a décidé où vivent les vérifications, et elle vaut d'être nommée : placez la vérification là où elle peut s'exécuter, non là où c'est le plus élégant. L'une d'elles vérifie une relation que le graphe de références ne peut structurellement pas atteindre. Les règles de références vérifient qu'un slug déclaré se résout ; elles ne peuvent pas vérifier qu'une entrée est pointée. Un cours pourrait donc être livré sans pratique attachée et chaque barrière resterait verte — d'où l'existence decourse-practice.test.ts, qui compte à rebours depuis chaque cours publié vers le laboratoire et l'exercice qui doivent le nommer. Toute règle du type « chaque X a au moins un Y » exige un test de cette forme. Un graphe de références est le mauvais outil pour cela.- Quatre autres s'exécutent dans
La règle à retenir
- Tout champ nommant un fichier livré exige un drapeau
readyet un test de système de fichiers à côté — Cette… - Un chemin dans un frontmatter est une chaîne de caractères, et rien dans une compilation ne peut dire s'il pointe vers…
Notes du présentateur
Tout champ nommant un fichier livré exige un drapeaureadyet un test de système de fichiers à côté. Cette plateforme l'a appris trois fois : vingt exemples travaillés déclarés et jamais écrits, trente-cinq livrables de projet déclarés et jamais écrits, et un ensemble de chemins de figures qui ne pointaient vers rien. Un chemin dans un frontmatter est une chaîne de caractères, et rien dans une compilation ne peut dire s'il pointe vers quelque chose. Le schéma met doncreadyà false par défaut et un test vérifie que le fichier existe.- Tout champ nommant un fichier livré exige un drapeau
Rapportez-le en entier — Exemple
Pipeline checks The loader validates every raw export before anything downstream runs: required columns present, 2,000-3,000 rows, water_source values within the known set, household_id unique, district at least 99% complete. Implausible litres-per-person values are tolerated up to 20 rows, which is the documented unit-entry defect; above that the run stops. Row counts are asserted across every join. A join that changes the row count stops the pipeline rather than producing a summary. All checks raise rather than warn. The March run stopped on an unknown water_source value ("piped-shared"), which turned out to be a new form option added upstream; it is now mapped explicitly in src/clean.py.Rapportez-le en entier
- La dernière phrase est ce qui rend la section crédible — Une section de vérifications qui n'a jamais rien attrapé est…
Notes du présentateur
La dernière phrase est ce qui rend la section crédible. Une section de vérifications qui n'a jamais rien attrapé est une section de vérifications que personne n'a testée.La suite
- Tout ce qui précède suppose que vous êtes encore là.
Notes du présentateur
Tout ce qui précède suppose que vous êtes encore là. La leçon suivante porte sur le document qui doit fonctionner quand vous n'y êtes plus — écrit pour quelqu'un qui a votre poste et rien de votre contexte.