English· Español· Deutsch· Nederlands· Français· 日本語· ქართული· 繁體中文· 简体中文· Português· Русский· العربية· हिन्दी· Italiano· 한국어· Polski· Svenska· Türkçe· Українська· Tiếng Việt· Bahasa Indonesia

un

invité
1 / ?
retour aux leçons

Théorie déjà existante

Chaque défaut MOAD disposait d'une solution connue des décennies avant la détection systématique en 2026. Les défauts n'ont pas persisté parce que personne ne savait mieux. Ils ont persisté parce que savoir n'est pas la même chose que détecter.

Chronologie MOAD fester : théorie connue vs. détectée pour chacun des cinq défauts

MOAD-0001 : list.contains O(N²)

Donald Knuth, 1973. The Art of Computer Programming, Volume 3: Sorting and Searching. Les tables de hachage pour une recherche O(1) sont entièrement spécifiées, avec analyse, en 1973. La différence entre une recherche linéaire O(N) et une recherche par hachage O(1) — documentée, formalisée, largement citée. Java a livré HashSet en 1.0 (1996). Python a livré set comme type de première classe en 2.4 (2004). La correction existait depuis 30 ans avant de devenir un idiome par défaut dans chaque écosystème.

Richard Hamming, 1986. Conférences de Bell Labs (publiées plus tard sous le titre The Art of Doing Science and Engineering, 1997). Hamming enseignait explicitement la complexité algorithmique, la différence entre correct et efficace, et le danger de construire des systèmes qui fonctionnent à petite échelle mais échouent à grande échelle. Il appelait cela « concevoir pour le problème que l’on voit aujourd’hui, pas pour celui auquel on sera confronté demain ».

MOAD-0002: Couplage par état global partagé

David Parnas, 1972. « On the Criteria To Be Used in Decomposing Systems into Modules ». CACM, décembre 1972. Parnas soutenait que les modules doivent être décomposés par dissimulation d’information — chaque module possède son propre état, sans variables globales mutables partagées. C’est le prédécesseur théorique direct du correctif Intertangle. Parnas était explicite : l’état global partagé crée un couplage invisible que les tests ne révèlent pas.

MOAD-0003: Fuite d’identité ThreadLocal

Java 1.2, 1998. ThreadLocal a été livré comme classe standard de la bibliothèque Java. Dès que le pooling de threads et ThreadLocal ont coexisté, le mécanisme de la fuite existait. Le défaut est structurel : un porteur dont la durée de vie est le thread, pas l’unité de travail. La documentation mettait en garde contre cela dès les premiers jours du cycle de vie de Java EE.

MOAD-0004: Identifiants journalisés

RFC 1945, 1996. HTTP/1.0 a défini l’en-tête Authorization. Le défaut de journalisation des identifiants est devenu possible dès l’existence de l’en-tête Authorization. OWASP a été fondé en 2001 et a documenté la journalisation des identifiants comme classe de vulnérabilité dans ses premiers guides. Le schéma : en-tête Authorization → middleware de journalisation → identifiants en clair sur disque. Connaissable depuis la première spécification d’authentification HTTP.

MOAD-0005: Troupeau tonitruant / Stampede de cache

Noyau Unix, 1993. Le « problème du troupeau tonitruant » — N processus réveillés simultanément sur un événement partagé — est apparu dans les discussions de développement du noyau Unix dès le début des années 1990. Les travaux de Doug Schmidt sur le patron Réacteur (1994) et Half-Sync/Half-Async (1995) ont traité la synchronisation au niveau de l’infrastructure. La variante « cache stampede » (N threads calculant la même valeur lors d’un échec de cache) a été documentée dans la littérature des systèmes distribués dès 2001.

---

Théorie : complète. Outils de détection : absents. L’écart entre « connaissable » et « détecté » varie de 28 à 54 ans selon le défaut.

L’écart de connaissabilité

La chronologie montre que chaque défaut MOAD disposait d’une solution connue au moins 28 ans avant sa détection systématique. L’écart le plus court (MOAD-0003) est de 28 ans. L’écart le plus long (MOAD-0002) est de 54 ans.

Il ne s’agit pas d’une histoire d’ignorance. Knuth, Parnas, Hamming — ce sont les auteurs les plus cités en informatique. Leurs travaux étaient enseignés dans les universités. Leur vocabulaire (Big O, dissimulation d’information, complexité algorithmique) est devenu un standard du cursus.

Pourquoi la connaissance de ces classes de défauts n’a-t-elle pas empêché leur persistance ? Choisissez un MOAD et retracez l’écart spécifique entre la solution connaissable et la détection effective.

Pourquoi le code s'envenime : cinq conditions

Un défaut ne persiste pas par accident. Cinq conditions structurelles, toutes présentes simultanément, créent un environnement d'envenimement. Supprimez-en une seule et la détection devient possible.

Cinq conditions pour l'envenimement d'un MOAD : DAG causal de la théorie à l'envenimement

Condition 1 : Sortie correcte

Une liste et un ensemble répondent à la question d’appartenance de manière identique. list.contains(x) et set.contains(x) renvoient le même booléen. Un ThreadLocal portant une identité obsolète porte toujours une identité — elle appartient simplement à la mauvaise requête. Les identifiants journalisés sont journalisés correctement — l’identifiant atteint le fichier journal sans erreur. Le défaut n’est pas un dysfonctionnement. Il n’est un dysfonctionnement qu’en termes de coût ou de conséquence de sécurité. Les tests qui vérifient la sortie passent. Les tests qui vérifient le coût ou la conséquence de sécurité : pour la plupart non écrits.

Condition 2 : Aucun test de complexité dans l’IC

Dijkstra a dit : « les tests montrent la présence de défauts, pas leur absence. » Hamming a ajouté : les défauts que nous testons sont ceux que nous trouvons. Les pipelines d’intégration continue en 2026 testent : la correction, la sûreté des types, les contrats d’API, le comportement fonctionnel. Ils ne testent pas : la complexité algorithmique par opération, la croissance mémoire par appel, le nettoyage des en-têtes d’autorisation, le cycle de vie de l’identité de thread.

Aucun test n’est exécuté. Aucun test n’échoue. Le pipeline est vert. Le défaut est invisible.

Condition 3 : Origine Small-N

Le code est écrit et relu dans des environnements de développement. Les graphes de développement comptent 50 nœuds. Les charges de requêtes de développement ont 10 threads concurrents. Les taux de cache miss en développement sont faibles (cache chaud, peu de clés). À N=50, le coût O(N²) est de 2 500 opérations. Invisible. À N=50 000, le coût est de 2 500 000 000 opérations. Un build de 17 minutes au lieu d’un build d’une seconde.

L’auteur qui a écrit le code n’a jamais vu N=50 000. Le relecteur qui l’a approuvé n’a jamais vu N=50 000. Le défaut n’était pas visible à l’échelle de son écriture.

Condition 4 : La copie se propage sans contexte

Un algorithme correct est instructif. Les tutoriels enseignent avec des exemples corrects. La documentation montre du code fonctionnel. Le même squelette Tarjan SCC — visited = [], if n not in visited interne — apparaît dans GHC, Maven, Python pip, Cargo, le compilateur TypeScript, le compilateur Kotlin, le compilateur Scala et javac. Équipes différentes, langages différents, décennies différentes. Même fossile. Le N=50 de l'auteur original ne se propage pas avec le code. Ce qui se propage : la sortie correcte. Ce qui reste derrière : l'hypothèse de performance.

Condition 5 : L'échelle grandit autour du code figé

Le code ne se dégrade pas. L'infrastructure évolue. Un résolveur de dépendances écrit en 2003 pour 200 paquets s'exécute sur 50 000 paquets en 2024. Personne ne le réécrit — il fonctionne. Personne ne le profile — le CI est vert. Le N qui rend le coût O(N²) catastrophique arrive progressivement, invisiblement, à l'échelle de production. À ce moment-là, l'auteur original a disparu. Le code est une dépendance. Personne ne touche les dépendances qui fonctionnent.

Diagnostic : Cinq conditions

Les cinq conditions : sortie correcte, absence de tests de complexité, origine à petit N, copie sans contexte, échelle qui grandit autour du code figé.

Les cinq conditions étaient présentes pour chaque MOAD simultanément. Ce n'est pas une coïncidence — c'est la signature structurelle d'une classe de défauts sédimentaires.

Laquelle des cinq conditions est la plus difficile à éliminer, et pourquoi ? Que faudrait-il pour la supprimer du pipeline d'une véritable organisation logicielle ?

Ce que Hamming a dit

Les conférences de Richard Hamming en 1986 aux Bell Labs — publiées en 1997 sous le titre The Art of Doing Science and Engineering — contiennent des avertissements qui se lisent comme des descriptions directes du schéma de défaut MOAD. Il ne décrivait pas MOAD. Il décrivait la tendance structurelle des systèmes d'ingénierie à se calcifier autour de décisions localement correctes qui deviennent globalement coûteuses.

Hamming sur la complexité : « Le but du calcul est la compréhension, pas les nombres. Mais il faut avoir la bonne complexité d'algorithme, sinon les nombres n'arriveront jamais. Un algorithme O(N²) qui fonctionne pour N=100 ne fonctionnera pas pour N=1 000 000 avant votre retraite. »

Hamming sur la copie : « Les grands ingénieurs ne se contentent pas de copier des solutions. Ils comprennent pourquoi la solution fonctionne, dans quelles conditions elle tient, et ce qui la briserait. Une solution copiée sans ses conditions est une bombe à retardement. »

Hamming sur les tests : « Tester ce que vous avez mesuré n'est pas la même chose que mesurer ce qui compte. Nous construisons des suites de tests élaborées pour les propriétés que nous avons choisi de tester. Nous laissons non testées les propriétés que nous n'avons pas choisies. Ce que nous laissons non testé est ce qui nous surprend en production. »

Hamming à l'échelle : « L'erreur que vous commettez la première année d'un projet est celle que vous corrigez encore la dixième année. Les hypothèses initiales se calcifient. Le projet s'y adapte. Personne ne réécrit les fondations. »

L'écart entre l'avertissement et l'opérationnalisation

Les avertissements de Hamming étaient justes. Ils ont été enseignés. Ils ont été cités. Ils ont été intégrés aux programmes. Mais un avertissement n'est pas un détecteur. Hamming a décrit la forme du défaut. Il n'a pas construit un outil qui s'exécute dans l'IC et signale les chemins chauds O(N²), les fuites d'identité ThreadLocal ou la journalisation des identifiants. L'écart entre « connaissable » et « détectable » est l'écart entre une théorie et son opérationnalisation en infrastructure automatisée.

MOAD existe parce que le domaine a construit une infrastructure de correction et non une infrastructure de performance ou de sécurité au même niveau. Tests unitaires : standard depuis les années 1970. Tests basés sur les propriétés : standard depuis les années 1990. Benchmarks de complexité algorithmique dans l'IC : encore expérimentaux en 2026.

Opérationnaliser l'avertissement

Hamming a mis en garde contre la calcification de la complexité, les propriétés non testées, les solutions copiées sans leurs conditions, et l'écrasement des hypothèses initiales par l'échelle. Il nous a donné le vocabulaire. Il ne nous a pas donné le détecteur.

Le pipeline MOAD comble cet écart : scan → ticket → correctif → test unitaire → divulgation → PR → fusion en amont. C'est le Hamming opérationnalisé : non seulement l'avertissement, mais la détection automatisée et un pipeline de correction.

Hamming a dit « ce que nous laissons non testé est ce qui nous surprend en production ». Nommez une propriété que l'industrie du logiciel laisse systématiquement non testée, et décrivez à quoi ressemblerait une détection automatisée.

La signature Fester

Un défaut de classe MOAD possède une signature reconnaissable. Les cinq conditions sont présentes simultanément. Les cinq sont vérifiables avant d’écrire une seule analyse :

1. Sortie correcte ? Exécutez la suite de tests standard. Si elle passe, le défaut concerne une propriété de performance ou de sécurité, pas de correction. Cela signifie que le CI standard ne le détectera pas.

2. Pas de test de complexité ? Vérifiez la configuration CI. Y a-t-il une étape de benchmark ? Compare-t-elle le comportement algorithmique (et non seulement le temps d’exécution) avec un commit précédent ? Sinon : condition présente.

3. Origine Small-N ? Vérifiez le git blame et le commit d’origine. Quelle était la taille du jeu de données dans la première implémentation ? Cette taille est-elle inférieure de plus de 100× à la charge actuelle en production ? Si oui : condition présente.

4. La copie se propage-t-elle ? Recherchez le motif dans la base de code et dans les écosystèmes. Le même motif structurel apparaît-il dans N≥3 bases de code indépendantes sans ascendance commune ? Si oui : le fossile s’est propagé. Chaque copie : un nouveau site de propagation.

5. L’échelle augmente-t-elle ? Vérifiez les métriques de production. Quelle est la valeur de N aujourd’hui par rapport à N lors du premier déploiement ? Le taux de croissance est-il soutenu ? À quel N le défaut devient-il critique en production ?

Si les cinq conditions sont vérifiées et confirmées : vous avez un défaut de classe MOAD. La correction est toujours une substitution d’une ligne ou d’une méthode. La découverte est la partie difficile. La correction est la partie facile.

C’est ce que Hamming voulait dire : l’ingénierie ne concerne pas la correction. La correction est simple une fois qu’on l’a vue. L’ingénierie consiste à construire les systèmes qui permettent de la voir.

Appliquer la signature

La signature de propagation MOAD : sortie correcte + absence de test de complexité + origine Small-N + propagation par copie + croissance de l’échelle.

Cette signature ne se limite pas aux cinq défauts MOAD. Elle décrit une classe de défaut qui persiste dans tout système où les tests de correction sont la seule porte de qualité automatisée.

Nommez une classe de défaut en dehors des cinq MOAD qui correspond à la signature « fester ». Montrez lesquelles des cinq conditions sont présentes et à quoi ressemblerait le détecteur automatisé.