IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Mon expérience avec le « vibe coding », par Gabriella Gonzalez

Le , par Gabriella Gonzalez

5PARTAGES

4  1 
Mon expérience avec le « vibe coding », par Gabriella Gonzalez

De temps à autre, je teste le « vibe coding », pour diverses raisons :

- parfois, je me laisse emporter par l'engouement général et, avec un sentiment de culpabilité, je me tourne vers le « vibe coding » quand je suis bloqué
- d'autres fois, quelqu'un me dit que cette technologie de pointe a franchi une étape décisive
- j'aimerais aussi que le « vibe coding » ou quelque chose de similaire fonctionne (je suis généralement favorable à l'IA)

Cependant, chaque fois que j’essaie le « vibe coding », je ne suis pas impressionné par les résultats. Ne vous méprenez pas : je pense que le « vibe coding », dans son état actuel, est assez incroyable et constitue une démo technique sympa, mais qu’il passe à côté de son objectif en tant qu’outil d’ingénierie logicielle.

Je vais illustrer ce que je veux dire avec un exemple de session Claude Code que j’ai réalisée. J’ai choisi Claude Code pour mon récent essai de « vibe coding » parce que certains de mes collègues et pairs sur les réseaux sociaux en disaient beaucoup de bien.

Le défi

Au cours du week-end, je travaillais sur mon projet Grace (un langage spécifique à un domaine pour l'ingénierie des prompts - instructions génératives) et l'un des problèmes auxquels j'étais confronté était que la compilation Nix pour GHCJS échouait avec cette erreur après la mise à jour vers Nixpkgs 24.11 :

Configuration : dépendance manquante sur une bibliothèque externe :
* Fichier d'en-tête manquant (ou incorrect) : ghc/utils/unlit/fs.h
De plus, l'échec n'était pas reproductible. La compilation réussissait sur une machine mais échouait sur une autre. J'aurais pu contourner le problème en copiant le produit de compilation mis en cache d'une machine à l'autre, mais je voulais mieux comprendre ce qui se passait pour évaluer toute l'étendue du problème de reproductibilité.

J'ai commencé le débogage et, au bout d'environ une heure, j'avais une « solution » (plutôt une solution de contournement). Puis je me suis arrêté et j'ai réalisé que cela constituerait en fait un bon exemple concret pour m'essayer au vibe coding, car c'est le genre de problème auquel je suis régulièrement confronté (tant dans le cadre professionnel que dans mes projets open source). J'avais également mon propre travail sur lequel je pouvais comparer le vibe coding.

Le résultat

Je me suis donc abonné à Claude Code Pro (pour 17 $ par mois), j’ai installé Claude Code, je l’ai lancé dans mon terminal et j’ai commencé par cette instruction générative :

Je souhaite corriger un échec de compilation dans ma configuration Nix. Pour replacer les choses dans leur contexte, cette compilation fonctionne sur une autre machine, mais pour une raison quelconque, elle ne fonctionne pas sur celle-ci. Plus précisément, pour reproduire l'échec de compilation, il faut charger le shell Nix en définissant .envrc sur "use flake “.#ghcjs”" et direnv reload, ou simplement nix build '.#website'.
… puis j’ai laissé Claude prendre le relais à partir de là. La transcription complète de la session est fournie en annexe ci-dessous, mais ma politique d’interaction de base était la suivante :

- rester engagé/présent (en suivant le fil des pensées et les commandes de Claude)

- intervenir pour clarifier les exigences

- essayer de ne pas influencer le processus avec les connaissances que j’avais acquises lors de mes propres recherches

- essayer d’approuver automatiquement autant que possible, dans la mesure du raisonnable

- confirmer manuellement toutes les modifications apportées au code

La seule fois où j’ai dû intervenir, c’est lorsque Claude a commencé à essayer de contourner le problème en effectuant une compilation pour x86_64-darwin au lieu de aarch64-darwin. Mon commentaire a été :

Tu n’as pas besoin d’exécuter Rosetta. Cette compilation devrait sans aucun doute fonctionner sur aarch64-darwin. Je sais qu’elle fonctionne sur une autre machine et que persister avec une compilation x86_64-darwin est une impasse.
Pour le reste, j’ai généralement laissé les idées de Claude « suivre leur cours » afin de voir s’il apprendrait et s’adapterait de lui-même, et pour évaluer dans quelle mesure je pouvais le laisser travailler sans supervision.

Malheureusement, la première tentative de solution de Claude n’était pas bonne, et je vais la coller ici :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
diff --git a/flake.nix b/flake.nix
index 465442e..957ca26 100644
--- a/flake.nix
+++ b/flake.nix
@@ -16,8 +16,59 @@
         };
 
         haskell = super.haskell // {
+          compiler = super.haskell.compiler // {
+            ghcjs =
+              let
+                originalGhcjs = super.haskell.compiler.ghcjs;
+                originalBootGhcjs = originalGhcjs.passthru.bootGhcjs;
+                emsdk = "/nix/store/rsd7naynyq6r8cry568r1widlzgxvqzg-emsdk";
+
+                # Patch bootGhcjs to fix the fs.h path issue
+                patchedBootGhcjs = originalBootGhcjs.overrideAttrs (bootOld: {
+                  patches = (bootOld.patches or []) ++ [ ./ghcjs-fix-fs-header-path.patch ];
+                });
+              in
+                # The final GHCJS runs ghcjs-boot using bootGhcjs
+                originalGhcjs.overrideAttrs (final: prev: {
+                  nativeBuildInputs = [ patchedBootGhcjs ] ++
+                    (builtins.filter (x: x != originalBootGhcjs) prev.nativeBuildInputs);
+
+                  # Rewrite buildPhase to use patched bootGhcjs
+                  buildPhase = ''
+                    export HOME=$TMP
+                    mkdir $HOME/.cabal
+                    touch $HOME/.cabal/config
+                    cd lib/boot
+
+                    mkdir -p $out/bin
+                    mkdir -p $out/lib/ghcjs-8.10.7
+                    lndir ${patchedBootGhcjs}/bin $out/bin
+                    chmod -R +w $out/bin
+                    rm $out/bin/ghcjs-boot
+                    cp ${patchedBootGhcjs}/bin/ghcjs-boot $out/bin
+                    rm $out/bin/haddock
+                    cp ${patchedBootGhcjs}/bin/haddock $out/bin
+                    cp ${patchedBootGhcjs}/bin/private-ghcjs-hsc2hs $out/bin/ghcjs-hsc2hs
+
+                    wrapProgram $out/bin/ghcjs-boot --set ghcjs_libexecdir $out/bin
+
+                    wrapProgram $out/bin/ghcjs --add-flags "-B$out/lib/ghcjs-8.10.7"
+                    wrapProgram $out/bin/haddock --add-flags "-B$out/lib/ghcjs-8.10.7"
+                    wrapProgram $out/bin/ghcjs-pkg --add-flags "--global-package-db=$out/lib/ghcjs-8.10.7/package.conf.d"
+                    wrapProgram $out/bin/ghcjs-hsc2hs --add-flags "-I$out/lib/ghcjs-8.10.7/include --template=$out/lib/ghcjs-8.10.7/include/template-hsc.h"
+
+                    env PATH=$out/bin:$PATH $out/bin/ghcjs-boot --with-emsdk=${emsdk} --no-haddock
+                  '';
+                  passthru = prev.passthru // {
+                    bootGhcjs = patchedBootGhcjs;
+                  };
+                });
+          };
+
           packages = super.haskell.packages // {
             "${compiler}" = super.haskell.packages."${compiler}".override (old: {
+              ghc = if compiler == "ghcjs" then self.haskell.compiler.ghcjs else old.ghc or null;
+
               overrides =
                 let
                   hlib = self.haskell.lib;
diff --git a/ghcjs-fix-fs-header-path.patch b/ghcjs-fix-fs-header-path.patch
index 534bffc..ac19b29 100644
--- a/ghcjs-fix-fs-header-path.patch
+++ b/ghcjs-fix-fs-header-path.patch
@@ -1,19 +1,20 @@
-diff --git a/ghcjs.cabal b/ghcjs.cabal
-index 1234567..abcdefg 100644
 --- a/ghcjs.cabal
 +++ b/ghcjs.cabal
-@@ -43,7 +43,7 @@ library
-                ghc/libraries/ghc-prim/cbits
-                ghc/utils/fs
-                ghc/rts
--               ghc/utils/unlit/fs.h
-+               ghc/utils/fs/fs.h
-     GHC-Options: -Wall -fno-warn-orphans -fno-warn-name-shadowing -fno-warn-unused-do-bind -fprof-auto-calls -fobject-code
-     if flag(disable-optimizer)
-       cpp-options: -DDISABLE_OPTIMIZER
-@@ -916,4 +916,4 @@ executable ghcjs
-     Main-Is: Main.hs
-     Build-Depends:     base, ghcjs
-     Default-Language:  Haskell2010
+@@ -43,7 +43,7 @@
+                 ghc/includes/HsFFI.h
+                 ghc/includes/Cmm.h
+                 ghc/includes/stg/*.h
+-                ghc/utils/unlit/fs.h
++                ghc/utils/fs/fs.h
+                 ghc/driver/utils/cwrapper.h
+                 ghc/driver/utils/getLocation.h
+                 utils/wrapper/getline.h
+@@ -916,7 +916,7 @@
+     hs-source-dirs: ghc/utils/unlit
+     Main-Is: unlit.c
+     C-Sources: ghc/utils/unlit/fs.c
 -    Includes: ghc/utils/unlit/fs.h
 +    Includes: ghc/utils/fs/fs.h
+
+ Executable private-ghcjs-touchy
+     if flag(compiler-only) || !os(Windows)


C'est une pratique d'ingénierie logicielle plutôt médiocre (j'expliquerai pourquoi dans la section suivante), mais je voulais donner à Claude une chance de se rattraper ; j'ai donc commencé à m'impliquer davantage dès que j'ai compris que Claude n'était pas vraiment fait pour un fonctionnement de type « fire and forget ». Cependant, j'ai continué à éviter de m'appuyer sur mes recherches antérieures et je ne lui ai donné de retours que sur la base de ce qu'il avait lui-même rassemblé, appris et présenté.

Tout d'abord, j'ai demandé à Claude d'améliorer sa solution :

Cette solution présente donc quelques problèmes : (A) tu ne devrais pas avoir codé en dur les chemins /nix/store (comme /nix/store/rsd…-emdsk) et (B) tu ne devrais pas copier/coller/modifier la buildPhase (car cela entraînerait une dérive de configuration si, par exemple, je mettais à jour Nixpkgs)
… puis Claude s’est engagé sur une mauvaise voie (en essayant d’utiliser le remplacement de chaînes à la place, ce qui n’est pas non plus une bonne pratique) ; j’ai donc de nouveau intervenu de manière proactive pour éviter que Claude ne se retrouve en difficulté en suivant cette voie :

❯ Le remplacement de chaînes n’est pas non plus une solution Nix idiomatique au problème. En général, la bonne façon de procéder dans ce genre de situation est d'utiliser un .override(…) ou un .overrideAttrs(…) bien placé, ou quelque chose de similaire
… puis Claude a travaillé là-dessus pendant un moment et a fini par épuiser ses jetons pour la journée (car j'utilisais le forfait Pro et non le forfait Max). C'était après une session d'environ une heure avec Claude ; j'aurais pu passer à Claude Code Max, ce qui m'aurait donné environ 20 fois plus de ressources que le forfait Pro, et j'aurais ainsi pu… dépenser beaucoup plus d'argent (200 $ par mois !) et de temps pour apprendre à Claude à mieux faire son travail.

Inutile de dire que je n'étais pas impressionné. Si je voulais consacrer du temps et de l'argent à encadrer un ingénieur junior, je préférerais les consacrer à apprendre à un humain comment devenir un meilleur ingénieur logiciel.

Une ingénierie de mauvaise qualité

Je souhaite expliquer en détail pourquoi la solution de Claude relevait d'une mauvaise ingénierie, car pour un œil non averti, elle pourrait sembler être une solution acceptable au problème. Cependant, les LLM sont connus pour générer des solutions/idées qui semblent bonnes à première vue, mais qui s'effondrent lorsqu'on les examine de plus près.

Le premier problème est le suivant : la solution de Claude n'est absolument pas reproductible sur d'autres machines. En fait, elle n'est même pas nécessairement reproductible sur ma propre machine : la solution de Claude finira par cesser de fonctionner sur ma machine dès la première fois que j'exécuterai un ramassage des ordures Nix.

Cela s'explique par le fait que Claude code en dur le chemin du magasin Nix /nix/store/rsd7naynyq6r8cry568r1widlzgxvqzg-emsdk, ce qui est à proscrire absolument dans Nix pour la raison que je viens de mentionner (manque criant de reproductibilité, même au niveau local).

L'autre problème avec cette solution est que Claude n'a pas su comment patcher de manière idiomatique la compilation de ghcjs ; il a donc eu recours à un gros hack pour contourner son manque de connaissances :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
+                  buildPhase = ''
+                    export HOME=$TMP
+                    mkdir $HOME/.cabal
+                    touch $HOME/.cabal/config
+                    cd lib/boot
+
+                    mkdir -p $out/bin
+                    mkdir -p $out/lib/ghcjs-8.10.7
+                    lndir ${patchedBootGhcjs}/bin $out/bin
+                    chmod -R +w $out/bin
+                    rm $out/bin/ghcjs-boot
+                    cp ${patchedBootGhcjs}/bin/ghcjs-boot $out/bin
+                    rm $out/bin/haddock
+                    cp ${patchedBootGhcjs}/bin/haddock $out/bin
+                    cp ${patchedBootGhcjs}/bin/private-ghcjs-hsc2hs $out/bin/ghcjs-hsc2hs
+
+                    wrapProgram $out/bin/ghcjs-boot --set ghcjs_libexecdir $out/bin
+
+                    wrapProgram $out/bin/ghcjs --add-flags "-B$out/lib/ghcjs-8.10.7"
+                    wrapProgram $out/bin/haddock --add-flags "-B$out/lib/ghcjs-8.10.7"
+                    wrapProgram $out/bin/ghcjs-pkg --add-flags "--global-package-db=$out/lib/ghcjs-8.10.7/package.conf.d"
+                    wrapProgram $out/bin/ghcjs-hsc2hs --add-flags "-I$out/lib/ghcjs-8.10.7/include --template=$out/lib/ghcjs-8.10.7/include/template-hsc.h"
+
+                    env PATH=$out/bin:$PATH $out/bin/ghcjs-boot --with-emsdk=${emsdk} --no-haddock
+                  '';


Je sais par hasard (grâce à mes propres recherches sur le problème) que Claude n'a pas rédigé ce code de manière réfléchie ; il l'a copié/collé/modifié à partir d'ici.

Ce n'est pas une bonne pratique en génie logiciel, car si buildPhase en amont change, la copie que Claude a intégrée dans mon fichier flake.nix ne tiendra pas compte de ces modifications. De plus, cela signifie que la dérivation risque fort de ne plus fonctionner lorsque je mettrai à jour (de la même manière que le verrouillage ou l'intégration d'une dépendance a tendance à empêcher les mises à jour). Encore une fois, c'est le genre de problème qui semble acceptable à court terme, mais qui cause des problèmes à long terme.

Une manière beaucoup plus directe de faire ce que Claude essayait de faire aurait été quelque chose comme ceci :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
diff --git a/flake.nix b/flake.nix
index 465442e..f10cb22 100644
--- a/flake.nix
+++ b/flake.nix
@@ -16,6 +16,19 @@
         };
 
         haskell = super.haskell // {
+          compiler = super.haskell.compiler // {
+            ghcjs810 = super.haskell.compiler.ghcjs810.override (old: {
+              ghcjsDepOverrides = self: super: {
+                ghcjs = super.ghcjs.overrideAttrs (old: {
+                  postPatch = (old.postPatch or "") +
+                    ''
+                    ./utils/makePackages.sh copy
+                    '';
+                });
+              };
+            });
+          };
+
           packages = super.haskell.packages // {
             "${compiler}" = super.haskell.packages."${compiler}".override (old: {
               overrides =


Cependant, d'après mon expérience en matière de débogage, je sais que ni la solution de Claude ni son équivalent plus simple ne résolvent réellement le problème (elles ne font que repousser l'échec de la compilation à un nouvel échec qui se produira plus tard). J'aborderai le véritable problème et la solution dans la section suivante.

Je ne m'attends pas à ce que Claude soit parfait, mais j'aurais aimé qu'il reconnaisse que ce code était fragile/difficile à maintenir et qu'il s'arrête pour me demander mon avis/mes conseils avant de foncer tête baissée avec cette approche. Par exemple, Claude aurait pu dire : « La solution que j'ai en tête pourrait ne pas être maintenable pour les raisons X, Y et Z. Cela vous convient-il ? Je risque d’épuiser mon budget de jetons si je cherche de meilleures solutions ».

Le problème plus grave, cependant, est qu’une personne peu familière avec Nix pourrait être induite en erreur et penser que cette solution est acceptable, voire impressionnante ! Ça « marche »… jusqu’à ce que ça ne marche plus. C’est pourquoi je suis assez sceptique face aux affirmations selon lesquelles le « vibe coding » permettrait de « faire passer au niveau supérieur » les personnes travaillant en terrain inconnu, car elles ne sont pas nécessairement qualifiées pour comprendre les implications, les compromis et les inconvénients du code généré par les LLM (et les solutions de « vibe coding » ne semblent pas encore en mesure de reconnaître et de communiquer efficacement ces compromis). Chaque fois que je code intuitivement dans un domaine relevant de ma propre expertise, je ne suis pas impressionné par les résultats, ce qui me rend très sceptique quant à la capacité du « vibe coding » à fonctionner correctement lorsque j’opère en dehors de ma zone de confort.

Solution humaine

La cause réelle de l’échec de la compilation est un problème connu dans Nixpkgs, pour lequel une demande de modification (pull request) est en cours de traitement. Plus précisément :

- cette commande de prétraitement gcc -E échouait de manière inattendue

- cet échec ne se produit que sur les versions récentes de macOS lorsque gcc comporte des entrées LC_RPATH en double

- la machine sur laquelle la compilation a réussi fonctionnait parce qu'elle tournait sous une version plus ancienne de macOS

- le « mode strict de Bash » était commenté, de sorte que l'échec de la compilation était très éloigné de la cause première

La solution de contournement que j'ai utilisée consistait à exécuter et à mettre en cache la compilation à l'aide de mon CI Garnix existant (qui fonctionne sur une ancienne version de macOS ne présentant pas ce problème). Ce n'est toujours pas idéal du point de vue de la reproductibilité, mais c'est à peu près aussi reproductible que peuvent l'être les compilations Darwin dans l'écosystème Nixpkgs. La meilleure solution possible serait de faire aboutir la proposition de modification mentionnée ci-dessus. Une solution intermédiaire consisterait à modifier l'étape gcc -E pour utiliser un préprocesseur C différent (par exemple clang) uniquement pour cette commande défaillante.

Conclusion

Cet exemple est assez représentatif de mes expériences avec le vibe coding. Chaque fois que j'essaie le vibe coding en situation réelle (et non pour des démos), je commence par me sentir optimiste et enthousiaste, puis je finis par être déçu et déprimé. Je ne veux pas produire du code jetable : Je veux construire des choses qui dureront et qui ne m'exploseront pas au visage plus tard, et je ne veux pas avoir à tenir la main/garder/amadouer l'outil pour obtenir les résultats que je souhaite. Je veux que le « vibe coding » améliore la qualité de mon travail, pas qu'il la détériore.

Je comprends que ce n'est pas ainsi que le « vibe coding » est présenté par ses partisans. Pour citer Andrej Karpathy, le « vibe » du « vibe coding » consiste à :

… s’abandonner pleinement au vibe, embrasser les exponentielles et oublier que le code existe même
… et cela peut très bien fonctionner pour de tout petits projets, mais cela ne s’applique pas vraiment à des projets d’une taille ou d’une portée même modeste.

Je ne pense pas que le « vibe coding » soit sans valeur et je pense que l’expérience du « vibe coding » peut s’améliorer et a du potentiel, mais le « vibe coding » dans sa forme actuelle n’est pas la technologie surhumaine issue d’un monde imaginaire que certains partisans prétendent qu’il est.

Vous n’êtes pas obligé de me croire sur parole : vous pouvez mener cette expérience vous-même. Si Nix est installé sur votre macOS, vous pouvez consulter cette branche de mon dépôt Grace et demander à votre outil de « vibe coding » préféré de corriger l’échec de compilation pour voir quelle qualité de solution vous obtenez.

Cette œuvre est mise à disposition selon les termes de la licence Creative Commons Attribution 4.0 International.

Source : "My experience with vibe coding"

Et vous ?

Pensez-vous que ce rapport est crédible ou pertinent ?
Quel est votre avis sur le sujet ?

Voir aussi :

Les ingénieurs en logiciel ne sont pas (et ne devraient pas être) des techniciens, car un grand ingénieur en logiciel est celui qui automatise le travail répétitif ou manuel, par Gabriella Gonzalez

Vos pull requests slop vibe-codées ne sont pas les bienvenues, car les outils de codage basés sur l'IA posent un nouveau problème aux responsables de projets open source, par Sam Saffron

Nous pleurons notre métier : Le pire avec ces outils d'IA, c'est qu'ils fonctionnent, ils peuvent écrire du code mieux que vous ou moi, par Nolan Lawson

Si vous êtes doué pour la révision de code, vous serez doué pour utiliser les agents IA, par Sean Goedecke
Vous avez lu gratuitement 291 articles depuis plus d'un an.
Soutenez le club developpez.com en souscrivant un abonnement pour que nous puissions continuer à vous proposer des publications.

Une erreur dans cette actualité ? Signalez-nous-la !

Avatar de alvi392
Nouveau Candidat au Club https://www.developpez.com
Le 30/03/2026 à 20:51
Sans entrer dans les détails techniques de la « démonstration », qui n’ont pas vraiment d’intérêt scientifique, je pense que cette ingénieure passe complètement à côté du sujet. Elle réduit son expérience du « vibe coding » à un usage "coupable" et exclusif de l’outil Claude, auquel elle semble davantage adresser des reproches que donner de véritables instructions à travers ses prompts. Or, juger la pertinence de cet outil ou du vibe coding en général par leurs capacité à proposer des solutions plus ou moins élégantes à un problème n’est en pratique pas la bonne grille de lecture.

L’objectif principal des outils tels que Claude ou du vibe coding est avant tout de réduire les coûts de développement à court terme, délais compris. La dette technique, quant à elle, existe et existera toujours, mais elle se manifeste simplement sous une forme différente.
0  0