Principe YAGNI, Comment écrire du code de qualité en évitant les fonctionnalités inutiles
YAGNI : Comment écrire du code de qualité en évitant les fonctionnalités inutiles
Introduction : Qu’est-ce que YAGNI ?
Audit d’une plateforme bancaire l’an dernier. Trois jours pour cartographier le code mort : près de 30 % de la base ne répondait à aucun besoin actif. Des modules de conversion multi-devises ajoutés "au cas où" cinq ans plus tôt, jamais activés. Une couche d’abstraction sur la persistence prête à supporter trois bases différentes (une seule en production). Chaque livraison ralentie par ce poids mort, chaque onboarding rallongé d’une semaine pour expliquer à quoi servaient des classes que personne n’avait touchées depuis 2019.
Ce gaspillage a un nom et un antidote : YAGNI (You Aren’t Gonna Need It). Formulé par Kent Beck dans le cadre de l’Extreme Programming, c’est l’un des piliers du software craftsmanship. La règle tient en une ligne : n’écrivez pas le code dont vous pensez avoir besoin demain, écrivez celui dont vous avez besoin aujourd’hui.
Cet article montre comment l’appliquer concrètement en Java, où repérer les ajouts superflus, et comment résister à la tentation d’anticiper.
Ce que YAGNI vous évite vraiment
Trois conséquences directes, observées sur le terrain.
Chaque fonctionnalité prématurée alourdit la base : plus de classes à lire, plus de chemins à tester, plus de surfaces où loger des bugs. Multipliez par cinq ans d’accumulation et vous obtenez la situation décrite plus haut : 30 % de code qui ne sert à rien mais que tout le monde doit comprendre. C’est de la dette technique pure, contractée pour rembourser un emprunt qui n’a jamais été demandé.
Inversement, moins de code écrit, c’est moins de tests à maintenir, moins de revues à instruire, moins de couplage à gérer le jour où le vrai besoin émerge. Un module minimal s’adapte. Un module sur-conçu pour un futur fantasmé doit d’abord être démêlé avant d’être modifié, et personne n’ose y toucher.
Vous voulez savoir, avant d'écrire une ligne, si elle est vraiment nécessaire ?
Résister à l'envie d'anticiper un besoin, ça ne se décrète pas en lisant un article : ça se travaille sur votre propre code. En mentoring 1:1, je relis vos PR avec vous et on traque ensemble chaque abstraction prématurée, chaque paramètre "au cas où". Vous développez le réflexe d'écrire juste ce qu'il faut, et rien de plus.
Comment repérer une fonctionnalité superflue
Trois questions suffisent en général. Si vous répondez "non" à la première et "oui" aux deux autres, vous tenez un candidat à supprimer ou à ne pas écrire.
- Existe-t-il aujourd’hui un cas d’usage concret, validé, qui exige cette fonctionnalité ? Pas un cas hypothétique évoqué en réunion il y a six mois, mais un besoin actif, daté, avec un utilisateur ou un client identifié.
- L’application fonctionnerait-elle correctement sans cette fonctionnalité ? Si oui, c’est qu’elle n’en a pas besoin maintenant.
- Cet ajout complique-t-il la lecture, les tests ou la maintenance du code existant ? Une option supplémentaire, un paramètre "au cas où", une couche d’abstraction préventive : chacun de ces choix a un coût immédiat pour un bénéfice incertain.
Quand la pression vient d’un client ou d’un manager qui demande une fonctionnalité "pour plus tard", la conversation à avoir est simple : qui en a besoin, à quelle date, et que coûte-t-il d’attendre que ce besoin soit confirmé ? Dans neuf cas sur dix, la demande s’évapore.
Exemples concrets en Java
Prenons un exemple simple en Java où vous pourriez être tenté d’ajouter une fonctionnalité inutile :
// Exemple où une fonctionnalité inutile est ajoutée
public class User {
private String name;
private int age;
private String address; // Cette information n'est pas encore utilisée
public User(String name, int age) {
this.name = name;
this.age = age;
// On pourrait être tenté d'ajouter l'adresse dès maintenant, mais YAGNI !
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
// On pourrait ajouter un getter pour l'adresse ici, mais ça serait prématuré.
}
Dans cet exemple, l’attribut address est inutile tant que le programme n’en a pas besoin. Selon YAGNI, ne l’ajoutez pas avant d’avoir une demande précise pour cette fonctionnalité.
Mettre YAGNI en pratique au quotidien
Appliquer YAGNI demande de la discipline et un cadre. Voici les leviers qui fonctionnent dans les équipes que j’accompagne.
1. Laisser les tests piloter le code
L’approche la plus efficace pour ne pas écrire de code spéculatif reste le Test-Driven Development (TDD). Un test d’abord, puis juste assez de code pour le faire passer. Le mécanisme oblige à rester sur le besoin réel : si aucun test ne le justifie, le code n’existe pas.
Exemple en Java :
@Test
public void testAddUser() {
User user = new User("Alice", 30);
assertEquals("Alice", user.getName());
assertEquals(30, user.getAge());
}
Avec ce test, vous vous concentrez uniquement sur l’ajout de l’utilisateur avec un nom et un âge. Tant qu’il n’existe pas de test nécessitant l’adresse, n’ajoutez pas d’attribut address à la classe User.
2. Évitez de généraliser trop tôt
Un autre piège commun est de vouloir tout de suite rendre votre code trop générique ou flexible. Par exemple, vous pourriez penser qu’une méthode pourrait être réutilisée plus tard et vouloir la rendre paramétrable. Mais en réalité, si cette flexibilité n’est pas nécessaire maintenant, elle pourrait ne jamais l’être.
Exemple à éviter :
public class MathOperations {
// On pourrait être tenté de rendre cette méthode très générique
public int multiply(int a, int b, boolean absoluteValues) {
if (absoluteValues) {
return Math.abs(a) * Math.abs(b);
} else {
return a * b;
}
}
}
Cette méthode introduit de la complexité inutile (avec le paramètre absoluteValues) si votre programme n'a besoin que de multiplier des nombres sans se préoccuper de leur signe. La solution YAGNI serait de garder la méthode simple :
public class MathOperations {
public int multiply(int a, int b) {
return a * b;
}
}
3. Refactoriser pour supprimer, pas seulement pour ajouter
Le refactoring sert aussi à retirer ce qui n’a jamais servi. Un projet évolue, certaines parties ajoutées dans l’anticipation ne sont jamais activées. Une revue trimestrielle suffit pour identifier les classes orphelines, les méthodes jamais appelées, les options jamais cochées, et les supprimer sans cérémonie.
4. Trancher en équipe sur le besoin réel
Quand une nouvelle fonctionnalité est proposée, une seule question à poser en stand-up : qui en a besoin maintenant ? Si la réponse est "personne, mais ça pourrait servir", la fonctionnalité retourne dans le backlog. Pas de débat, pas de compromis. Le backlog est fait pour ça.
Les deux pièges classiques
Sur le terrain, deux dérives reviennent constamment.
La première est le "juste au cas où" déguisé en bonne pratique. Un développeur ajoute une couche de gestion multi-devises dans une application qui ne traite que des euros, parce qu’"on ne sait jamais". Trois ans plus tard, l’app traite toujours des euros, mais chaque modification du module de paiement doit composer avec une abstraction qui n’a jamais servi. La majorité des scénarios anticipés ne se présentent pas, et ceux qui se présentent ressemblent rarement à ce qu’on avait imaginé.
La deuxième dérive est l’inverse : confondre YAGNI avec un refus d’anticiper. YAGNI n’interdit pas d’adapter le code quand un besoin réel émerge. Si un client demande une fonctionnalité confirmée et planifiée, on l’implémente. La discipline porte sur les besoins spéculatifs, pas sur l’évolution légitime du produit. Le critère est simple : un besoin formulé, daté, attribué à un utilisateur identifié, pas un "ce serait bien si" entendu en couloir.
YAGNI n'est qu'une pratique parmi les 100 qui font un code propre
Cet article décortique une discipline : ne pas écrire le code dont vous n'avez pas besoin aujourd'hui. Le Craft Bundle réunit les 100 pratiques que j'applique au quotidien pour coder propre, savoir quand simplifier, quand refactoriser, quand s'arrêter. Ce sont celles que l'IA ne vous apprendra jamais, parce qu'elle ne les a jamais vues tenir sur cinq ans de production.
Questions fréquentes sur YAGNI
YAGNI veut-il dire "ne jamais anticiper" ?
Non. YAGNI cible le code écrit pour des besoins non confirmés. Si vous savez avec certitude qu’une fonctionnalité sera livrée dans deux semaines parce qu’elle est validée et planifiée, l’ignorer serait absurde. La règle s’applique aux "au cas où", pas aux engagements pris.
Comment l’expliquer à un client qui demande des fonctionnalités "pour plus tard" ?
Sortez les chiffres. Une fonctionnalité ajoutée prématurément coûte trois fois : à l’écriture, à la maintenance, et au moment où il faudra la retirer ou la modifier parce que le besoin réel ne correspond pas à ce qui a été imaginé. Proposez plutôt de garder le besoin dans le backlog et de l’implémenter quand il sera confirmé, avec une meilleure compréhension du contexte réel.
"Si je ne l’ajoute pas maintenant, je devrai tout refaire plus tard", vraiment ?
Cette peur est compréhensible mais le terrain la dément. Un code minimal est plus facile à étendre qu’un code sur-conçu. Quand le besoin réel arrive, il diffère presque toujours de ce qui avait été anticipé : l’abstraction préventive devient un obstacle, pas un raccourci.
YAGNI et architectures évolutives : compatibles ?
Oui. YAGNI ne s’oppose pas à la qualité ni au design : il s’oppose à la spéculation. Vous pouvez parfaitement appliquer SOLID, écrire des interfaces propres et concevoir des modules cohérents sur le code que vous avez besoin d’écrire aujourd’hui. La différence est qu’on n’invente pas de points d’extension pour des extensions qui n’existent pas encore.
Conclusion
YAGNI ne rend pas votre code meilleur : il vous évite simplement de l’aggraver avec des fonctionnalités que personne n’a demandées. La discipline est moins intuitive qu’il n’y paraît, parce qu’elle suppose d’accepter une forme d’inconfort : ne pas écrire le code qu’on aurait envie d’écrire, ne pas anticiper ce qu’on imagine utile, faire confiance au backlog pour rattraper le besoin quand il sera réel. C’est cette retenue qui distingue les bases de code qui vieillissent bien des autres.
Ressource gratuite : Votre équipe livre-t-elle aussi vite qu'elle le pourrait ?
30 questions, 5 dimensions, score sur 100. Mesurez la maturité engineering de votre équipe avec le benchmark utilisé dans des DSI de 50 à 800+ développeurs, et identifiez vos 3 chantiers prioritaires.


