L'illusion de la complexité

Complex means Skillful Fallacy

complex-means-skillful-fallacy
Philippe Escalle CTO

Dans le monde du développement logiciel, il existe un phénomène discret mais toxique : l’illusion que la complexité est une preuve de compétence. Ce que l’on appelle, dans un clin d’œil critique, le “Complex means Skillful Fallacy”.

Nous avons tous été confrontés à ce moment étrange, face à une portion de code si dense, si obscure, qu’elle semble presque échapper à toute compréhension humaine. Le réflexe, alors, n’est pas toujours de remettre en question la qualité du code, mais plutôt de s’interroger sur ses propres compétences. “Si je ne comprends pas, c’est que l’auteur est plus fort que moi.”

Cette dynamique est dangereuse. Elle pousse à ériger la confusion en talent, et à considérer la lisibilité comme un luxe superflu plutôt qu’une exigence de qualité. Pourtant, comme le dit la formule : “Quelqu’un qui produit du code que l’on est incapable de comprendre semble souvent meilleur que nous. Meilleur que ses collègues. Et c’est dangereux.”

Il y a une tendance inquiétante que l’on voit émerger de plus en plus, notamment sur LinkedIn : des développeurs, souvent seniors ou se présentant comme tels, s’amusent à comparer deux extraits de code. À gauche, un code simple, clair, lisible  que l’on attribue à un "junior". À droite, une version plus dense, abstraite, couverte de fonctions anonymes, de raccourcis syntaxiques et de design patterns opaques  celle du "senior".
Le message est toujours le même, parfois explicite, parfois implicite : “Le vrai niveau, c’est ça.”
Comme si l’incompréhensibilité était un gage de maîtrise. Comme si l’on prouvait sa compétence en rendant le code inaccessible.
Cette illusion tenace selon laquelle plus un code est complexe, plus son auteur est compétent. En réalité, c’est souvent tout l’inverse.

Les visages de la complexité inutile

L’illusion se manifeste dans les moindres détails d’un projet logiciel. À commencer par l’architecture, parfois surdimensionnée, où des couches entières de complexité sont ajoutées non pas pour répondre à un besoin réel, mais pour démontrer une supposée maîtrise avancée. L’élégance fait alors place à l’exhibition.

La syntaxe elle-même peut devenir un piège. Certains développeurs s’amusent à utiliser les recoins les plus ésotériques du langage, comme s’il s’agissait d’un sport d’élite. Des expressions ternaires imbriquées, des raccourcis obscurs, des fonctions anonymes imbriquées dans des appels de méthodes, tout est bon pour perdre le lecteur.

Le nommage est une autre arme de confusion massive. Des fonctions s’appellent process(), handle(), doStuff(), sans donner la moindre indication sur ce qu’elles font réellement. Parfois, c’est même volontaire : maintenir une forme de brouillard autour de sa propre production, comme un magicien gardant ses tours secrets.

Et bien sûr, les commentaires sont absents. Ou alors sibyllins. Ou datés, contradictoires, trompeurs. L’auteur sait ce qu’il a voulu faire, et cela lui suffit. Le reste de l’équipe ? Elle improvisera.

Quand le code impressionne mais n’explique plus rien

J’ai vu plusieurs fois, dans ma carrière, des développeurs complexifier volontairement le code pour devenir indispensables. Parfois pour se protéger, parfois par simple réflexe culturel. Le résultat est le même : le code devient une œuvre cryptée, et l’auteur son seul traducteur.

Dans certaines équipes, cela crée des tensions. Des rivalités. Des clans. Des jeux d’ego où l’on écrit du code non plus pour résoudre un problème, mais pour prendre le dessus sur ses pairs.

J’ai assisté à des guerres de tranchées techniques où chaque ligne de code était une tentative de prouver sa valeur, souvent au détriment du projet lui-même. Derrière les apparences de “haute technicité”, il y avait souvent une peur sous-jacente : celle d’être remplacé.

Voici un exemple simple, presque caricatural, mais révélateur :

function q(x){return[...x].map((z,i)=>x.charCodeAt(i)%2?z.toUpperCase():z).join('')}

Et maintenant, la version lisible :

function capitalizeOddChars(input){
  return input.split('').map((char, i) => i % 2 ? char.toUpperCase() : char).join('');
}

Ces deux fonctions font exactement la même chose. La première semble “maligne”, la seconde est “claire”. Mais laquelle préférez-vous devoir déboguer dans six mois ? Laquelle un nouveau développeur pourra modifier sans crainte ?

Pourquoi cette illusion perdure

Les raisons sont nombreuses, souvent inconscientes. D’abord, il y a les biais cognitifs : le biais d’autorité nous pousse à croire que ce que nous ne comprenons pas est supérieur. L’effet Dunning-Kruger inversé fait que les développeurs expérimentés doutent d’eux-mêmes face à un code trop compliqué, pendant que les moins aguerris restent impressionnés.

Mais il y a aussi des facteurs culturels. Certaines organisations valorisent la complexité, car elle flatte l’ego, et rend les développeurs “irremplaçables”. Un code illisible crée un effet de rareté : seul son auteur peut y toucher sans tout casser. C’est le fameux “bus factor” – si cette personne quitte l’équipe, tout s’écroule.

J’ai même vu des managers conforter ce système, consciemment ou non, en valorisant les “sorciers du code”, ceux que l’on appelle dans l’urgence parce qu’ils sont les seuls à comprendre tel module. À court terme, cela peut sembler utile. Mais à long terme, c’est une bombe à retardement.

Les conséquences

Les effets sont désastreux. La dette technique grimpe en flèche. Les bugs s’incrustent et résistent. Les nouvelles recrues peinent à comprendre ce qu’elles lisent, et mettent des semaines à devenir productives. Les silos de connaissance se forment, alimentés par le culte de la complexité. L’énergie de l’équipe est aspirée par la simple compréhension du code existant, au lieu d’être investie dans l’amélioration continue.

La simplicité comme compétence avancée

Et si, au contraire, on considérait la simplicité comme une forme suprême de sophistication ? Antoine de Saint-Exupéry écrivait : “La perfection est atteinte, non pas lorsqu’il n’y a plus rien à ajouter, mais lorsqu’il n’y a plus rien à retirer.”

Les ingénieurs les plus brillants ne sont pas ceux qui complexifient, mais ceux qui simplifient sans appauvrir. Ceux qui savent rendre lisible ce qui semblait confus. Ceux qui écrivent du code qui “s’explique tout seul”. Ce sont eux qui, in fine, permettent aux systèmes de durer, d’évoluer, et aux équipes de travailler sereinement.

Vers une culture technique responsable

Il est temps de renverser la logique. D’arrêter de confondre obscurité avec excellence. La lisibilité n’est pas une faiblesse, c’est une preuve de maturité.

En tant que développeur, écrire un code que les autres comprennent, ce n’est pas faire une concession. C’est faire acte de collaboration. Et en tant que responsable technique, tech lead ou CTO, il est crucial de créer une culture qui valorise cette compétence.

Une culture où les revues de code ne récompensent pas la virtuosité gratuite, mais la clarté et la maintenabilité. Où la documentation n’est pas une tâche secondaire, mais une part intégrée de la production. Où l’égo cède la place à l’intention collective.

Un CTO ne devrait pas chercher à créer une équipe de génies incompris. Il ou elle devrait chercher à bâtir une équipe capable de se relire, de se remplacer, de s’entraider. Un système que l’on peut confier sans crainte, un produit que l’on peut faire évoluer sans avoir à convoquer un “grand prêtre” du legacy.
Simplifier, ce n’est pas trahir la technique. C’est lui rendre hommage.


L'oeil du CTO

" En tant que CTO, j’ai appris que la valeur d’un système ne réside pas dans sa sophistication apparente, mais dans sa capacité à durer, à être compris, et à évoluer avec ses équipes. Favoriser une culture où la lisibilité est considérée comme une compétence clé n’est pas un luxe : c’est un choix stratégique. Un code complexe peut impressionner à court terme, mais un code clair, lisible et maintenable crée de la résilience, de la fluidité, et de la confiance dans l’organisation. La mission d’un CTO ne consiste pas à valider des prouesses techniques isolées. Elle consiste à bâtir un environnement dans lequel chaque développeur peut contribuer, comprendre, et transmettre. Un environnement où l’équipe grandit ensemble, au lieu de dépendre d'individualités qui compliquent pour mieux exister. Ma conviction est simple : la véritable excellence technique, c’est celle qui se partage. Et le code qui se partage, c’est d’abord le code que l’on comprend. "