Tout développeur l'a entendu : « Don't Repeat Yourself ». C'est l'un des premiers principes qu'on apprend, et il semble si raisonnable qu'on le remet rarement en question. Du code dupliqué ? On l'extrait. Un pattern ? On l'abstrait. Trois lignes similaires ? Une fonction utilitaire.
Mais après 16 ans de développement logiciel dans différentes industries et pays — des plateformes e-learning à Rome aux systèmes de trading financier à Zurich — je suis arrivé à une conclusion différente : YAGNI — « You Aren't Gonna Need It » — est le principe le plus précieux, et l'adhérence aveugle à DRY nuit activement aux codebases.
Le piège DRY
DRY a été introduit par Andy Hunt et Dave Thomas dans « The Pragmatic Programmer ». Leur définition originale concernait le savoir : « Every piece of knowledge must have a single, unambiguous, authoritative representation within a system. » Notez le mot : savoir, pas code.
Ce que la plupart des développeurs pratiquent n'est pas DRY — c'est « Don't Repeat Code », ce qui est fondamentalement différent. Deux morceaux de code peuvent sembler identiques aujourd'hui mais représenter des concepts métier totalement différents qui divergeront demain.
J'ai vu cela se produire de nombreuses fois : la logique de validation pour deux flux différents semble identique au départ. Un développeur bien intentionné les fusionne dans un utilitaire partagé. Des mois plus tard, des changements réglementaires ou des décisions produit exigent des règles différentes pour chaque flux, et démêler cet utilitaire partagé signifie toucher chaque appelant, réécrire les tests et coordonner les déploiements entre équipes.
// These look the same, but they're NOT the same knowledge
function validateUserEmail(email: string) {
return email.includes('@') && email.length > 5;
}
function validateNewsletterEmail(email: string) {
return email.includes('@') && email.length > 5;
}
// Merging them into validateEmail() creates coupling
// between user registration and newsletter signup.
// When newsletter needs to accept '+' aliases but
// registration doesn't, you'll fight the abstraction.Pourquoi YAGNI gagne
YAGNI dit : ne le construis pas avant d'en avoir besoin. N'abstrais pas avant d'avoir vu le vrai pattern. Ne généralise pas avant de comprendre les cas spécifiques. Ce n'est pas de la paresse — c'est de la discipline.
Le coût d'une mauvaise abstraction est bien plus élevé que celui de la duplication. La duplication est évidente et locale — on la voit, et la corriger est simple. Une mauvaise abstraction est subtile et virale — elle façonne la façon dont les gens pensent le code, et la défaire signifie refactoriser chaque appelant.
Je suis la « Rule of Three » : n'abstrais pas avant d'avoir vu trois utilisations véritablement indépendantes. Et même alors, demande-toi si la duplication représente le même savoir ou juste du code qui se ressemble.
Chez Migros, quand nous avons reconstruit Bikeworld et Micasa sur un monorepo Next.js partagé, la tentation de tout partager entre les boutiques était énorme. Mais les pages produit pour les vélos et les meubles ont des parcours utilisateur fondamentalement différents. Nous avons gardé les composants séparés jusqu'à ce que de vrais patterns partagés émergent naturellement — et le résultat était une codebase où chaque boutique pouvait évoluer indépendamment sans coordonner les releases.
Le vrai coût de l'abstraction prématurée
J'ai vu ce pattern se répéter des dizaines de fois dans les équipes que j'ai dirigées — des petites agences en Italie aux équipes enterprise chez AXA et UBS. Quelqu'un crée un composant ou utilitaire « partagé » tôt. Il fonctionne très bien pour deux cas d'usage. Puis un troisième arrive qui convient presque mais nécessite un flag. Puis un quatrième qui nécessite un autre flag. Bientôt, on a une fonction avec six paramètres booléens, et personne ne comprend ce qu'elle fait réellement.
J'appelle cela la « dette d'abstraction ». Contrairement à la dette technique, visible dans vos temps de build et listes de dépendances, la dette d'abstraction se cache dans la vélocité de votre équipe. Les développeurs ralentissent parce qu'ils ont peur de modifier le code partagé. Les nouvelles features prennent plus de temps parce qu'elles doivent contourner des abstractions conçues pour d'autres cas d'usage.
// The abstraction graveyard — we've all seen this
function formatData(
data: unknown,
isUser?: boolean,
isAdmin?: boolean,
includeMetadata?: boolean,
skipValidation?: boolean,
legacyMode?: boolean
) {
// 200 lines of branching logic
// that nobody dares to touch
}YAGNI en pratique
Voici comment j'applique YAGNI dans les décisions quotidiennes :
En construisant la plateforme Vontobel Markets, nous avions besoin de mises à jour de prix en temps réel via WebSockets. Le premier instinct était de construire une couche de données temps réel générique pour tout futur cas de streaming. Au lieu de cela, nous avons construit exactement ce dont le ticker de prix avait besoin — rien de plus. Quand une deuxième feature temps réel est arrivée (alertes portfolio), nous comprenions assez bien les deux cas pour concevoir quelque chose qui servait véritablement les deux, plutôt que de deviner à l'avance.
Chez UBS, en unifiant l'application des Administrative Officers, j'ai activement déconseillé de créer un « framework de formulaires universel » qui gérerait chaque formulaire du système. Au lieu de cela, chaque équipe a construit ses formulaires selon ses besoins, et nous avons identifié les vrais patterns partagés seulement après que plusieurs équipes avaient livré. Les patterns que nous avons finalement extraits étaient plus simples et robustes que tout ce que nous aurions pu concevoir à l'avance.
Ce que je dis à mes équipes
Quand j'intègre des développeurs, je partage ce modèle mental : la duplication est bien moins chère que la mauvaise abstraction. Copie-colle ces trois lignes. Laisse le pattern émerger naturellement. Quand tu as vu le même concept — pas le même code, le même concept — apparaître trois fois ou plus, alors considère si une abstraction clarifierait ou obscurcirait.
« Make sense » est l'un de mes principes fondamentaux. Chaque décision doit avoir du sens dans son contexte, pas simplement suivre une règle. DRY a du sens quand on encode véritablement un savoir partagé. YAGNI a du sens presque partout ailleurs.
Le meilleur code que j'ai livré n'était pas le plus astucieux ni le plus DRY. C'était le code où chaque partie exprimait clairement son intention, où on pouvait changer une chose sans craindre d'en casser cinq autres, et où les nouveaux membres de l'équipe pouvaient le comprendre sans visite guidée.
La prochaine fois que tu cherches un utilitaire partagé, fais une pause. Demande-toi : « Est-ce que j'abstrais parce que je vois un vrai pattern, ou parce qu'on m'a dit que la répétition c'est mal ? » Cette pause vaut plus que n'importe quel design pattern.

