Teoría que ya existía
Cada defecto MOAD tenía una solución conocida décadas antes de su detección sistemática en 2026. Los defectos no persistieron porque nadie supiera mejor. Persistieron porque saber no es lo mismo que detectar.
MOAD-0001: list.contains O(N²)
Donald Knuth, 1973. The Art of Computer Programming, Volume 3: Sorting and Searching. Las tablas hash para búsquedas O(1) fueron especificadas completamente, con análisis, en 1973. La diferencia entre una búsqueda lineal O(N) y una búsqueda hash O(1) — documentada, formalizada y ampliamente citada. Java incluyó HashSet en la versión 1.0 (1996). Python incluyó set como tipo de primera clase en la versión 2.4 (2004). La solución existía desde hacía 30 años antes de convertirse en un patrón por defecto en todos los ecosistemas.
Richard Hamming, 1986. Conferencias de Bell Labs (publicadas posteriormente como The Art of Doing Science and Engineering, 1997). Hamming enseñó explícitamente la complejidad algorítmica, la diferencia entre correcto y eficiente, y el peligro de construir sistemas que funcionan a pequeña escala pero fallan a gran escala. Lo llamó «diseñar para el problema que puedes ver hoy, no para el problema que enfrentarás mañana».
MOAD-0002: Acoplamiento por Estado Global Compartido
David Parnas, 1972. «On the Criteria To Be Used in Decomposing Systems into Modules». CACM, diciembre de 1972. Parnas argumentó que los módulos deben descomponerse mediante ocultamiento de información: cada módulo posee su propio estado, sin variables globales mutables compartidas. Este es el predecesor teórico directo de la corrección Intertangle. Parnas fue explícito: el estado global compartido crea un acoplamiento invisible que las pruebas no revelan.
MOAD-0003: Fuga de Identidad ThreadLocal
Java 1.2, 1998. ThreadLocal se incluyó como clase de la biblioteca estándar de Java. En el momento en que coexistieron el pooling de hilos y ThreadLocal, existió el mecanismo de la fuga. El defecto es estructural: un portador cuya vida útil es el hilo, no la unidad de trabajo. La documentación advirtió sobre esto desde los inicios del ciclo de vida de Java EE.
MOAD-0004: Credenciales Registradas en Logs
RFC 1945, 1996. HTTP/1.0 definió la cabecera Authorization. El defecto de registro de credenciales se hizo posible el día que existió la cabecera Authorization. OWASP se fundó en 2001 y documentó el registro de credenciales como una clase de vulnerabilidad en sus primeras guías. El patrón: cabecera Authorization → middleware de logs → credenciales en texto claro en disco. Conocible desde la primera especificación de autenticación HTTP.
MOAD-0005: Rebaño de Truenos / Tormenta de Caché
Núcleo de Unix, 1993. El 'problema del rebaño atronador' — N procesos despertados simultáneamente por un evento compartido — apareció en discusiones sobre el desarrollo del núcleo de Unix a principios de los años 90. El trabajo de Doug Schmidt sobre el patrón Reactor (1994) y Half-Sync/Half-Async (1995) abordó la sincronización a nivel de infraestructura. La variante de estampida de caché (N hilos calculan el mismo valor en un fallo de caché) fue documentada en la literatura de sistemas distribuidos en 2001.
---
Teoría: completa. Herramientas de detección: ausentes. La brecha entre 'conocible' y 'detectado' oscila entre 28 y 54 años según el defecto.
La Brecha de Conocibilidad
La línea temporal muestra que cada defecto MOAD tenía una solución conocida al menos 28 años antes de su detección sistemática. La brecha más corta (MOAD-0003) es de 28 años. La más larga (MOAD-0002) es de 54 años.
Esta no es una historia sobre ignorancia. Knuth, Parnas, Hamming — estos son los autores más citados en ciencias de la computación. Su trabajo fue asignado en las universidades. Su vocabulario (Big O, ocultamiento de información, complejidad algorítmica) se convirtió en el plan de estudios estándar.
Por qué el Código Se Pudre: Cinco Condiciones
Un defecto no persiste por accidente. Cinco condiciones estructurales, todas presentes simultáneamente, crean un entorno de pudrición. Elimina cualquiera y la detección se vuelve posible.
Condición 1: Salida Correcta
Una lista y un conjunto responden a la pregunta de pertenencia de forma idéntica. list.contains(x) y set.contains(x) devuelven el mismo booleano. Un ThreadLocal que lleva una identidad obsoleta sigue llevando una identidad — solo que pertenece a la solicitud incorrecta. Las credenciales registradas se registran correctamente — la credencial llega al archivo de registro sin error. El defecto no es un mal funcionamiento. Es un mal funcionamiento solo en costo o consecuencia de seguridad. Las pruebas que verifican la salida pasan. Las pruebas que verifican costo o consecuencia de seguridad: en su mayoría no escritas.
Condición 2: Sin pruebas de complejidad en CI
Dijkstra dijo: «las pruebas muestran la presencia de defectos, no su ausencia». Hamming lo amplió: los defectos que probamos son los defectos que encontramos. Las canalizaciones de CI en 2026 prueban: corrección, seguridad de tipos, contratos de API, comportamiento funcional. No prueban: complejidad algorítmica por operación, crecimiento de memoria por llamada, limpieza del encabezado de autorización, ciclo de vida de la identidad del hilo.
Ninguna prueba se ejecuta. Ninguna prueba falla. La canalización está verde. El defecto es invisible.
Condición 3: Origen en N pequeño
El código se escribe y revisa en entornos de desarrollo. Los grafos de desarrollo tienen 50 nodos. Las cargas de solicitudes de desarrollo tienen 10 hilos concurrentes. Las tasas de fallos de caché en desarrollo son bajas (caché caliente, pocas claves). En N=50 el costo O(N²) es de 2,500 operaciones. Invisible. En N=50,000 el costo es de 2,500,000,000 operaciones. Una compilación de 17 minutos en lugar de una de 1 segundo.
El autor que escribió el código nunca vio N=50,000. El revisor que lo aprobó nunca vio N=50,000. El defecto no fue visible a la escala en que se escribió.
Condición 4: La copia se propaga sin contexto
Un algoritmo correcto es instructivo. Los tutoriales enseñan con ejemplos correctos. La documentación muestra código que funciona. El mismo esqueleto de Tarjan SCC — visited = [], if n not in visited interno — aparece en GHC, Maven, Python pip, Cargo, TypeScript compiler, Kotlin compiler, Scala compiler y javac. Equipos diferentes, lenguajes diferentes, décadas diferentes. El mismo fósil. El N=50 del autor original no se propaga con el código. Lo que se propaga: la salida correcta. Lo que queda atrás: la suposición de rendimiento.
Condición 5: La escala crece alrededor del código congelado
El código no se degrada. La infraestructura escala. Un resolvedor de dependencias escrito en 2003 para 200 paquetes se ejecuta con 50 000 paquetes en 2024. Nadie lo reescribe — funciona. Nadie lo perfila — el CI está verde. El N que hace que el coste O(N²) sea catastrófico llega de forma gradual, invisible, a escala de producción. Para entonces el autor original ya no está. El código es una dependencia. Nadie toca las dependencias que funcionan.
Diagnóstico: Cinco condiciones
Las cinco condiciones: salida correcta, ausencia de pruebas de complejidad, origen con N pequeño, copia sin contexto, la escala crece alrededor del código congelado.
Las cinco condiciones estuvieron presentes en cada MOAD simultáneamente. No es coincidencia — es la firma estructural de una clase de defecto sedimentario.
Lo que dijo Hamming
Las conferencias de Richard Hamming de 1986 en Bell Labs —publicadas en 1997 como The Art of Doing Science and Engineering— contienen advertencias que se leen como descripciones directas del patrón de defecto MOAD. No estaba describiendo MOAD. Estaba describiendo la tendencia estructural de los sistemas de ingeniería a calcificarse alrededor de decisiones localmente correctas que se vuelven globalmente costosas.
Hamming sobre complejidad: «El propósito de la computación es obtener conocimiento, no números. Pero tienes que tener la complejidad correcta del algoritmo o los números nunca llegarán. Un algoritmo O(N²) que funciona con N=100 no funcionará con N=1.000.000 antes de que te jubiles».
Hamming sobre copia: «Los grandes ingenieros no solo copian soluciones. Entienden por qué funciona la solución, bajo qué condiciones se mantiene y qué la rompería. Una solución copiada sin sus condiciones es una bomba de tiempo».
Hamming sobre pruebas: «Probar lo que mediste no es lo mismo que medir lo que importa. Construimos suites de pruebas elaboradas para las propiedades que elegimos probar. Dejamos sin probar las propiedades que no elegimos. Lo que dejamos sin probar es lo que nos sorprende en producción».
Hamming a escala: 'El error que cometes en el primer año de un proyecto es el error que sigues corrigiendo en el décimo año. Las suposiciones iniciales se calcifican. El proyecto crece alrededor de ellas. Nadie reescribe los cimientos.'
La brecha entre la advertencia y la operacionalización
Las advertencias de Hamming eran correctas. Se enseñaron. Se citaron. Se asignaron en los planes de estudio. Pero una advertencia no es un detector. Hamming describió la forma del defecto. No construyó una herramienta que se ejecute en CI y marque rutas calientes O(N²), fugas de identidad ThreadLocal o registro de credenciales. La brecha entre «conocible» y «detectable» es la brecha entre una teoría y su operacionalización como infraestructura automatizada.
MOAD existe porque el campo construyó infraestructura de corrección y no infraestructura de rendimiento o seguridad al mismo nivel. Pruebas unitarias: estándar desde los años 70. Pruebas basadas en propiedades: estándar desde los años 90. Benchmarks de complejidad algorítmica en CI: todavía experimentales en 2026.
Operacionalizando la advertencia
Hamming advirtió sobre la calcificación de la complejidad, las propiedades no probadas, las soluciones copiadas sin sus condiciones y la escala aplastando las suposiciones iniciales. Nos dio el vocabulario. No nos dio el detector.
El pipeline de MOAD llena esa brecha: escanear → ticket → parche → prueba unitaria → divulgar → PR → fusión upstream. Esto es Hamming operacionalizado: no solo la advertencia, sino la detección automatizada y un pipeline de corrección.
La Firma Fester
Un defecto de clase MOAD tiene una firma reconocible. Las cinco condiciones presentes simultáneamente. Las cinco son verificables antes de escribir un solo escaneo:
1. ¿Salida correcta? Ejecuta la suite de pruebas estándar. Si pasa, el defecto es una propiedad de rendimiento o seguridad, no de corrección. Esto significa que la CI estándar no lo detectará.
2. ¿Sin prueba de complejidad? Revisa la configuración de CI. ¿Hay una etapa de benchmark? ¿Compara el comportamiento algorítmico (no solo el tiempo de ejecución) con un commit anterior? Si no: condición presente.
3. ¿Origen en N pequeño? Revisa el git blame y el commit original. ¿Cuál era el tamaño del conjunto de datos en la primera implementación? ¿Ese tamaño es más de 100× menor que la carga actual en producción? Si es así: condición presente.
4. ¿Se propaga la copia? Busca el patrón en toda la base de código y en los ecosistemas. ¿Aparece el mismo patrón estructural en N≥3 bases de código independientes sin ancestro compartido? Si es así: el fósil se ha propagado. Cada copia: un nuevo sitio de infección.
5. ¿Crece la escala? Revisa las métricas de producción. ¿Cuál es N hoy frente a N en el primer despliegue? ¿Se mantiene la tasa de crecimiento? ¿En qué N se vuelve crítico el defecto operativamente?
Si las cinco se revisan y confirman: tienes un defecto de clase MOAD. La corrección siempre es una sustitución de una línea o un método. Lo difícil es el descubrimiento. Lo fácil es la corrección.
Esto es lo que Hamming quiso decir: la ingeniería no trata de la corrección. La corrección es sencilla una vez que la ves. La ingeniería trata de construir los sistemas que te permiten verla.
Aplica la firma
La firma de fester MOAD: salida correcta + sin prueba de complejidad + origen en N pequeño + copia se propaga + escala crece.
Esta firma no se limita a los cinco defectos MOAD. Describe una clase de defecto que persiste en cualquier sistema donde las pruebas de corrección son la única puerta de calidad automatizada.