Chapitre 4.2 — Primitives & réutilisation
⏱️ TL;DR — L’autre moitié de l’incohérence : l’agent réinvente un composant qui existe déjà, parce qu’il ne l’a pas vu. La parade : un jeu de primitives (
Button,Input,Card,Dialog…) à un endroit connu, un point d’entrée unique (@/components/ui), et une règle ferme — avant de créer, cherche l’existant. Un agent qui trouve facilement la primitive la réutilise ; un agent qui ne la trouve pas en fabrique une troisième.
🎯 Objectifs
- Comprendre pourquoi l’agent réinvente (et que ce n’est pas de la « bêtise »).
- Structurer des primitives découvrables.
- Imposer le réflexe chercher-avant-créer.
- Tenir un inventaire de composants que l’agent consulte.
Pourquoi l’agent réinvente
Rappel de la boucle (1.1) : l’agent agit sur ce qu’il voit. S’il doit afficher un bouton et qu’il n’a pas connaissance de ton Button, il en écrit un — c’est rationnel de son point de vue. Le problème n’est pas qu’il soit mauvais ; c’est que rien ne lui a rendu ton composant visible et obligatoire. Deux causes concrètes :
- Découvrabilité : tes primitives sont éparpillées, mal nommées, sans index → l’agent ne les trouve pas vite.
- Absence de règle : rien ne dit « passe par l’existant d’abord » → il crée par défaut.
Rendre les primitives découvrables
Une primitive réutilisée est une primitive facile à trouver. Trois gestes :
- Un emplacement unique et connu :
src/components/ui/. Tout y est, rien ailleurs. - Un point d’entrée (
src/components/ui/index.ts) qui ré-exporte tout :L’agent (et toi) importe viaexport { Button } from './button' export { Input } from './input' export { Card } from './card' export { Dialog } from './dialog'@/components/ui— un seul endroit à connaître. - Des noms canoniques :
Button, pasMyButton/AppBtn/CustomButton. Un nom évident se retrouve d’ungrep.
💡 Réflexe d’architecte — Le meilleur signal « réutilise-moi » que tu puisses envoyer à l’agent, c’est un
index.tsd’UI bien peuplé et une phrase dans leCLAUDE.md: « les composants d’UI existants sont exportés depuis@/components/ui— regarde-les avant d’en créer un ». Tu transformes la réutilisation en chemin de moindre effort.
Le réflexe chercher-avant-créer
C’est la règle qui fait la différence. Formulée pour l’agent :
« Avant de créer un composant d’UI, cherche s’il existe déjà dans
@/components/ui(et dans la feature). S’il existe, réutilise-le ou étends-le. Ne crée une nouvelle primitive que si rien ne convient — et dans ce cas, place-la dans@/components/uiet signale-le. »
Tu peux (et devras, Partie 7/11) la renforcer par la revue : une des questions de /code-review sera « ce composant réinvente-t-il quelque chose d’existant ? ». Mais énoncée + montrée, elle porte déjà beaucoup.
⚠️ Piège — La « petite variante locale ». L’agent (ou toi) crée un
PrimaryButtondans une feature « parce que c’est un peu spécifique ». Trois features plus tard, il y a quatre boutons quasi identiques dispersés. Règle : une variante = une prop du composant existant (<Button variant="primary">), pas un nouveau composant. On étend, on ne duplique pas.
L’inventaire vivant
Sur un projet qui grossit, l’agent gagne à disposer d’un inventaire consultable des primitives et de leur usage. Deux formes utiles :
- Le
index.tsest déjà un mini-inventaire (la liste des exports). - Pour aller plus loin : un court
src/components/ui/README.mdlistant chaque primitive, ses variantes et un exemple. L’agent le lit avant de créer.
Le point clé : l’inventaire se met à jour quand une primitive naît (sinon il devient périmé, cf. 3.4). Une nouvelle primitive non inventoriée sera réinventée la fois d’après.
🧭 Sur TaskFlow — On maintiendra
@/components/uicomme unique source de primitives, avec sonindex.ts. La règle chercher-avant-créer ira dans leCLAUDE.md, et on la vérifiera en revue (Partie 11). Concrètement : un seulButton, étendu par desvariant, jamais unTaskButtonqui traîne dans une feature.
✏️ Exercices
Exercice 1 — Chasse aux doublons. grep (ou demande à l’agent) tous les composants de type bouton/carte/modale de ton projet. Combien de variantes du « même » composant trouves-tu ?
✅ Solution
Beaucoup de projets « IA-assistés » ont 2-4 boutons quasi identiques éparpillés. Le nombre est ta dette de réutilisation. La consolidation (un composant, des variant) + un index.ts + la règle chercher-avant-créer stoppe l’hémorragie.
Exercice 2 — Le point d’entrée. Crée (ou fais créer) un src/components/ui/index.ts qui ré-exporte tes primitives, et ajoute au CLAUDE.md la phrase « UI depuis @/components/ui, chercher avant de créer ». Demande ensuite un nouvel écran et observe : réutilise-t-il ?
✅ Solution
Avec le point d’entrée + la règle, l’agent importe en général les primitives existantes au lieu d’en fabriquer. S’il en crée quand même une, c’est souvent que la primitive manquait vraiment (bon signal) ou que ton index.ts/README ne la rendait pas assez visible.
🧠 Quiz de révision
1. Pourquoi l’agent réinvente-t-il un composant existant ?
Parce qu’il agit sur ce qu’il voit : si la primitive n’est pas découvrable (éparpillée, mal nommée, sans index) et qu’aucune règle n’impose de chercher, en créer une est le choix par défaut. Ce n’est pas de la bêtise, c’est un manque d’outillage.
2. Quels trois gestes rendent une primitive découvrable ?
Un emplacement unique (src/components/ui/), un point d’entrée (index.ts qui ré-exporte), et des noms canoniques (Button, pas AppBtn). L’agent la trouve d’un import ou d’un grep.
3. Une variante d’un composant : nouveau composant ou prop ?
Une prop (<Button variant="primary">) du composant existant. On étend, on ne duplique pas — sinon on multiplie les quasi-doublons.
4. Formule la règle « chercher-avant-créer ».
« Avant de créer un composant d’UI, cherche l’existant dans @/components/ui (et la feature) ; réutilise ou étends ; ne crée du neuf que si rien ne convient, dans ui/, en le signalant. »
5. Pourquoi maintenir l’inventaire à jour ?
Parce qu’une primitive non inventoriée est invisible, donc réinventée la fois suivante. L’inventaire (index.ts + README) doit grandir en même temps que les primitives, sinon il devient périmé.
Chapitre suivant : Techniques anti-dérive — les gestes qui maintiennent la cohérence dans la durée.