Aller au contenu
Garder la main
Sommaire
03Chapitre 3·60 min·Intermédiaire

Méthodologie

Ne jamais coder sur une ambiguïté

Le cœur opérationnel : Spec-Driven Development, le cycle Explore → Plan → Code → Verify, et quoi faire quand la session déraille.

Ce que tu sauras faire
  • 01Appliquer le cycle Explore → Plan → Code → Verify sur des cas réels
  • 02Maîtriser le Spec-Driven Development pour les nouvelles features
  • 03Utiliser les fichiers spec.md / plan.md / tasks.md comme source de vérité
  • 04Éviter les pièges de l'implémentation directe sans planification
  • 05Reconnaître les trois façons dont une session déraille, et savoir quoi faire

1. Pourquoi une méthodologie ?

Sans méthode, utiliser l'IA pour coder ressemble à ça :

Sans méthode
  1. Prompt vague
  2. Code généré
  3. Ça ne marche pas
  4. Nouveau prompt
  5. Code différent
  6. Ça marche en apparence
  7. On merge
  8. 3 semaines plus tard : bug en prod

Le même travail, mais cadré, prend une tout autre allure :

Avec méthode
  1. Spec validée
  2. Exploration de l'existant
  3. Plan approuvé
  4. Implémentation atomique
  5. Vérification automatique
  6. Revue humaine
  7. Merge confiant

La différence : tu ne codes jamais sur des ambiguïtés.


2. Le cycle Explore → Plan → Code → Verify

Ce cycle, qu'on abrégera EPCV dans la suite, est issu des bonnes pratiques documentées par Anthropic pour Claude Code, et s'adapte à n'importe quel outil IA.

Phase 1 : EXPLORE (Plan Mode)

Objectif : comprendre l'existant avant de toucher quoi que ce soit.

Règle absolue : en mode Explore, l'IA lit uniquement, n'écrit pas.

Prompt
[MODE ANALYSE — PAS DE CODE] Explore le répertoire src/auth/. Comprends comment les sessions sont gérées et comment le login fonctionne. Identifie également la gestion des variables d'environnement pour les secrets. Livre un rapport avec : 1. Fichiers clés et leur rôle 2. Dépendances entre composants 3. Points d'entrée et de sortie 4. Risques si on modifie l'auth flow

Quand utiliser Explore :

  • Tu modifies du code que tu ne connais pas bien (legacy, écrit par quelqu'un d'autre).
  • La modification touche plusieurs fichiers ou une couche partagée.
  • Le risque de régression est élevé, ou le code n'a pas de tests pour te rattraper.

Quand skipper Explore : quand tu sais déjà ce que ton changement va casser. Une typo dans un message d'erreur, un log de plus, un bump de patch, une valeur de config évidente, un fichier que tu as écrit toi-même il y a cinq minutes. Explorer ne t'apprendrait rien.

Avant de ranger un changement dans cette catégorie, pose-toi la question : si je me trompe, est-ce que je le vois tout de suite ? Tant que tu ne peux pas répondre oui franchement, tu explores, même pour trois lignes.

Sauter Explore ne donne jamais le droit de sauter Verify. L'analyse préalable est facultative sur du vraiment trivial ; la vérification finale (Phase 4) ne l'est pas.


Phase 2 : PLAN

Objectif : obtenir un plan d'implémentation détaillé, validé par un humain, avant d'écrire une seule ligne.

Prompt
Je veux ajouter l'authentification Google OAuth. Sur la base de ton analyse précédente : 1. Quels fichiers doivent changer ? 2. Quel est le flow session OAuth complet ? 3. Quels sont les edge cases (token expiré, compte existant, etc.) ? Génère un plan d'implémentation détaillé en étapes numérotées. Format : Étape | Fichier(s) concerné(s) | Action | Critère de validation Ne génère pas de code encore.

La validation humaine est obligatoire ici. Tu lis le plan, tu valides ou tu renvoies tes corrections en réponse. En Claude Code, reste en plan mode (Shift+Tab) tant que le plan n'est pas bon : l'agent ne touchera à aucun fichier avant que tu sortes du mode.

Questions à te poser avant de valider :

  • Le choix des librairies est-il cohérent avec notre stack ?
  • L'approche architecturale respecte-t-elle nos patterns existants ?
  • Y a-t-il des étapes qui semblent trop grosses (à découper) ?
  • Tous les edge cases sont-ils couverts ?

Phase 3 : CODE

Objectif : implémentation atomique, étape par étape, en suivant le plan validé.

Prompt
Implémente maintenant l'étape 1 du plan : [description étape]. Vérifie ta progression contre le plan. Une fois cette étape terminée, arrête-toi et attends ma validation.

Règles d'implémentation :

  • Une étape du plan = une demande
  • Ne demande jamais "implémente tout le plan" en une fois
  • Valide chaque bloc avant de passer au suivant
  • Si l'IA s'écarte du plan, stoppe et redirige

Phase 4 : VERIFY

Objectif : fournir à l'IA les moyens de vérifier son propre travail. C'est la différence entre du code "qui a l'air bien" et du code qui fonctionne.

Prompt
L'implémentation est terminée. Maintenant, agis en QA Engineer. 1. Lance les tests unitaires : npm run test -- --testPathPattern=auth 2. Lance le linter : npm run lint src/auth/ 3. Génère des tests pour les edge cases non couverts : - Token OAuth expiré - Email déjà associé à un compte local - Provider indisponible (timeout) 4. Prends un screenshot du flow si c'est une feature UI [optionnel] Rapport final : Tests passés | Avertissements | Échecs

La vérification sans les outils ne vaut rien. Donne à l'IA accès aux commandes de test, au linter, au build. C'est là que la qualité se construit.


3. Spec-Driven Development (SDD)

Le SDD est complémentaire au cycle EPCV. Il s'applique en amont, pour les nouvelles features et projets.

Principe

Les specifications sont la source de vérité. Tout le reste est généré depuis elles.

Structure de fichiers SDD

/specs
  ├── feature-auth-oauth.md    → Requirements + User Stories
  ├── plan.md                  → Étapes d'implémentation
  ├── tasks.md                 → Tâches atomiques avec statuts
  └── outcome.md               → Résultats, décisions prises, leçons

Ces fichiers vivent dans le repo Git, versionnés comme du code.

Quand le SDD ne vaut pas son prix

Quatre fichiers pour une feature, c'est un vrai coût : à écrire, à relire, et surtout à maintenir à jour pendant que le code avance. Ce coût se justifie quand quelque chose d'autre le rembourse. Sinon, le cycle EPCV seul fait le travail, et la spec devient un rituel que personne ne relit.

Le SDD est rentable quand au moins un de ces éléments est vrai :

  • Plusieurs personnes doivent s'accorder avant de coder. La spec sert alors de contrat, et c'est son meilleur usage.
  • Le travail va dépasser une session. Ce qui n'est pas écrit sera reconstitué de mémoire, mal, trois jours plus tard.
  • Les edge cases sont l'essentiel du travail. Auth, facturation, permissions, migrations : le code est court, ce sont les cas limites qui coûtent, et les lister en amont est ce qui évite d'en découvrir la moitié en production.
  • Quelqu'un devra comprendre pourquoi, plus tard. La section « décisions techniques » d'une spec vaut souvent plus que tout le reste.

Si rien de tout ça n'est vrai — un bug isolé, une feature que tu tiens entièrement dans ta tête, un travail d'une heure sur du code que tu connais — passe directement au cycle Explore → Plan → Code → Verify. Le plan validé de la phase 2 est déjà une spec légère, et il ne te coûte rien à maintenir.


Étape 1 : Générer la spec avec l'IA Interview

Prompt
Je veux construire [description de la feature]. Interviewe-moi en détail en utilisant l'outil AskUserQuestion. Pose des questions sur : - L'implémentation technique (stack, patterns, contraintes) - L'UX/UI si pertinent - Les edge cases - Les tradeoffs entre approches - Les risques Ne pose pas de questions triviales. Creuse les parties difficiles. Continue jusqu'à avoir tout ce qu'il faut. Puis génère une spec complète dans specs/feature-[nom].md.

Structure d'une spec.md

# Feature : [Nom]
**Date** : [date]  
**Auteur** : [nom]  
**Status** : Draft / Validated / Implemented

## Résumé
[2-3 phrases : quoi, pourquoi, pour qui]

## Requirements
### Must Have
- [ ] [Requirement 1]
- [ ] [Requirement 2]

### Should Have
- [ ] [Requirement 3]

### Won't Have (this version)
- [Exclusion explicite]

## Architecture
[Description de l'approche technique choisie]

## Entités & Modèles
[Structures de données, schémas DB]

## API / Interface
[Endpoints, signatures de méthodes, contrats]

## Edge Cases & Gestion d'erreurs
[Liste des cas limites et comportements attendus]

## Critères d'acceptance
- [ ] Test 1 : [comportement attendu]
- [ ] Test 2 : ...

## Décisions techniques
[Pourquoi cette approche vs alternatives considérées]

Étape 2 : Générer le plan depuis la spec

Prompt
Voici la spec validée : @specs/feature-auth-oauth.md Génère maintenant un plan d'implémentation dans specs/plan.md. Format : - Étapes numérotées et séquentielles - Chaque étape : description + fichiers concernés + estimation - Dépendances entre étapes (ce qui doit être fait avant) - Critère de validation de chaque étape

Étape 3 : Décomposer en tâches atomiques

Prompt
Sur la base du plan @specs/plan.md, génère specs/tasks.md. Format pour chaque tâche : - [ ] [ID] [Description courte] | Dépendances: [IDs] | Validation: [commande/critère] Règle : chaque tâche doit être faisable en < 30 minutes. Si une tâche est plus grande, décompose-la.

Étape 4 : Implémenter tâche par tâche

Prompt
Implémente la tâche T-03 de @specs/tasks.md. Contexte : @specs/feature-auth-oauth.md Plan global : @specs/plan.md Une fois T-03 terminée : 1. Marque-la comme [x] dans tasks.md 2. Exécute le critère de validation 3. Arrête-toi et rapporte

4. Cas pratique complet : Ajout d'un soft delete

Voici l'application du cycle EPCV sur un cas concret : migrer un delete physique en soft delete.

Explore

Prompt
[ANALYSE UNIQUEMENT] Analyse UserRepository.ts. Identifie : - La méthode deleteUser actuelle (signature, SQL) - Toutes les requêtes SELECT qui devront être modifiées - La contrainte UNIQUE sur email et ses implications - Les tests existants qui couvrent deleteUser

Plan

Prompt
Sur la base de l'analyse : Propose le plan de migration vers le soft delete. Inclus : 1. Le SQL exact du nouveau delete (UPDATE + suffixage email pour UNIQUE) 2. Les SELECT à modifier (ajout WHERE deleted_at IS NULL) 3. Les tests à mettre à jour Format : plan en markdown, pas de code d'implémentation encore. Attends ma validation.

Code (après validation du plan)

Prompt
Implémente maintenant la méthode deleteUser selon le plan validé. Stack : TypeORM + PostgreSQL. Gère : - Le suffixage email : email + '_deleted_' + timestamp - La transaction si plusieurs tables sont touchées - La gestion d'erreur (user inexistant) Arrête après cette méthode uniquement.

Verify

Prompt
Agis en QA Engineer. Génère un test d'intégration (Jest + testcontainers PostgreSQL) pour deleteUser. Scénarios : 1. Delete d'un user existant → deleted_at renseigné, email suffixé 2. findByEmail après delete → retourne null 3. Réinscription avec le même email → fonctionne (contrainte UNIQUE respectée) 4. Delete d'un user inexistant → erreur appropriée

5. Quand l'agent déraille

Le cycle ci-dessus décrit une session qui se passe bien. Il faut aussi savoir quoi faire des autres. Les échecs d'agent ne sont pas aléatoires : ils prennent trois formes, elles se reconnaissent vite, et chacune appelle un geste différent. Le point commun des trois : le réflexe naturel, qui est de relancer, est le mauvais.

La boucle

Il essaie une approche, ça échoue. Il en essaie une deuxième, ça échoue. Il revient à la première avec une variation cosmétique. Le signal qui ne trompe pas : le même fichier édité trois fois en dix minutes, avec des diffs qui se ressemblent.

Ce qui se passe : il lui manque une information, et il compense en produisant des variantes. Aucune quantité de tentatives ne va faire apparaître l'information manquante. Le geste est donc de sortir de la boucle, pas de l'alimenter.

Sortir une session de la boucle
Arrête d'essayer de corriger. On change de mode.Dis-moi, sans écrire une ligne de code : Ce que tu as tenté, et l'erreur exacte obtenue à chaque fois. Ce que tu supposes sans en avoir la preuve. Sois précis sur ce qui est vérifié et ce qui est deviné. Quelle information te manque pour trancher, et quelle commande ou quel fichier me le dirait. Ne propose aucun correctif tant que je n'ai pas répondu.

Neuf fois sur dix, la réponse à la question 3 est quelque chose que tu peux fournir en trente secondes : une version de dépendance, un message d'erreur complet, le contenu réel d'un fichier de config.

Le faux vert

Il annonce que les tests passent. Ils ne passent pas. Trois variantes, par ordre de fréquence : il ne les a pas lancés et il te décrit ce qu'il attend, il les a lancés sur un sous-ensemble qui ne couvre pas son changement, ou il a modifié le test pour qu'il passe.

Le remède tient en une phrase : ne crois jamais un compte-rendu, lis la sortie de commande. Un agent te dit ce qu'il pense avoir fait ; le terminal dit ce qui s'est passé. Ce sont deux choses différentes, et l'écart n'a rien de malveillant : il prédit du texte plausible, et « les tests passent » est extrêmement plausible après une correction.

Deux garde-fous qui coûtent peu :

# Avant de merger, regarde si les tests ont bougé en même temps que le code.
# Un test modifié dans le même diff que le correctif qu'il est censé valider,
# ça demande une explication.
git diff --stat -- '*test*' '*spec*'

Et côté déterministe, un hook qui lance vraiment la suite après chaque édition, plutôt qu'une consigne que le modèle peut oublier. Le principe et l'implémentation sont au Module 6 ; l'idée est qu'une vérification qui compte ne doit pas dépendre de la bonne volonté de l'agent.

La dérive de périmètre

Tu demandes une correction sur trois lignes, le diff en fait quatre-vingts. Le reste est du nettoyage spontané : imports réorganisés, variables renommées, un else transformé en retour anticipé. Rien de faux, et c'est précisément le problème : tu vas devoir relire quatre-vingts lignes pour en valider trois, ou approuver sans lire.

La cause est presque toujours dans ton cadrage : tu as demandé le quoi sans borner le où. La correction se fait en amont, dans le prompt (« périmètre autorisé : ce fichier, ces fonctions ») ou dans le fichier de contexte, où une ligne suffit à couvrir toutes tes sessions.

SymptômeCause probableGeste
Le même fichier réécrit trois foisInformation manquanteOn arrête, on lui fait formuler ce qu'il ignore
« Les tests passent » sans sortie affichéeCompte-rendu au lieu de constatOn lance la commande soi-même
Un test modifié dans le diff du fixLe test a été plié au codeOn relit ce test en priorité
Un diff trois fois trop grosPérimètre non bornéOn reprend le prompt, pas le diff
Il s'excuse et change au hasardTu as dit « ça ne marche pas » sans dire quoiOn donne l'erreur exacte

La règle du deuxième échec

C'est la règle 4 ci-dessous, et elle mérite qu'on dise pourquoi elle marche. Si tu as corrigé l'agent deux fois sur la même chose, le problème n'est plus dans sa réponse : il est dans le contexte, qui contient maintenant deux tentatives ratées que le modèle va continuer de regarder. Chaque relance part d'un point de départ un peu plus mauvais.

Repartir de zéro n'est pas un aveu d'échec, c'est le geste rentable : tu ouvres une session propre en y mettant ce que les deux tentatives t'ont appris. Ce que tu as compris pendant l'échec est justement ce qui manquait au premier prompt.


6. Les règles d'or de la méthodologie

Règle 1 : Pas de code sans plan validé par un humain.

Règle 2 : Une tâche = une session. Ne mélange jamais deux features dans la même conversation.

Règle 3 : Donne toujours à l'IA un moyen de vérifier son travail (tests, linter, commande de build). Si ce moyen n'existe pas dans ton projet, c'est lui qu'il faut construire en premier : c'est tout l'objet du Module 4.

Règle 4 : Si tu as dû corriger l'IA plus de 2 fois sur la même chose → /clear + nouveau prompt enrichi.

Règle 5 : Les specs vivent dans le repo. Ce qui n'est pas versionné n'existe pas.