Aller au contenu principal
LaPolaris lance ses formations. 40% de réduction jusqu'au 30 juin En savoir plus

KISS : pourquoi la simplicité est la compétence technique la plus difficile à maîtriser

Tout le monde sait que le code simple est meilleur. Pourtant, la complexité s'accumule à chaque sprint. Ce n'est pas un problème de connaissance, c'est un problème de pratique.

Architecture logicielle ·
Adel LATIBI
Adel LATIBI
KISS : pourquoi la simplicité est la compétence technique la plus difficile à maîtriser

KISS signifie Keep It Simple, Stupid. La formulation est directe, presque agressive. C'est voulu. Le principe a été formulé dans les années 60 par Kelly Johnson, ingénieur en aéronautique chez Lockheed, qui estimait qu'un système bien conçu devait pouvoir être réparé par un mécanicien ordinaire, sur le terrain, avec des outils basiques. Pas par une équipe de spécialistes en conditions idéales.

Ce principe a été repris dans le développement logiciel et il y est peut-être encore plus pertinent qu'en mécanique. Dans notre domaine, la complexité ne coûte pas seulement en maintenance. Elle coûte en bugs, en incompréhensions entre développeurs, en temps de débogage, en onboarding raté, en features livrées avec du retard parce que personne ne voulait toucher à ce module que tout le monde trouvait trop compliqué.

Cet article n'est pas une énième définition de KISS. Il s'attaque à un problème concret : pourquoi la complexité revient toujours malgré les bonnes intentions, et comment la combattre de façon durable.

"La simplicité est la sophistication ultime."

Leonard de Vinci. Pas un développeur, mais l'intuition reste valide.

Le vrai problème : la complexité se justifie toujours

Personne ne choisit délibérément de rendre son code complexe. Chaque décision qui mène à la complexité est prise pour une bonne raison : "ce design pattern rend le code plus extensible", "cette abstraction évite la duplication", "ce niveau d'indirection protège contre un couplage trop fort".

Le problème n'est pas la décision individuelle. C'est l'accumulation. Cent décisions individuellement justifiées peuvent produire un système incompréhensible dans son ensemble. C'est ce qu'on appelle parfois la dette de conception : pas un seul mauvais choix, mais une série de compromis qui finissent par se contraindre mutuellement.

KISS demande un effort different de YAGNI ou DRY. YAGNI dit "n'écrivez pas ce qui n'est pas demandé". DRY dit "ne répétez pas". KISS dit quelque chose de plus subtil : "si votre solution actuelle est difficile à expliquer en deux phrases, elle est probablement trop complexe, même si elle fonctionne."

Ce critère de lisibilité est plus difficile à mesurer que le nombre de lignes ou la couverture de tests. C'est pourquoi KISS est si fréquemment violé malgré la bonne volonté des équipes.

Les formes concrètes de complexité inutile

La hiérarchie de classes à sept niveaux

L'héritage est un outil puissant. Mal utilisé, il crée des chaînes de dépendances où comprendre le comportement d'une méthode oblige à remonter cinq classes parentes. Chaque niveau d'héritage est une couche d'abstraction supplémentaire. Trois niveaux maximum est une heuristique souvent citée. Au-delà, demandez-vous si la composition ne serait pas plus lisible.

La fonction qui fait trop de choses

Une fonction de cent cinquante lignes qui valide des données, appelle une API, formate la réponse, log les erreurs et met à jour un état global est impossible à tester unitairement et difficile à comprendre au premier regard. Le principe de responsabilité unique de SOLID va dans le même sens que KISS ici : une fonction, une chose. Si vous ne pouvez pas nommer votre fonction sans utiliser "et" ou "ou", c'est un signe qu'elle fait trop.

Le nommage cryptique

Les noms courts et génériques sont une forme de complexité invisible. tmp, data, handler, utils : ces noms n'informent pas sur l'intention. Chaque développeur qui lit ce code doit reconstruire mentalement le contexte que le nommage aurait pu lui offrir gratuitement. Le bon nommage est une des formes les moins coûteuses de KISS et l'une des plus efficaces.

L'état global partagé

Un état global mutable accessible depuis n'importe quel module du projet est une source de complexité exponentielle. Chaque modification de cet état peut avoir des effets de bord dans des endroits inattendus. Tracer l'origine d'un bug dans ce type de code ressemble à démêler un câble avec les yeux fermés.

La configuration sur-paramétrée

Un fichier de configuration de deux cents lignes pour une application dont 90% des options ne sont jamais modifiées n'est pas de la flexibilité. C'est de la complexité déguisée en puissance. Chaque option est une décision que l'utilisateur ou le développeur doit prendre. Réduire les options par défaut à ce qui est réellement utile est une forme directe d'application de KISS.

Un exemple concret : avant et après KISS

Voici une fonction typiquement trop complexe :

function processUserData(data, opts = {}) {
  const mode = opts.mode || 'default';
  const strict = opts.strict !== undefined ? opts.strict : true;
  let result = {};

  if (mode === 'default') {
    if (strict) {
      if (!data.name || !data.email) throw new Error('Missing fields');
      result = { name: data.name.trim(), email: data.email.toLowerCase() };
    } else {
      result = {
        name: data.name ? data.name.trim() : '',
        email: data.email ? data.email.toLowerCase() : ''
      };
    }
  } else if (mode === 'extended') {
    // 40 lignes supplémentaires...
  }

  return result;
}

La version KISS :

function normalizeUser(user) {
  if (!user.name || !user.email) {
    throw new Error('Les champs name et email sont requis');
  }
  return {
    name: user.name.trim(),
    email: user.email.toLowerCase()
  };
}

La deuxième version fait exactement ce que le nom annonce. Elle ne gère pas des cas hypothétiques. Si un "mode extended" devient nécessaire, on l'ajoutera à ce moment-là dans une fonction séparée, avec un nom qui reflète ce qu'elle fait. Le comportement est prévisible, les tests sont directs, et n'importe quel développeur comprend la fonction en quinze secondes.

Pourquoi les développeurs expérimentés compliquent parfois plus que les juniors

C'est un paradoxe fréquent. Un développeur junior écrit souvent du code direct, parfois naïf, mais lisible. Un développeur intermédiaire qui vient d'apprendre les design patterns a tendance à en appliquer partout. Un développeur senior, s'il a bien intégré KISS, revient à quelque chose de plus proche du code junior, mais avec une compréhension profonde de pourquoi la simplicité est le bon choix.

Ce phénomène a été décrit sous différents noms : "couche d'abstraction prématurée", "architecture astronaute" (terme popularisé par Joel Spolsky). L'idée est la même : plus un développeur connaît d'outils, plus il est tenté de les utiliser, même quand la situation ne le justifie pas.

KISS demande une forme de maturité particulière : savoir qu'on pourrait faire plus élaboré, et choisir délibérément de ne pas le faire. Ce n'est pas de la paresse. C'est un jugement technique.

KISS ne veut pas dire "éviter la complexité nécessaire"

Il y a une confusion fréquente entre complexité essentielle et complexité accidentelle. La complexité essentielle vient du problème lui-même. Un moteur de règles métier pour un système de tarification assurantielle est intrinsèquement complexe. Vous ne pouvez pas le simplifier sans perdre de la précision.

Complexite essentielle

Vient du domaine métier. Inhérente au problème à résoudre. Ne peut pas être éliminée sans perdre de la valeur fonctionnelle.

A gérer avec soin, pas à supprimer.

Complexite accidentelle

Vient de nos choix de conception. Abstractions inutiles, couplages évitables, structures de données inadaptées.

C'est contre ça que KISS se bat.

La mission de KISS est précisément d'éliminer la complexité accidentelle pour que la complexité essentielle soit plus visible, plus compréhensible, et plus facile à gérer. Un code qui cache la logique métier derrière six couches d'abstraction n'est pas plus professionnel. Il est juste plus difficile à corriger quand le métier change.

Comment appliquer KISS au quotidien

1

Le test de l'explication orale

Si vous ne pouvez pas expliquer ce que fait votre code en deux phrases à un collègue sans dessin ni documentation, il est probablement trop complexe. Ce test est brutal mais fiable. Le code que vous ne savez pas expliquer simplement est le code que vous ne savez pas maintenir simplement.

2

Ecrivez la solution naive en premier

Avant d'introduire un pattern, une abstraction ou un design élaboré, commencez par la solution la plus directe qui fonctionne. Souvent, cette solution naive est suffisante. Si elle ne l'est pas, vous verrez clairement pourquoi quand le problème se manifestera, et vous pourrez alors introduire de la complexité de façon ciblée et justifiée.

3

Limitez la longueur des fonctions et des fichiers

Les seuils varient selon les équipes, mais des repères courants sont : une fonction sous vingt lignes, un fichier sous deux cents lignes. Ces chiffres ne sont pas des règles absolues, mais quand vous les dépassez, c'est un signal pour vérifier si votre découpage est correct. Une fonction trop longue cache souvent plusieurs responsabilités qui mériteraient d'être séparées.

4

Prenez le temps de refactoriser

KISS n'est pas un état qu'on atteint une fois pour toutes. La complexité revient naturellement à mesure que le code évolue. Des sessions régulières de refactoring, même courtes, maintiennent le code dans un état lisible. L'idée de "boy scout rule" de Robert C. Martin va dans ce sens : laissez le code un peu plus propre que vous l'avez trouvé.

5

Questionnez chaque couche d'indirection

Chaque interface, chaque classe abstraite, chaque proxy, chaque middleware ajoute une couche que le lecteur doit traverser pour comprendre ce qui se passe réellement. Certaines de ces couches sont justifiées. D'autres existent parce qu'un jour quelqu'un a pensé que ce serait "plus propre". Avant d'en ajouter une, demandez-vous quel problème concret elle résout.

6

Relisez votre code le lendemain

Ce conseil pratique est sous-estimé. Un code qui vous semble clair à minuit après six heures de travail peut s'avérer obscur le lendemain matin avec un regard frais. La relecture à froid est un des filtres KISS les plus simples et les plus efficaces. Si vous devenez vous-même perdu dans votre propre code au bout de vingt-quatre heures, il y a un problème.

KISS dans le contexte du développement avec IA en 2026

Les assistants de code comme Copilot, Cursor ou les interfaces de chat avec des modèles de langage sont devenus des outils quotidiens pour une large part des développeurs. Ils ont un effet paradoxal sur KISS : ils permettent d'écrire du code complexe plus vite qu'avant, ce qui peut accélérer l'accumulation de complexité accidentelle.

Un assistant IA va naturellement produire du code complet, défensif, générique. Il va gérer des cas limites que vous n'aviez pas demandés, ajouter des vérifications de type sur tout, structurer la réponse comme s'il anticipait des évolutions futures. C'est souvent du bon travail sur le plan technique, mais c'est du code qui viole KISS si votre besoin était plus simple.

La discipline KISS s'applique donc aussi à la façon dont vous utilisez ces outils. Cadrez vos prompts sur le besoin exact, pas sur le besoin imaginé. Relisez le code généré avec l'angle KISS : supprimez ce qui n'est pas utile maintenant, simplifiez ce qui peut l'être, renommez ce qui n'est pas explicite.

Les outils IA sont des accélérateurs. Ils amplifient votre façon de travailler. Si votre culture de code tend vers la complexité, ils la renforceront. Si elle tend vers la simplicité, ils vous aideront à aller plus vite dans la bonne direction.

Ce que KISS apporte à votre équipe au-dela du code

Les bénéfices de KISS ne s'arrêtent pas au niveau du fichier ou de la fonction. Ils remontent jusqu'à la productivité de l'équipe et à la santé du projet.

Revues de code plus courtes

Le code simple se review plus vite. Les reviewers comprennent l'intention sans devoir reconstituer mentalement une logique complexe.

Moins de bugs de régression

Un code avec peu de couplage et des responsabilités claires produit moins d'effets de bord lors des modifications.

Onboarding accelere

Un nouveau développeur sur un projet KISS peut contribuer en jours. Sur un projet complexe, il peut mettre des semaines à se sentir à l'aise.

Tests plus faciles a écrire

Le code simple est naturellement plus testable. Les fonctions avec une seule responsabilité se testent unitairement sans monter des mocks complexes.

Ces gains sont cumulatifs. Un projet qui applique KISS de façon cohérente depuis le début développe une vélocité qui résiste mieux aux changements de priorités et aux turnover d'équipe. La complexité est un capital qui se déprécie. La simplicité est un capital qui s'apprécie.

FAQ

KISS signifie-t-il qu'il faut éviter les design patterns ?

Non. Les design patterns sont des solutions éprouvées à des problèmes connus. KISS ne dit pas de les ignorer, il dit de ne pas les appliquer quand le problème qu'ils résolvent n'existe pas encore dans votre code. Un Singleton est justifié quand vous avez réellement besoin d'une instance unique. Un Observer est justifié quand vous avez réellement besoin de notifier plusieurs composants d'un changement. L'utiliser parce que "c'est une bonne pratique" sans ce besoin réel, c'est violer KISS.

Comment faire la différence entre code simple et code simplistique ?

Le code simple gère correctement le problème avec le minimum de complexité. Le code simplistique ignore des cas qui existent réellement. La différence réside dans la couverture fonctionnelle : si votre code simple rate des cas d'usage confirmés, il est simplistique. S'il couvre tous les cas réels avec une structure claire et lisible, il est simple au bon sens du terme. Les tests permettent souvent de faire cette distinction.

KISS et performances sont-ils compatibles ?

Oui, dans la plupart des cas. La complexité accidentelle n'améliore pas les performances, elle les dégrade souvent en ajoutant des couches d'indirection inutiles. Il existe des situations où optimiser les performances nécessite du code moins lisible (algorithmes bas niveau, optimisations mémoire), mais ces cas sont rares et doivent être documentés et mesurés. L'optimisation prématurée est d'ailleurs elle-même une violation de KISS.

Est-ce que KISS s'applique aussi à l'architecture de base de données ?

Absolument. Des schémas de base de données sur-normalisés ou sur-généralisés produisent des requêtes difficiles à lire et à optimiser. Partir d'un schéma simple et le faire évoluer en fonction des besoins réels est souvent plus sain que de concevoir un schéma universel dès le départ. Les migrations sont là pour accompagner l'évolution, pas pour être évitées à tout prix via une sur-conception initiale.

Comment introduire KISS dans une équipe qui a déjà une codebase complexe ?

Par petites touches, pas par réécriture totale. Identifiez les zones les plus douloureuses : celles où les bugs sont fréquents, où les modifications prennent trop de temps, où personne ne veut toucher au code. Proposez des refactorings ciblés lors des prochaines features sur ces zones. Chaque simplification partielle est un gain. Il n'est pas nécessaire d'avoir un projet entièrement simple pour bénéficier de KISS : chaque module simplifié réduit la charge cognitive globale.

KISS s'applique-t-il aussi aux APIs que l'on expose ?

C'est même là qu'il est le plus visible pour les autres. Une API avec un contrat simple, des endpoints au nom clair, et des réponses prévisibles est adoptée plus vite, génère moins de support, et est plus facile à documenter. Une API sur-conçue avec des dizaines de paramètres optionnels et des comportements qui varient selon les combinaisons de flags est un problème pour tous ceux qui doivent l'utiliser.

Y a-t-il des domaines où KISS est difficile à appliquer ?

Oui. Les systèmes distribués, la cryptographie, le traitement du signal, certains algorithmes d'optimisation ont une complexité essentielle élevée. Dans ces contextes, KISS ne signifie pas simplifier l'algorithme jusqu'à le rendre incorrect. Il signifie ne pas ajouter de complexité accidentelle par-dessus une complexité déjà inévitable. L'encapsulation bien pensée est souvent la réponse : isoler la complexité nécessaire dans des modules dédiés avec une interface simple vers l'extérieur.

Vous êtes expert ?

Partagez votre expertise sur notre blog

Tutoriel, retour d'expérience, analyse — publiez un article invité et gagnez en visibilité.

Écrire pour nous