guest@6admin.io:~$

Clean Code vs Vibe Coding (ou comment ne pas finir dans les journaux)

L’émergence des grands modèles de langage (LLM) dans le développement logiciel soulève une question fondamentale : nos pratiques établies de clean code restent-elles pertinentes face au “vibe coding” ? Et surtout, comment éviter de se retrouver à la une des journaux tech avec le prochain “oops, j’ai exposé 50 millions de mots de passe” ?

Ces vieilles habitudes qui nous sauvent la mise

Le clean code repose sur des principes éprouvés qui, accessoirement, ont évité à pas mal de développeurs de finir au chômage technique :

DRY (Don’t Repeat Yourself) nous évite de dupliquer nos vulnérabilités dans tout le codebase. SOLID nous aide à créer des architectures où une faille de sécurité ne transforme pas tout le système en gruyère numérique. KISS (Keep It Simple, Stupid) limite les surfaces d’attaque, parce qu’un code complexe cache souvent des surprises désagréables. YAGNI (You Aren’t Gonna Need It) nous empêche d’ajouter du code inutile qui ne fait qu’augmenter la surface d’attaque sans apporter de valeur.

Ces approches favorisent la validation centralisée, les contrôles d’accès cohérents et cette petite voix dans notre tête qui dit “attendez, est-ce qu’on valide vraiment cette entrée utilisateur ?”

Quand l’inspiration rencontre l’exploitation

Le “vibe coding” a démocratisé le développement, permettant à chacun de créer des applications fonctionnelles en quelques heures. C’est formidable… jusqu’à ce qu’on réalise que “fonctionnel” ne signifie pas “sécurisé”.

Les LLM excellent à produire du code qui marche, mais ont parfois une relation compliquée avec les bonnes pratiques de sécurité. Ils peuvent générer du code vulnérable aux injections SQL, aux XSS ou aux fuites de données, surtout quand le contexte de sécurité n’est pas explicitement mentionné dans le prompt.

L’actualité nous rattrape : Les catastrophes du vibe coding

L’actualité récente regorge d’exemples où l’approche “ça marche, on ship” s’est mal terminée. Des startups ont découvert que leurs APIs générées par IA exposaient des données sensibles, des applications mobiles ont été compromises par des validations insuffisantes et certains développeurs ont appris à leurs dépens que “move fast and break things” ne devrait jamais s’appliquer aux systèmes d’authentification.

Le problème ? Les LLM optimisent pour la fonctionnalité, pas pour la sécurité. Ils peuvent produire un système de login qui fonctionne “parfaitement”, tout en stockant les mots de passe en plain text ou en oubliant de vérifier les permissions. Pire encore, ils ont tendance à générer du code “au cas où” : des endpoints supplémentaires, des fonctionnalités “qui pourraient servir”, créant autant de portes d’entrée potentielles pour les attaquants. Un bel exemple où ignorer YAGNI peut littéralement coûter cher.

Le paradoxe des LLM et la sécurité

Voici le nœud du problème : les pratiques de clean code, avec leurs validations centralisées et leurs abstractions de sécurité, créent effectivement plus de complexité pour les LLM. Mais cette complexité est souvent notre première ligne de défense !

Un middleware d’authentification bien abstrait peut sembler “obscur” pour un LLM, mais il centralise les contrôles de sécurité. Des fonctions de validation centralisées peuvent consommer plus de tokens à analyser, mais elles garantissent que toutes les entrées sont traitées de manière cohérente selon les mêmes règles.

À l’inverse, le code “vibe” plus direct peut être transparent pour les LLM, mais il multiplie les points de défaillance potentiels.

Le TDD : le garde-fou que le vibe coding attendait

Le test-driven development n’est pas une pratique de puriste: c’est le mécanisme qui rend le vibe coding safe. Le pattern:

  1. Écrire les tests D’ABORD, avant de demander au LLM de générer le code. Les tests sont la spécification, pas la validation après coup.
  2. Inclure les tests de sécurité dans la spécification: injection SQL, XSS, débordement de buffer, permission denied, edge cases d’entrée. Le LLM ne connaît pas votre modèle de menace à moins que vous le lui donniez et les tests SONT le modèle de menace.
  3. Générer le code avec le LLM, en lui donnant les tests comme contexte. Le LLM optimise pour passer les tests, pas pour “marcher”.
  4. Exécuter les tests. Un échec est une vulnérabilité attrapée avant le déploiement, pas après.

Le Red-Green-Refactor devient Spec-Generate-Verify: la spec est votre test, la génération est le LLM, la vérification est le test qui passe. Sans TDD, le code du LLM va en prod sans être testé. Avec TDD, le code du LLM passe par exactement le même filtre que le code humain.

Et le coût est dérisoire: écrire les tests AVANT prend 10 minutes, corriger l’injection SQL découverte en prod prend 10 jours.

Le compilateur strict, l’autre garde-fou

Le TDD pose la spec, mais il ne tranche qu’au moment où l’on lance les tests et entre deux il reste une ligne de défense que le vibe coding néglige presque toujours, le compilateur, réglé au plus strict et au plus verbeux. Un vérificateur de types attrape l’erreur du LLM à la compilation, là où elle ne coûte rien et refuse le None qui traîne, le cast hasardeux ou la branche oubliée. Activez le typage statique partout où le langage le permet, mypy en --strict, TypeScript en mode strict, le borrow checker de Rust qui ne négocie jamais et montez les avertissements du compilateur au maximum, -Wall -Wextra -Werror en C, les linters en mode paranoïaque ailleurs. Le LLM produit volontiers du code qui marche dans le cas nominal et s’effondre sur le cas limite et un compilateur intraitable transforme ce cas limite en erreur de build plutôt qu’en incident de prod. C’est un garde-fou quasi gratuit, en complément du TDD plutôt qu’à sa place, parce qu’il travaille pendant que vous tapez, sans que vous ayez à écrire quoi que ce soit de plus que les types.

La sécurité comme arbitre

La sécurité informatique tranche clairement en faveur du clean code, mais avec des nuances importantes :

Les patterns de sécurité doivent être explicites. Au lieu de cacher la logique de sécurité dans des abstractions complexes, il faut la rendre visible et documentée pour que les LLM puissent la comprendre et la respecter.

La validation doit être centralisée mais redondante. Centraliser la logique de validation (principe DRY) tout en ajoutant des vérifications supplémentaires aux points critiques - même si cela semble contradictoire, mieux vaut une validation en trop qu’une faille béante.

Les LLM ont besoin de contexte de sécurité explicite. Un prompt qui mentionne “génère-moi une API” sans mentionner l’authentification, l’autorisation ou la validation produira probablement du code vulnérable.

Vers un vibe coding responsable ?

L’avenir réside dans un “vibe coding responsable” qui combine la rapidité des LLM avec les garde-fous du clean code :

Templates sécurisés : Créer des modèles de code avec les bonnes pratiques intégrées que les LLM peuvent réutiliser.

Checklists de sécurité : Systématiser les vérifications post-génération comme on le ferait pour du code humain.

Tests de sécurité automatisés : Intégrer des outils de scan de vulnérabilités dans le workflow de développement assisté par IA.

Formation des prompts : Apprendre à inclure systématiquement les exigences de sécurité dans nos interactions avec les LLM.

Typage strict et compilateur intraitable : en complément du TDD, comme décrit plus haut, un filtre quasi gratuit qui attrape à la compilation ce que le LLM glisse entre les lignes.

TDD en premier : Écrire les tests avant de générer le code, avec les tests de sécurité inclus dans la spec. Le LLM passe les tests ou le code ne part pas.

Conclusion

La compatibilité entre clean code et vibe coding existe, mais elle passe par une prise de conscience : la vitesse de développement ne doit jamais se faire au détriment de la sécurité. Les LLM sont d’excellents assistants, mais ils ont besoin de garde-corps humains pour éviter les catastrophes.

Parce qu’au final, personne ne veut être ce développeur qui explique à son équipe comment une injection SQL a fait fuiter la base clients, surtout quand c’est un chatbot qui a écrit le code incriminé.

Rappel amical : Vos utilisateurs vous font confiance avec leurs données. Ne les décevez pas pour gagner quelques heures de développement.