Aller au contenu principal
Retour au blog
vibe coding

Hériter d’un code vibe-codé : guide CTO et devs

Par ···10 min de lecture
Des pièces de porcelaine aux connexions emmêlées deviennent trois modules ordonnés, reliés par des tubes de verre aux accents teal.

La démo fonctionne. Les utilisateurs ont commencé à arriver. Puis une modification du tarif casse les réservations, un correctif de permissions modifie trois écrans et personne ne sait pourquoi deux services calculent le même montant différemment. Vous venez d’hériter du dépôt.

Pour un développeur ou un CTO, reprendre cette base commence par une question : pouvons-nous prévoir les conséquences du prochain changement ? La réponse dépend des règles métier, des frontières du code et des moyens de vérification disponibles.

Notre article sur les avantages et limites du vibe coding aide à choisir cette approche. Le guide de reprise d’une application couvre l’audit et le passage en production. Ici, nous entrons dans le dépôt : tests, vocabulaire, modules, décisions d’architecture et migrations.

Le risque : du code que l’équipe ne peut plus expliquer

Du code généré peut être correctement conçu, relu et testé. À l’inverse, une application écrite entièrement à la main peut accumuler les mêmes difficultés. L’origine du code renseigne peu sur sa capacité à évoluer ; il faut examiner son comportement et les décisions qui le structurent.

Le rapport DORA 2025 décrit l’IA comme un amplificateur des forces et faiblesses d’une organisation. Ce constat ne mesure pas la qualité de votre dépôt. Nous en tirons une priorité pour la reprise : renforcer la compréhension et la validation avant d’accélérer à nouveau la production de code.

Un symptôme mérite particulièrement l’attention : personne ne peut expliquer une règle sans parcourir toute l’application ou demander au modèle de la reconstituer. Une explication plausible reste une hypothèse jusqu’à ce que le code exécuté, les tests et le métier la confirment.

Avant le refactoring : retrouver une version de référence

Commencez par un environnement reproductible, avec une version du code identifiée, des dépendances verrouillées et des données de test. Vérifiez que l’équipe peut déployer et restaurer le service, puis suivez un parcours critique de l’écran jusqu’au stockage et aux services externes.

Si vous découvrez une exposition de données, des accès non autorisés ou des secrets compromis, traitez ce risque avant le nettoyage architectural. Une application instable ne devient pas sûre parce que ses dossiers ont été réorganisés.

Choisissez ensuite un premier périmètre : une capacité métier qui change souvent, provoque des incidents ou bloque une livraison. Les cinq chantiers ci-dessous peuvent avancer sur ce périmètre avant d’être étendus.

1. Augmenter la testabilité avant de changer les règles

Les tests de caractérisation décrits par Michael Feathers capturent ce que fait réellement un programme. Ils permettent de détecter un changement de comportement pendant une reprise, y compris lorsque la spécification d’origine manque. Ils ne prouvent pas que ce comportement est souhaitable.

Prenons un exemple fictif de réservation, utilisé dans la suite de cet article. Avant de réorganiser le code, observez une réservation confirmée, une annulation et une demande répétée après une coupure réseau. Enregistrez les réponses et les effets produits : état de la réservation, écriture en base, notification envoyée.

En parallèle, faites valider les résultats attendus par le métier. Si le comportement actuel autorise deux confirmations pour la dernière place, conservez la reproduction du défaut et écrivez un test du résultat corrigé. Un bug connu ne doit pas devenir une exigence sous prétexte de préserver l’existant.

La testabilité s’améliore quand les dépendances peuvent être contrôlées. Séparez le calcul d’une échéance de la lecture de l’heure, et la décision de confirmer de l’appel au prestataire de paiement. Testez les règles sans réseau ; vérifiez aussi les vrais adaptateurs et contraintes de base dans des tests d’intégration.

  • Règles métier : expiration, annulation, remboursement partiel, changement de tarif.
  • Intégrations : concurrence sur la dernière place, réponse tardive, événement reçu deux fois.
  • Parcours critiques : confirmation visible par le bon utilisateur, accès refusé depuis une autre organisation.

Pour le CTO, le premier résultat attendu est une modification utile livrée sous protection de ces tests. Le pourcentage global de couverture peut compléter ce constat ; il ne remplace pas la vérification des risques du produit.

2. Établir un langage métier partagé

Une application peut appeler la même chose « booking » dans l’interface, « order » dans l’API et « session » dans la base. Elle peut aussi employer « client » pour une personne connectée, une organisation et un compte de facturation. Cette ambiguïté finit par toucher les permissions et les règles de gestion.

Le langage partagé du Domain-Driven Design, présenté par Martin Fowler à partir des travaux d’Eric Evans, rapproche les mots des développeurs de ceux des experts métier. Il évolue avec la compréhension du domaine.

Pour notre réservation fictive, un premier atelier pourrait produire ceci :

TermeSignification retenueRègle à vérifier
HoldUne place temporairement retenuePossède une échéance explicite
BookingUne réservation confirméeRespecte la capacité disponible
PaymentUne opération de paiementSon état ne se confond pas avec celui de la réservation
OrganizationLe périmètre d’accès d’une équipeUne organisation ne lit pas les réservations d’une autre

Ces définitions doivent être validées pour le produit concerné. Un paiement échoué annule-t-il la réservation ou ouvre-t-il un délai de régularisation ? Le code seul ne permet pas de décider ce que l’entreprise veut faire.

Reportez les termes retenus dans les types, les opérations, les tests et la documentation du domaine. Gardez une traduction explicite pour les anciennes API. Deux domaines peuvent légitimement utiliser des mots différents : les fusionner artificiellement créerait une nouvelle ambiguïté.

Un agent de code doit recevoir ces définitions et les invariants associés avant de proposer un changement. Cela donne aussi au reviewer un critère concret pour accepter ou refuser la proposition.

3. Créer des modules profonds, avec des contrats simples

Un module profond rassemble une capacité importante derrière une interface relativement simple. Dans son échange avec Robert C. Martin, John Ousterhout explique pourquoi multiplier les petites fonctions peut disperser la complexité au lieu de la réduire.

Dans notre exemple, chaque écran pourrait actuellement vérifier la disponibilité, calculer le tarif, créer une réservation et envoyer une notification. Ajouter des fichiers « helpers » laisse encore tous les appelants responsables du bon enchaînement.

Une opération métier telle que confirmBooking peut exposer un contrat plus utile : identité authentifiée, réservation concernée, clé d’idempotence et résultats possibles. Le module coordonne les règles de confirmation ; l’appelant sait aussi distinguer une place indisponible, un refus d’accès et un paiement encore en attente.

Une interface courte ne suffit pas. Le contrat doit préciser les effets et les échecs. Une transaction locale ne rend pas atomique un appel à un prestataire externe : l’état intermédiaire, la reprise après échec et la prévention des doublons doivent rester explicites.

Cherchez des responsabilités cohérentes : réservation, facturation, identité. Elles peuvent vivre dans le même déploiement. Extraire des microservices ajouterait des contraintes de réseau et d’exploitation qu’il faut justifier séparément.

Critère de validation : une évolution des règles de confirmation modifie le module et ses tests ; ses appelants restent stables tant que le contrat ne change pas. Le nombre de fichiers ou leur longueur apporte peu d’information sans cette vérification.

4. Expliquer les décisions surprenantes avec des ADR

Le code indique comment une solution fonctionne, mais laisse parfois son motif invisible. Pourquoi conserver deux identifiants ? Pourquoi traiter un événement de manière asynchrone ? Pourquoi accepter temporairement deux formats ?

Un Architecture Decision Record, ou ADR, conserve une décision significative, son contexte, son statut et ses conséquences. Michael Nygard propose des documents courts, versionnés avec le code, dont les anciennes décisions restent accessibles lorsqu’elles sont remplacées.

Voici le contenu possible d’un ADR pour notre exemple fictif :

  • Contexte : le prestataire peut livrer plusieurs fois le même événement de paiement.
  • Décision : enregistrer l’identifiant de l’événement et rendre son traitement idempotent.
  • Option écartée : supposer que chaque livraison correspond à un nouveau paiement.
  • Conséquences : définir l’unicité en base, la reprise après échec et les tests de livraisons concurrentes.
  • Statut : accepté, avec un lien vers l’implémentation et les tests correspondants.

Lors d’une reprise, un agent peut aider à retrouver les indices d’une décision. S’il manque l’historique, indiquez que le motif reste à confirmer. Une justification inventée aujourd’hui ne constitue pas la mémoire du projet.

Réservez les ADR aux choix structurants. Une condition locale peut simplement demander un nom plus précis ou un commentaire expliquant la contrainte. Le livrable utile est celui qui évite qu’un futur changement supprime une protection mal comprise.

5. Automatiser les migrations répétitives

Une fois le contrat cible validé, il reste parfois des dizaines d’appels à modifier. C’est un bon candidat pour un codemod : une transformation de code que l’on peut examiner, tester et rejouer.

jscodeshift fournit des outils pour transformer plusieurs fichiers JavaScript ou TypeScript à partir de leur structure syntaxique. Cette approche permet de cibler des formes de code plutôt que de remplacer indistinctement du texte.

Dans notre exemple, une transformation pourrait remplacer les appels à l’ancien service de réservation dont les paramètres correspondent au nouveau contrat. Elle doit laisser les cas ambigus à une revue manuelle. Un arbre syntaxique ne prouve pas, à lui seul, que deux opérations ont le même sens métier.

  • Tester la transformation sur des exemples avant/après, y compris les fichiers qu’elle doit ignorer.
  • Examiner une simulation sur un petit périmètre et vérifier imports, alias et signatures.
  • Appliquer par lots, puis exécuter typage, tests et revue du diff.
  • Vérifier qu’une seconde exécution ne modifie plus le résultat et recenser les appels restants.

Une migration du code ne migre pas automatiquement les données. Pour un changement d’API ou de schéma incompatible, le pattern Parallel Change décrit par Danilo Sato distingue trois phases : étendre, migrer, retirer l’ancien contrat.

Concrètement, introduisez le nouveau format compatible avec la transition, migrez les consommateurs et les données, puis vérifiez qu’aucun ancien lecteur ou écrivain ne subsiste. La suppression vient ensuite. Si l’ancien et le nouveau système écrivent simultanément, définissez aussi comment détecter et corriger les divergences.

Le retour arrière doit couvrir les données transformées et les effets externes. Revenir au commit précédent ne suffit pas après une suppression de colonne ou l’envoi d’une notification.

Ce que le CTO doit arbitrer

La décision se prend par capacité métier. Une interface utilisable peut être conservée alors que le module de permissions doit être remplacé. La modernisation progressive décrite par Martin Fowler avec Strangler Fig fournit un cadre pour remplacer le système par étapes et vérifier les résultats au fil de la transition.

État observéDécision possiblePreuve attendue
Comportement compris, stable et vérifiéConserverLe prochain changement reste local et testable
Règles fiables, dépendances trop coupléesRefactorer progressivementLes tests de comportement restent valides
Sous-système fragile avec frontière identifiableIsoler puis remplacerContrat et stratégie de migration vérifiés
Modèle incompatible avec les besoins, reprise trop coûteuseÉvaluer une réécriture du périmètreComparaison incluant données, transition et exploitation

Avant de financer une reprise complète, choisissez un pilote borné : par exemple, fiabiliser la confirmation d’une réservation et livrer une modification réelle de sa règle. Faites estimer séparément compréhension, sécurisation, refactoring et migration. Notez les inconnues et fixez un point de réévaluation.

Suivez le temps nécessaire pour livrer ce changement, les régressions, le travail de revue et la capacité de l’équipe à diagnostiquer un échec. Un dépôt avec davantage de tests et de documents, mais toujours impossible à modifier sereinement, n’a pas encore atteint l’objectif.

Continuer avec l’IA après la reprise

Les agents restent utiles pour cartographier les dépendances, proposer des scénarios limites et préparer les transformations répétitives. Demandez-leur des références précises aux fichiers, des hypothèses explicites et des changements suffisamment petits pour être relus.

Les résultats attendus d’un test doivent provenir des règles validées ou d’un comportement observé et compris. Faire générer l’implémentation et son évaluation à partir de la même supposition peut simplement reproduire l’erreur deux fois.

Le premier objectif de la reprise est concret : une autre personne de l’équipe peut expliquer, modifier, tester et déployer une capacité métier sans redécouvrir toute l’application. Les cinq chantiers servent cette autonomie.

Pour préparer une reprise avec Appik Studio, présentez-nous le parcours qui bloque et la prochaine évolution attendue. Nous pourrons cadrer l’analyse autour de ce changement, des risques associés et des parties du produit à conserver.

Sources et références

Retour au blogGaspard Chevassus · CEO, Appik Studio

CONTACT

contact@appik-studio.ch
+41 78 693 58 72

APPIK STUDIO

Avenue de Béthusy 26,

1005, Lausanne, Suisse.

46.52°N · 6.63°E

facebook logo iconlinkedin logo icon

Appik Studio SARL, Copyright © 2026|Politique de confidentialité|À propos

Appik Studio est une équipe senior basée à Lausanne. Nous concevons et développons des applications mobiles, web et IA pour des startups, des laboratoires de recherche et des institutions suisses.