Teoria Già Esistente
Ogni difetto MOAD aveva una soluzione nota decenni prima della rilevazione sistematica nel 2026. I difetti non sono persistiti perché nessuno sapeva. Sono persistiti perché sapere non equivale a rilevare.
MOAD-0001: list.contains O(N²)
Donald Knuth, 1973. The Art of Computer Programming, Volume 3: Sorting and Searching. Le tabelle hash per ricerche O(1) sono state pienamente specificate, con analisi, nel 1973. La differenza tra ricerca lineare O(N) e lookup hash O(1) — documentata, formalizzata, ampiamente citata. Java ha introdotto HashSet nella versione 1.0 (1996). Python ha introdotto set come tipo nativo nella 2.4 (2004). La soluzione esisteva da 30 anni prima di diventare un’idioma predefinita in ogni ecosistema.
Richard Hamming, 1986. Lezioni ai Bell Labs (poi pubblicate come The Art of Doing Science and Engineering, 1997). Hamming insegnò esplicitamente la complessità algoritmica, la differenza tra corretto ed efficiente, e il pericolo di costruire sistemi che funzionano su piccola scala ma falliscono su larga scala. Lo definì come "progettare per il problema che vedi oggi, non per il problema che affronterai domani."
MOAD-0002: Accoppiamento tramite Stato Globale Condiviso
David Parnas, 1972. 'On the Criteria To Be Used in Decomposing Systems into Modules.' CACM, dicembre 1972. Parnas sostenne che i moduli dovrebbero essere decomposti tramite information hiding — ogni modulo possiede il proprio stato, senza globali mutabili condivisi. Questo è il diretto predecessore teorico della correzione Intertangle. Parnas fu esplicito: lo stato globale condiviso crea un accoppiamento invisibile che i test non rivelano.
MOAD-0003: Perdita di Identità ThreadLocal
Java 1.2, 1998. ThreadLocal è stato distribuito come classe della libreria standard di Java. Nel momento in cui thread pooling e ThreadLocal coesistevano, esisteva già il meccanismo della perdita. Il difetto è strutturale: un carrier la cui durata è quella del thread, non dell'unità di lavoro. La documentazione ne avvisava già all'inizio del ciclo di vita di Java EE.
MOAD-0004: Credenziali Registrate nei Log
RFC 1945, 1996. HTTP/1.0 definì l'header Authorization. Il difetto di registrazione delle credenziali divenne possibile il giorno in cui l'header Authorization esisteva. OWASP fu fondata nel 2001 e documentò la registrazione delle credenziali come classe di vulnerabilità nelle sue prime guide. Il pattern: header Authorization → middleware di logging → credenziali in chiaro su disco. Conoscibile fin dalla prima specifica di autenticazione HTTP.
MOAD-0005: Thundering Herd / Cache Stampede
Kernel Unix, 1993. Il "problema del thundering herd" — N processi risvegliati simultaneamente su un evento condiviso — apparve nelle discussioni sullo sviluppo del kernel Unix già all'inizio degli anni '90. Il lavoro di Doug Schmidt sul pattern Reactor (1994) e Half-Sync/Half-Async (1995) affrontò la sincronizzazione a livello infrastrutturale. La variante cache stampede (N thread che calcolano lo stesso valore in caso di cache miss) fu documentata nella letteratura sui sistemi distribuiti entro il 2001.
---
Teoria: completa. Strumenti di rilevamento: assenti. Il divario tra "conoscibile" e "rilevato" varia da 28 a 54 anni a seconda del difetto.
Il divario di conoscibilità
La timeline mostra che ogni difetto MOAD aveva una soluzione nota almeno 28 anni prima del rilevamento sistematico. Il divario più breve (MOAD-0003) è di 28 anni. Il più lungo (MOAD-0002) è di 54 anni.
Questa non è una storia di ignoranza. Knuth, Parnas, Hamming — questi sono gli autori più citati nell'informatica. Il loro lavoro veniva assegnato nelle università. Il loro vocabolario (Big O, information hiding, complessità algoritmica) è diventato curriculum standard.
Why Code Festers: Five Conditions
Un difetto non persiste per caso. Cinque condizioni strutturali, tutte presenti simultaneamente, creano un ambiente di fester. Rimuovendone una qualsiasi, il rilevamento diventa possibile.
Condition 1: Correct Output
Una lista e un set rispondono alla domanda di membership in modo identico. list.contains(x) e set.contains(x) restituiscono lo stesso booleano. Un ThreadLocal che trasporta un’identità obsoleta trasporta comunque un’identità — appartiene semplicemente alla richiesta sbagliata. Le credenziali registrate nel log vengono registrate correttamente — la credenziale raggiunge il file di log senza errori. Il difetto non è un malfunzionamento. Lo è solo in termini di costo o di conseguenza sulla sicurezza. I test che verificano l’output passano. I test che verificano costo o conseguenza sulla sicurezza: per lo più non scritti.
Condizione 2: Nessun test di complessità in CI
Dijkstra diceva: «il testing mostra la presenza di difetti, non la loro assenza». Hamming aggiunse: i difetti per cui testiamo sono i difetti che troviamo. Le pipeline CI nel 2026 testano: correttezza, sicurezza dei tipi, contratti API, comportamento funzionale. Non testano: complessità algoritmica per operazione, crescita della memoria per chiamata, scrubbing dell’authorization-header, ciclo di vita dell’identità del thread.
Nessun test viene eseguito. Nessun test fallisce. La pipeline è verde. Il difetto è invisibile.
Condizione 3: Origine Small-N
Il codice viene scritto e revisionato in ambienti di sviluppo. I grafi di sviluppo hanno 50 nodi. I carichi di richieste in sviluppo hanno 10 thread concorrenti. I tassi di cache miss in sviluppo sono bassi (cache calda, poche chiavi). A N=50 il costo O(N²) è di 2.500 operazioni. Invisibile. A N=50.000 il costo è di 2.500.000.000 operazioni. Una build di 17 minuti invece di una build di 1 secondo.
L’autore che ha scritto il codice non ha mai visto N=50.000. Il revisore che lo ha approvato non ha mai visto N=50.000. Il difetto non era visibile alla scala in cui è stato scritto.
Condizione 4: La copia si propaga senza contesto
Un algoritmo corretto è istruttivo. I tutorial insegnano con esempi corretti. La documentazione mostra codice funzionante. Lo stesso scheletro Tarjan SCC — visited = [], if n not in visited interno — appare in GHC, Maven, Python pip, Cargo, TypeScript compiler, Kotlin compiler, Scala compiler e javac. Team diversi, linguaggi diversi, decenni diversi. Stesso fossile. L’N=50 dell’autore originale non si propaga con il codice. Ciò che si propaga: l’output corretto. Ciò che resta indietro: l’assunzione sulle prestazioni.
Condizione 5: La scala cresce intorno a codice congelato
Il codice non si degrada. L’infrastruttura scala. Un risolutore di dipendenze scritto nel 2003 per 200 pacchetti viene eseguito su 50.000 pacchetti nel 2024. Nessuno lo riscrive — funziona. Nessuno lo profila — la CI è verde. L’N che rende catastrofico il costo O(N²) arriva gradualmente, invisibilmente, alla scala di produzione. A quel punto l’autore originale è sparito. Il codice è una dipendenza. Nessuno tocca le dipendenze funzionanti.
Diagnosi: Cinque Condizioni
Le cinque condizioni: output corretto, assenza di test di complessità, origine con N piccolo, copia senza contesto, scala che cresce intorno a codice congelato.
Tutte e cinque erano presenti in ogni MOAD simultaneamente. Non è una coincidenza — è la firma strutturale di una classe di difetti sedimentari.
Cosa disse Hamming
Le lezioni tenute da Richard Hamming nel 1986 ai Bell Labs — pubblicate nel 1997 come The Art of Doing Science and Engineering — contengono avvertimenti che sembrano descrizioni dirette del pattern difettoso MOAD. Non stava descrivendo MOAD. Stava descrivendo la tendenza strutturale dei sistemi ingegneristici a calcificarsi attorno a decisioni localmente corrette che diventano globalmente costose.
Hamming sulla complessità: «Lo scopo del calcolo è l’intuizione, non i numeri. Ma è necessario avere la giusta complessità dell’algoritmo, altrimenti i numeri non arriveranno mai. Un algoritmo O(N²) che funziona su N=100 non funzionerà su N=1.000.000 prima del pensionamento.»
Hamming sulla copia: «I grandi ingegneri non si limitano a copiare le soluzioni. Capiscono perché la soluzione funziona, sotto quali condizioni vale e cosa la romperebbe. Una soluzione copiata senza le sue condizioni è una bomba a orologeria.»
Hamming sui test: «Testare ciò che hai misurato non è lo stesso che misurare ciò che conta. Costruiamo suite di test elaborate per le proprietà che abbiamo scelto di testare. Lasciamo non testate le proprietà che non abbiamo scelto. Ciò che lasciamo non testato è ciò che ci sorprende in produzione.»
Hamming in scala: 'L'errore che commetti nel primo anno di un progetto è l'errore che stai ancora correggendo nel decimo anno. Le ipotesi iniziali si calcificano. Il progetto si scala attorno a esse. Nessuno riscrive le fondamenta.'
Il divario tra avvertimento e operazionalizzazione
Gli avvertimenti di Hamming erano corretti. Sono stati insegnati. Sono stati citati. Sono stati assegnati nei curricula. Ma un avvertimento non è un rilevatore. Hamming ha descritto la forma del difetto. Non ha costruito uno strumento che gira in CI e segnala percorsi caldi O(N²), perdite di identità ThreadLocal o log di credenziali. Il divario tra "conoscibile" e "rilevabile" è il divario tra una teoria e la sua operazionalizzazione come infrastruttura automatizzata.
MOAD esiste perché il settore ha costruito un'infrastruttura di correttezza e non un'infrastruttura di prestazioni o sicurezza allo stesso livello. Test unitari: standard dagli anni '70. Test basati su proprietà: standard dagli anni '90. Benchmark di complessità algoritmica in CI: ancora sperimentali nel 2026.
Operazionalizzare l'avvertimento
Hamming ha avvertito sulla calcificazione della complessità, sulle proprietà non testate, sulle soluzioni copiate senza le loro condizioni e sulla scala che schiaccia le ipotesi iniziali. Ci ha dato il vocabolario. Non ci ha dato il rilevatore.
La pipeline MOAD colma quel divario: scan → ticket → patch → unit test → disclose → PR → merge upstream. Questo è Hamming operazionalizzato: non solo l'avvertimento, ma il rilevamento automatizzato e una pipeline di correzione.
La Fester Signature
Un difetto di classe MOAD ha una firma riconoscibile. Tutte e cinque le condizioni presenti simultaneamente. Tutte e cinque sono verificabili prima di scrivere una singola scansione:
1. Output corretto? Esegui la suite di test standard. Se passa, il difetto è una proprietà di prestazioni o sicurezza, non di correttezza. Questo significa che la CI standard non lo rileverà.
2. Nessun test di complessità? Controlla la configurazione CI. Esiste una fase di benchmark? Confronta il comportamento algoritmico (non solo il tempo di esecuzione) con un commit precedente? In caso contrario: condizione presente.
3. Origine Small-N? Controlla il git blame e il commit originale. Qual era la dimensione del dataset nella prima implementazione? È inferiore al carico di produzione attuale di oltre 100×? In tal caso: condizione presente.
4. La copia si propaga? Cerca il pattern in tutto il codebase e negli ecosistemi. Lo stesso pattern strutturale appare in N≥3 codebase indipendenti senza antenati comuni? In tal caso: il fossile si è propagato. Ogni copia: un nuovo sito di infezione.
5. La scala cresce? Controlla le metriche di produzione. Qual è N oggi rispetto a N al primo deployment? Il tasso di crescita è sostenuto? A quale N il difetto diventa criticamente operativo?
Se tutti e cinque i punti sono verificati e confermati: hai un difetto di classe MOAD. La correzione è sempre una sostituzione di una riga o di un metodo. La scoperta è la parte difficile. La correzione è la parte facile.
Questo è ciò che intendeva Hamming: l’ingegneria non riguarda la correzione. La correzione è semplice una volta individuata. L’ingegneria riguarda la costruzione di sistemi che ti permettano di vederla.
Applica la Signature
La signature del MOAD fester: output corretto + nessun test di complessità + origine Small-N + copia che si propaga + scala che cresce.
Questa signature non è limitata ai cinque difetti MOAD. Descrive una classe di difetto che persiste in qualsiasi sistema in cui i test di correttezza sono l’unico automated quality gate.