Solutions — série 10-1 (choisir et cadrer un projet)

Rappel de la règle d'or : on n'ouvre ce fichier qu'après avoir terminé (ou sérieusement séché sur) la série. Particularité de cette série : il n'y a pas UNE bonne réponse — compare la structure de ton cadrage (testabilité des exigences, présence du hors-périmètre, taille des issues) plutôt que le contenu mot à mot.


Exercice facile a — le crible des trois sujets

Raisonnement — On passe chaque sujet aux quatre critères, mécaniquement, sans se laisser séduire ni effrayer par le sujet lui-même. Le verdict découle des critères, pas de l'envie.

Solution

1. « Clone de Spotify avec lecture audio et recommandations »

Utile pour toi ?       Douteux — Spotify existe déjà, tu ne l'utiliseras pas.
Trois semaines ?       NON, ni trois mois — lecture audio, catalogue, reco.
Couvert par 00–09 ?    NON — audio temps réel, algorithmes de recommandation,
                       probablement une GUI : rien de tout ça n'a été vu.
Un peu peur ?          Oui — mais une terreur, pas une brume.
VERDICT : à écarter. Même dégonflé, le cœur du sujet (jouer de la musique)
est hors périmètre technique. Version sauvable éventuelle : un gestionnaire
de playlists en CLI qui organise des fichiers… mais c'est un autre projet.

2. « Gestionnaire de flashcards à répétition espacée, en CLI »

Utile pour toi ?       OUI — réviser Python avec, précisément (boucle vertueuse).
Trois semaines ?       OUI — add/review/stats + un JSON, c'est calibré.
Couvert par 00–09 ?    OUI — dicts, dates, JSON, argparse, pytest. Tout est vu.
Un peu peur ?          OUI — l'algorithme d'espacement (quand remontrer une
                       carte ?) est une vraie zone de brume, mais bornée.
VERDICT : bon calibre, quasi exemplaire. C'est d'ailleurs une des idées de la
fiche 12.

3. « Un script qui renomme des fichiers »

Utile pour toi ?       Peut-être, ponctuellement.
Trois semaines ?       Non — trois HEURES. C'est le défaut inverse.
Couvert par 00–09 ?    Oui, intégralement (niveau 05 suffit).
Un peu peur ?          NON — aucune zone de brume, donc aucun apprentissage.
VERDICT : à regonfler ou à écarter comme projet FINAL. Version regonflée
valable : un outil de rangement/renommage configurable avec règles, mode
--dry-run, undo, et rapport — là il y a trois semaines et un peu de peur.

Pourquoi ça marche — Les quatre critères forment un filtre complet : motivation (utile), faisabilité calendaire (trois semaines), faisabilité technique (00–09), apprentissage (peur). Un sujet qui rate UN critère échoue d'une manière prévisible : sans utilité on abandonne en semaine 2, sans calibrage on abandonne à 30 %, sans couverture technique on passe le projet dans des tutoriels, sans peur on n'apprend rien.

Erreur classique sur cet exercice — Écarter le sujet 3 sans voir qu'il a le défaut INVERSE (l'énoncé le signalait) : le crible sert aussi à détecter les sujets trop petits. L'autre erreur : « sauver » le sujet 1 par attachement (« mais en simplifiant beaucoup… ») — quand le CŒUR du sujet est hors périmètre technique, dégonfler produit un projet qui n'a plus rien à voir avec l'envie initiale ; autant choisir franchement autre chose.

Variante plus difficile — Passe au crible trois sujets de TON cru, dont au moins un dont tu as vraiment envie. C'est plus dur : on triche avec les critères quand le sujet nous plaît. Astuce : rédige le verdict comme si le sujet était proposé par quelqu'un d'autre.


Exercice facile b — rendre les exigences testables

Raisonnement — Pour chaque exigence floue, on cherche le comportement observable qui se cache derrière, et on le formule en « quand je fais X, il se passe Y ». S'il y a PLUSIEURS comportements derrière le flou, c'est plusieurs exigences.

Solution

FLOU : « L'outil doit être facile à utiliser »
TESTABLE :
  - « `--help` (global et par sous-commande) documente chaque argument
    avec un exemple. »
  - « Toute erreur d'utilisation affiche un message en une ligne indiquant
    la forme attendue (jamais un traceback). »

FLOU : « Les données sont sauvegardées »
TESTABLE :
  - « Après `add 12.50 courses`, relancer le programme et taper `list`
    affiche la dépense : les données survivent d'un lancement à l'autre. »
  - « Le fichier de données est créé automatiquement au premier lancement
    s'il n'existe pas. »

FLOU : « Le programme gère les mauvaises entrées »
TESTABLE :
  - « `add abc courses` affiche "montant invalide : abc" et ne modifie pas
    le fichier de données. »
  - « `add -5 courses` refuse le montant négatif avec un message clair. »
  - « `report 2026-13` refuse le mois invalide avec un message clair. »

Pourquoi ça marche — Chaque version testable peut devenir un test pytest presque mot à mot (def test_add_rejects_negative_amount():). C'est le critère : si le test s'écrit tout seul, l'exigence est bonne. On remarque aussi que « facile à utiliser » et « gère les mauvaises entrées » se recouvrent : le travail de reformulation révèle les doublons du cahier des charges.

Erreur classique sur cet exercice — Reformuler en restant abstrait : « l'outil valide les entrées utilisateur » — c'est plus propre, mais toujours pas testable (valider comment ? lesquelles ? avec quel résultat ?). Le test du « quand X alors Y » démasque ces fausses reformulations : il manque le X concret.

Variante plus difficile — Reformule « le code doit être maintenable » en exigences vérifiables. (Piste : ce n'est pas une exigence produit mais une exigence de processus — « chaque fonction du cœur a un test », « aucune fonction ne dépasse 30 lignes », « le module storage ne fait aucun affichage ». Certaines équipes les mettent dans un fichier à part : conventions vs specs.)


Exercice facile c — trier les issues

Raisonnement — Deux règles de jugement : (1) formulée par un résultat observable ? (2) calibrée à une session maximum ?

Solution

« améliorer le code »
  MAUVAISE (les deux règles violées : rien d'observable, taille infinie).
  Correction impossible telle quelle — il faut la remplacer par des tâches
  concrètes : « extraire la logique CSV de cli.py vers storage.py » (et
  encore : quel résultat observable ? → « cli.py n'importe plus csv ;
  pytest reste vert »).

« `delete 3` supprime la dépense n°3 et l'affiche »
  BONNE : résultat observable, une session, testable.

« implémenter la classe Storage »
  MAUVAISE (formulée par l'implémentation). Le jour venu, on ne sait ni
  pourquoi ni quand c'est fini. Correction : « les dépenses sont relues
  depuis le CSV au démarrage et list les affiche » — la classe Storage
  sera peut-être le moyen, c'est le code qui décidera.

« `report` sans argument affiche le mois courant »
  BONNE : petite, observable, testable. (Bonus : c'est typiquement une
  issue de jalon v0.2 — du confort, pas du cœur.)

Pourquoi ça marche — Une issue formulée par le résultat reste compréhensible des jours plus tard, se vérifie en lançant le programme, et laisse la liberté d'implémentation. Une issue calibrée à une session donne le rythme « petit, fini, mergé » du projet final.

Erreur classique sur cet exercice — Considérer « implémenter la classe Storage » comme bonne « parce qu'elle est précise ». Elle est précise sur le COMMENT et muette sur le POURQUOI — c'est exactement l'inversion à détecter. La précision d'une issue se mesure sur le résultat, pas sur la technique.

Variante plus difficile — Prends la v0.1 de ton propre projet final et audite tes issues avec ces deux règles. Compte combien survivent telles quelles ; moins de la moitié est un score normal au premier jet.


Exercice moyen a — SPECS.md complet : le suivi d'habitudes

Raisonnement — On suit le modèle de l'exemple 3 de la leçon, section par section. Le sujet imposé (« cocher une habitude, voir la série en cours, stockage JSON ») donne le cœur ; le travail est de le border : exigences testables (dont les entrées invalides — le piège annoncé), hors-périmètre fourni, « fini » binaire.

Solution — un cahier des charges de référence, complet :

# SPECS — habitude v1

## Problème
Je veux tenir 2-3 habitudes quotidiennes (révision Python, sport, journal)
et je n'ai aucun suivi : les séries se cassent sans que je m'en rende compte.

## Utilisateur
Moi, dans un terminal, 30 secondes le soir.

## Exigences v1 (testables)
1. `add <nom>` crée une habitude ; `add` d'un nom déjà existant affiche
   « habit already exists » et ne crée pas de doublon.
2. `done <nom>` coche l'habitude pour AUJOURD'HUI ; cocher deux fois le
   même jour est sans effet (pas de double comptage, message informatif).
3. `done` d'une habitude inconnue affiche la liste des habitudes existantes.
4. `streak <nom>` affiche la série en cours : nombre de jours consécutifs
   cochés jusqu'à aujourd'hui (0 si hier n'est pas coché ni aujourd'hui).
5. `list` affiche chaque habitude avec sa série en cours, triées par série
   décroissante.
6. Les données survivent d'un lancement à l'autre (habits.json à côté du
   programme) ; le fichier est créé au premier lancement s'il manque.
7. Un habits.json corrompu (JSON invalide) affiche un message clair et
   n'écrase PAS le fichier — aucun traceback.
8. Aucune entrée utilisateur essayée ne produit de traceback.

## Hors périmètre v1
- Rappels/notifications (V2 ? nécessiterait un démon — probablement jamais)
- Habitudes hebdomadaires ou « 3 fois par semaine » (V2 — quotidien d'abord)
- Statistiques historiques, graphiques (V2 ?)
- Rattraper un jour oublié (`done --date`) (V2 — tentant, mais ouvre la
  triche ; à décider avec l'usage)
- Multi-utilisateurs, synchro (non)

## Définition de « fini »
Exigences 1–8 implémentées, pytest vert (dont un test par entrée invalide
des exigences 1, 3, 7), README complet, tag v1.0.

Pourquoi ça marche — Chaque exigence est un « quand X alors Y » (ou peut s'y réécrire trivialement) ; trois exigences sur huit couvrent les entrées invalides (le piège de l'énoncé) ; le hors-périmètre a cinq lignes MOTIVÉES — noter POURQUOI on écarte (démon, triche…) est ce qui empêchera de céder plus tard. L'exigence 4 montre autre chose : écrire les specs force à définir les cas limites (que vaut une série si hier n'est pas coché ?) AVANT de coder — c'est là que le cadrage paie.

Erreur classique sur cet exercice — Oublier le cas « fichier corrompu » (exigence 7) : les exigences pensent au chemin heureux et aux mauvais ARGUMENTS, rarement aux mauvaises DONNÉES. Autre classique : une définition de « fini » qui reprend « quand tout marche bien » — non binaire, donc inutilisable. La bonne renvoie aux numéros d'exigences.

Variante plus difficile — Ajoute l'exigence « undo <nom> décoche aujourd'hui » et regarde ce qu'elle coûte : nouvelle commande, nouveau cas limite (décocher un jour non coché ?), nouveaux tests. Estimer le coût RÉEL d'une exigence « toute simple », c'est l'exercice que tu referas à chaque tentation du projet final.


Exercice moyen b — roadmap et issues du suivi d'habitudes

Raisonnement — v0.1 = le plus petit chemin qui rend service (peut-on cocher et voir sa série ? alors c'est utilisable) ; v0.2 = confort et robustesse ; v1.0 = finition. Puis chaque jalon se découpe en issues d'une session, formulées par résultat.

Solution

## ROADMAP — habitude

- v0.1 — le cœur utilisable : add, done, streak, stockage JSON.
         (dès ce jalon, je m'en sers tous les soirs)
- v0.2 — confort : list triée, messages d'erreur soignés, double-done
         sans effet, habitude inconnue → suggestions.
- v1.0 — fini : JSON corrompu géré, chasse aux tracebacks, README,
         tag v1.0.

## ISSUES — v0.1 (une session chacune)

#1 `add lecture` crée l'habitude dans habits.json (créé s'il manque) ;
   `list` brut l'affiche.
#2 `add` d'un nom existant affiche « habit already exists », sans doublon.
#3 `done lecture` enregistre la date du jour dans habits.json.
#4 `streak lecture` affiche la série en cours (0 si rien hier ni
   aujourd'hui ; règle de l'exigence 4).
#5 squelette pytest : tests de add/done/streak sur un fichier JSON
   temporaire (tmp_path).

Pourquoi ça marche — La v0.1 rend déjà service (critère de la leçon, section 5 exemple 4) : quatre commandes, zéro confort, mais l'outil vit. Chaque issue est observable et tient dans une session ; l'issue #5 rappelle que les tests sont un livrable du JALON, pas de la fin du projet. (⏩ tmp_path : la fixture pytest vue au niveau 08 — les tests ne touchent jamais le vrai habits.json.)

Erreur classique sur cet exercice — Mettre streak en v0.2 « parce que c'est le plus dur » : sans la série, l'outil ne motive pas, donc on ne s'en sert pas, donc pas de revue de mi-parcours honnête. Le jalon v0.1 se décide sur l'USAGE (qu'est-ce qui rend service ?), pas sur la difficulté. L'autre classique : une issue « mettre en place le stockage JSON » — implémentation pure, elle est ici fusionnée dans #1 dont elle est le moyen.

Variante plus difficile — Découpe la v0.2 et la v1.0 en issues aussi. Difficulté réelle : les issues de finition (« chasse aux tracebacks ») résistent au format résultat-observable — une formulation qui marche : « les 12 entrées absurdes de ma liste d'essais n'affichent aucun traceback » (la liste d'essais devient un artefact du projet).


Exercice difficile a — le cadrage de TON projet final

Raisonnement — Pas de solution type : c'est ton sujet. Voici la grille de correction à appliquer à ton propre dossier, section par section — c'est elle, la « solution ».

Solution — la grille de relecture :

SUJET
  □ Les quatre critères passés par écrit (pas de tête), verdict argumenté.
  □ Le critère « trois semaines » vérifié avec la règle ×2.

SPECS.md
  □ Problème et utilisateur : 3 lignes max, concrets.
  □ 5 à 10 exigences, toutes au format « quand X alors Y » (teste-les une
    par une : le test pytest s'écrit-il tout seul ?).
  □ Au moins 2 exigences sur les entrées invalides, 1 sur les données
    corrompues/absentes.
  □ Hors-périmètre : 4 lignes minimum, chacune motivée.
  □ Définition de « fini » binaire, renvoyant aux numéros d'exigences.

ROADMAP
  □ v0.1 utilisable pour de vrai (test : « le soir du jalon, je m'en sers »).
  □ Trois jalons, pas cinq.

ISSUES
  □ La v0.1 entièrement découpée, 3 à 6 issues.
  □ Chaque issue : résultat observable + une session max.
  □ Une issue « squelette + premier test » existe.

Pourquoi ça marche — La grille reprend chaque piège de la section 6 de la leçon sous forme de case à cocher : elle transforme la relecture (vague) en audit (binaire). La relecture différée de trois jours demandée par le mini-projet est ce qui la rend efficace : à froid, les exigences floues et les issues gonflées se voient immédiatement.

Erreur classique sur cet exercice — Le faire en une session. Le cadrage d'un projet de trois semaines vaut deux à trois sessions (la leçon l'annonce) ; un cadrage expédié se paie en semaine 2, avec intérêts. Deuxième classique : garder secret un doute sur le calibre (« ça ira ») — le doute se traite MAINTENANT, en coupant, pas au jour 12.

Variante plus difficile — Fais évaluer ton cadrage par quelqu'un d'autre (ou par Claude, en lui donnant la grille ci-dessus et ton SPECS.md, au gabarit de question de la leçon 10-3). Consigne : il ne doit juger que la STRUCTURE, pas le sujet. Encaisse les remarques par écrit dans le journal avant de décider lesquelles appliquer.