Dé-slop : rendre le code généré indiscernable de celui d'un humain attentif
Le slop n'est pas un problème de style, c'est un problème de confiance. Les réviseurs qui en repèrent un arrêtent de lire le code et commencent à en chercher d'autres. La correction n'est jamais uniquement cosmétique : chaque passage ci-dessous vérifie la nécessité, pas seulement l'apparence.
Travaillez à partir du diff réel, jamais de mémoire de ce que vous avez écrit. Si le travail s'étend sur plusieurs branches, auditez le diff de chaque branche par rapport à sa base de fusion.
Passe 0 — rédigez en petites parties, justifiez chaque ligne (la prévention bat le nettoyage)
Le slop est le moins coûteux à supprimer avant qu'il n'existe. Lors de la construction :
- Construisez pièce par pièce. Commencez par le plus petit changement qui fait une chose ; rendez-le correct et idiomatique avant d'ajouter la pièce suivante. Un grand diff écrit d'un seul coup accumule toujours du slop ; N petites incrémentations, chacune relue selon cette compétence, ne le font pas. Cela produit également des PRs de petite taille, que les réviseurs font systématiquement plus confiance et approuvent plus rapidement qu'une grosse PR.
- Interrogez chaque ligne au moment de sa création : pourquoi cette ligne existe-t-elle ? Pourquoi est-ce une nouvelle fonction plutôt qu'un appel à une fonction existante ? Pourquoi un nouveau fichier ? Si la réponse est « la génération a coulé de cette façon », supprimez ou intégrez-la. Chaque ajout a besoin d'une raison que vous pourriez énoncer à voix haute lors de la relecture.
- Ne compliquez pas les choses. La version évidente de 5 lignes bat la version abstraite de 25 lignes jusqu'à ce qu'un deuxième appelant existe. Pas de paramètres spéculatifs, pas de « pour une flexibilité future », pas de types wrapper autour d'une seule valeur.
- Ne réinventez pas la roue — au moment de la rédaction, pas seulement lors du nettoyage : avant d'écrire un utilitaire, cherchez dans le dépôt une aide existante et vérifiez l'arbre des dépendances pour un package qui possède le problème (voir Passe 2).
- Adaptez-vous au voisinage avant d'écrire. Lisez d'abord les fichiers adjacents ; adoptez leurs conventions de nommage, de gestion des erreurs et de tests d'intégration pour que le nouveau code donne l'impression d'avoir toujours été là.
Si la tâche ne peut pas être construite pièce par pièce (un gros portage, un contrat externalisé), dites-le et compensez par un audit plus strict des Passes 1 à 5 avant que quiconque d'autre ne le voie.
Passe 1 — commentaires
Le plus grand indicateur. Appliquez une règle : un commentaire doit énoncer une contrainte que le code ne peut pas montrer. Tout le reste est supprimé.
Supprimez sans hésitation :
- La narration :
// parcourir les entrées,// appeler l'aide,// retourner le résultat - Le fait de reformuler le code ou son propre en-tête de documentation une deuxième fois dans le corps
- Le discours de relecteur :
// c'est sûr parce qu'on a vérifié ci-dessus,// notez que...— c'est vous qui défendez le diff, pas qui informez le prochain lecteur - Les références à la PR, à la relecture, à la conversation, ou à « récemment modifié »
- Les commentaires expliquant pourquoi la modification est correcte (appartient au corps de la PR)
- Les bannières de section (
// ---- aides ----) dans les fichiers de moins d'environ 300 lignes
Conservez (ce sont des éléments porteurs) :
- Les contraintes de format filaire ou de protocole, en particulier celles rétroconçues sans spécification publique : le champ X doit être présent même s'il est nul ; le client Y rejette toute la charge utile si Z manque ; citez le fichier source en amont
- Les commentaires « pourquoi pas » : pourquoi l'approche évidente a été rejetée, ce qui casse
- Les faits de plateforme sur lesquels un lecteur trébuchera : cette variable d'environnement est une convention Unix ; cette API ne fait silencieusement rien sous Windows
- Les invariants de sécurité/protection des données : ne mettez jamais en cache l'enregistrement brut, il contient des secrets
- Les ancrages de politique délibérés qui contredisent les valeurs par défaut en amont, avec la condition de levage
Heuristique de densité, pas une règle : pour le code de colle/CRUD, plus d'environ 1 ligne de commentaire par 15 lignes ajoutées mérite un second regard. Pour le code de protocole non documenté, une densité élevée peut être correcte — les commentaires SONT la spécification. Jugez chaque commentaire par les listes conserver/supprimer, jamais uniquement par le nombre.
En-têtes de documentation : 4 à 8 lignes de contraintes pures. Si un en-tête est un paragraphe racontant ce que le module fait étape par étape, réduisez-le à ce que le nom du fichier et les exportations ne peuvent pas déjà dire.
Passe 2 — code fait à la main alors qu'une dépendance ou une bibliothèque standard le fournit déjà
Le deuxième plus grand indicateur : réimplémenter uuid, le hachage, l'analyse sémantique, la correspondance de glob, les calculs de dates, la fusion profonde.
Procédure :
- Vérifiez de quoi dépend déjà le paquet (lisez package.json, pas de mémoire). Préférez une dépendance existante ou la bibliothèque standard d'exécution plutôt que d'en ajouter une.
- Si une nouvelle dépendance est justifiée, choisissez la plus éprouvée et ennuyeuse.
- Avant de remplacer une implémentation manuelle existante, prouvez l'équivalence de manière empirique — exécutez les deux sur les mêmes entrées et comparez les sorties. Le code d'identifiant déterministe et de hachage en particulier : un échange qui modifie les sorties casse silencieusement l'idempotence pour les utilisateurs existants.
- Si garder la version faite à main est vraiment correct (évite une dépendance pour 10 lignes), attendez-vous à la question du relecteur et décidez si l'argument vaut plus que la dépendance. Généralement non : l'ennuyeux gagne en relecture.
- Exception : le code qui est déjà une composition de bibliothèque standard (createHash + pipeline) n'est pas fait à la main. Dites-le si on vous le demande ; ne l'enveloppez pas davantage.
Passe 3 — cohésion et nécessité
Le slop s'accumule : chaque édition ajoute sans consolider. Cherchez :
- Des expressions conditionnelles répétées → extrayez une fois, nommez par signification (
pasDeChangementsConfig, pasverif1) - Le même littéral dans N fichiers → une constante partagée dans le module qui possède le concept ; les adoptants l'importent
- Des réimplémentations locales d'aides du dépôt → cherchez une aide existante avant de garder une copie privée (
cheminExiste, utilitaires de formatage/sortie, aides d'erreur). Supprimez la copie locale, importez la partagée. - Du code mort : pour chaque aide/type/exportation dans le diff, trouvez un consommateur. Pas de consommateur → supprimez maintenant, pas « pour plus tard ».
- Des sites d'appel qui réimplémentent ce qu'une aide possède (espacement, citation, génération d'ID) → déplacez le comportement dans l'aide, allégez les sites d'appel
- Le même fait énoncé deux fois (en-tête de documentation + commentaire en ligne) → gardez-en un
- Des fonctions qui retournent des tuples de valeurs faiblement liées → souvent un signe que deux responsabilités ont été fusionnées ; divisez ou documentez le contrat
Ensuite, vérifiez l'adéquation au dépôt : lisez les fichiers voisins et adaptez leur idiome, leur nommage, leur style d'erreur et leurs modèles de test. Le code qui ignore le style de la maison a l'air généré même lorsqu'il est correct.
Passe 4 — tests
- Les tests doivent fixer le comportement, pas le bogue. Si une assertion encode la mauvaise valeur « parce que c'est ce que fait le code », corrigez les deux.
- Miroir de la suite existante de harnais et d'aides ; n'inventez pas un style de simulation parallèle dans le même fichier.
- Chaque saut spécifique à une plateforme comporte une raison d'une ligne.
- Les noms de tests décrivent le scénario, pas l'implémentation.
- Lorsque vous modifiez la forme de la sortie, ajoutez une assertion négative pour la forme supprimée.
Passe 5 — parité des outils, puis vérifiez
- Utilisez la version du formateur/linteur épinglée dans le dépôt (lisez package.json — exécuter une version majeure différente en local laisse passer des échecs uniquement CI).
- Exécutez les tests que le diff touche à chaque couche d'un changement empilé, pas seulement le sommet.
- Révisez le diff final une fois de plus après toutes les modifications :
git diffet lisez chaque ligne de commentaire restante à voix haute par rapport à la Passe 1. Vérification de densité :git diff | grep -cE '^\+\s*(//|\*)'par rapport au nombre total de lignes ajoutées. - Messages de commit : expliquez pourquoi, en prose, comme une personne. Pas de journaux de modifications sous forme de liste à puces pour un commit de 3 lignes, pas de « amélioré/optimisé/robuste ».
Rapports
Lorsqu'on vous demande « est-ce dé-sloppé ? » : auditez le diff en direct et répondez avec des preuves (chiffres de densité, ce qui a été supprimé, ce qui a été délibérément conservé et pourquoi), jamais « oui » de mémoire. Si quelque chose a été conservé qu'un relecteur pourrait signaler — comme un fichier de protocole à haute densité — nommez-le de manière proactive et donnez la défense en une phrase.
Lorsqu'un relecteur qualifie quelque chose de slop : concédez le motif avant de défendre une instance. Corrigez la catégorie partout, y compris dans les fichiers qu'il n'a pas signalés (et ceux qu'il a loués). Appliquer la norme comme une discipline, pas comme une gestion des dégâts sur les lignes signalées, est ce qui rétablit la confiance.