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

un

invitado
1 / ?

Nombrar No Es Encontrar

Ya conoces siete patrones MOAD. Saber los nombres importa: te permite reconocer un patrón cuando lo ves. Pero el reconocimiento en una lección controlada difiere de la detección en una base de código que nunca has abierto.

Una base de código no etiqueta sus defectos. Un MOAD sedimentario no viene con un comentario que diga // O(N²) — arreglalo. Una multitud ensordecedora no se anuncia a sí misma como una avalancha de pérdida de caché. Los encuentras leyendo código con una pregunta específica en mente: ¿qué estructura de datos contiene estos valores, & qué operaciones se ejecutan contra ella dentro de un bucle?

La detección es una habilidad separada del reconocimiento. El reconocimiento dice: sí, ese patrón es MOAD-0001. La detección dice: déjame encontrar todos los lugares en esta base de código donde ese patrón podría existir, ya sea que pueda ver el código completo o solo un nombre de símbolo.

Seven MOADs: substrates, signatures, fixes

Primer Escaneo

Un primer paso usa grep. Cada MOAD tiene un sustrato: una estructura de datos o API cuya presencia, cerca de ciertas operaciones, es una señal que vale la pena investigar.

MOAD-0001 (Sedimentario): List.contains en un bucle

# Signal: membership test on a list variable inside a loop
grep -rn '.contains(' src/ | grep -v HashSet | grep -v TreeSet
grep -rn 'visited =' src/ | grep -v set | grep -v Set

MOAD-0002 (Intertangle): shared mutable flag across phases

# Signal: static mutable field written by one subsystem, read by another
grep -rn 'static ' src/ | grep -v final | grep -v class | grep -v void

MOAD-0003 (Leaked Context): ThreadLocal in a pooled executor

# Signal: ThreadLocal.set() without guaranteed ThreadLocal.remove()
grep -rn 'ThreadLocal' src/
grep -rn 'ThreadLocal.set' src/ -l

MOAD-0004 (Logged Secret): HTTP headers in log output

# Signal: log call with headers variable near auth endpoints
grep -rn 'log.*header' src/
grep -rn 'Authorization' src/ --include='*.log'

MOAD-0005 (Thundering Herd): cache miss with no synchronization

# Signal: cache.get() + null check + cache.put() without lock
grep -rn 'cache.get' src/ -A4 | grep 'cache.put'

Estos patrones producen candidatos, no defectos confirmados. Cada candidato necesita triage: lee el código circundante, verifica el tipo de estructura de datos, confirma que la operación se ejecuta a escala.

Elige un MOAD de MOAD-0001 a MOAD-0005. Describe un paso de detección concreto que tomarías en una base de código que nunca has leído: qué buscas, cómo se ve un resultado positivo, & qué distingue un defecto confirmado de un falso positivo.

Leer Código para Complejidad

Grep encuentra candidatos. Leer los confirma. Cuando abres un archivo candidato, lees con una pregunta: ¿el costo de esta operación crece con el tamaño de entrada?

Para MOAD-0001, el protocolo de confirmación:

1. Find the outer loop. What bounds its iteration count?
2. Find the inner operation (.contains, .indexOf, 'in'). What data structure does it run against?
3. Does that data structure grow with the same input that drives the outer loop?
4. If yes: the cost is O(N²) where N = input size. Confirmed defect.
5. If no: the inner structure is bounded (config, enum, small constant). False positive.

Un recorrido de grafos visitando N nodos, verificando una lista visited en cada paso: tanto el bucle como la estructura de datos interna crecen con N. Confirmado.

Un manejador de solicitud verificando una lista blanca de 5 IPs de administrador: la lista blanca nunca crece con el volumen de solicitudes. Falso positivo.

El mismo protocolo se aplica a cada MOAD: identifica el controlador externo, identifica la estructura interna, pregunta si ambas escalan juntas.

Surge Score: Priorizando tus Hallazgos

No todos los defectos confirmados justifican parches inmediatos. Un MOAD en una biblioteca con 10,000 dependientes downstream tiene una surge score más alta que el mismo MOAD en una herramienta interna privada.

Surge score = speedup × in-degree. Speedup: ¿cuánto más rápido se ejecuta la solución a la escala de producción típica? In-degree: ¿cuántos paquetes o servicios downstream heredarían la solución automáticamente cuando el upstream la fusione?

Un MOAD-0001 confirmado en el resolvedor de dependencias de Apache Maven, ejecutándose en grafos de 50,000 nodos, con 1,000+ complementos Maven downstream que heredan cambios automáticamente: la surge score es muy alta. Esta solución pertenece al frente de tu cola.

Un MOAD-0001 confirmado en una herramienta CLI de usuario único sin dependientes: surge score cerca de cero. Vale la pena arreglarlo, pero no es urgente.

Nodos workaholic vs. glutton. Un nodo con alta betweenness & alto speedup es un workaholic: maneja flujo crítico & inundará colas downstream cuando se desbloquee. Aplica parches solo después de confirmar la capacidad downstream. Un nodo con alto out-degree & bajo speedup es un glutton: consume todo lo que se le alimenta & no siente dolor. Parchar un workaholic sin preparar la capacidad downstream crea MOAD-0005 (multitud ensordecedora) a escala de infraestructura.

Factory DAG: workaholic & glutton node patterns

Has confirmado MOAD-0001 en dos lugares: (A) un resolvedor de dependencias en una herramienta de construcción con 200,000 proyectos activos dependiendo de ella, ejecutándose en grafos de 10,000 nodos; (B) una utilidad de gráfico en una tubería de datos interna en una única compañía, ejecutándose en grafos de 50 nodos. Compara sus surge scores. ¿Cuál aplicas parches primero, & qué pasos tomas antes de divulgar?

Escanear a Fusionar: Una Tubería MOAD

Un defecto confirmado con una surge score alta se mueve a través de una tubería. Cada etapa produce un artefacto. Ninguna etapa es opcional.

scan    → candidate list (grep output, static analysis results)
ticket  → defect description (MOAD number, location, complexity analysis)
patch   → code change (data structure swap, primitive adoption)
test    → unit test (O(1) proof: time the fix at N=100 and N=10,000)
UNDF    → public disclosure post (undefect.com, public domain)
disclose → CVE or CWE reference if security-relevant
PR      → upstream pull request with patch + test + UNDF link
merge   → maintainer acceptance; fix propagates via version bump

Cada artefacto alimenta la siguiente etapa. Una solución sin una prueba no puede verificarse. Una prueba sin una divulgación no puede propagarse a otras instancias del mismo patrón. Una divulgación sin una PR upstream deja la solución atrapada en un fork.

Un MOAD post (UNDF) es la etapa que la mayoría de los ingenieros omiten. Aplican parches al defecto, envían una PR, & se consideran listos. Pero una solución sin un post nombrado significa que cada futuro ingeniero que encuentre el mismo patrón debe redescubrir tanto el problema como la solución de forma independiente. Un MOAD post cierra el bucle de conocimiento: nombra el patrón, muestra el método de detección, & vincula al parche. Los investigadores futuros encuentran la solución buscando el nombre del patrón.

Parchar el planeta a escala. Una única solución MOAD-0001 en una biblioteca ampliamente utilizada se propaga a cada proyecto que la importa. Un MOAD post asegura que los ingenieros en proyectos que nunca actualicen esa biblioteca aún aprendan la solución. Ambos caminos corren en paralelo.

Escribiendo un Ticket de Defecto

Un buen ticket de defecto responde cinco preguntas:

1. Where: exact file, class, function, and line range
2. What: the data structure type and the operation against it
3. Why: the complexity analysis (O(N²) or worse, with N defined)
4. Impact: what inputs trigger worst-case behavior, and at what scale
5. Fix: the data structure or primitive to substitute

Un ticket que responda a los cinco es autosuficiente: un mantenedor que nunca ha leído tu análisis puede reproducir tu hallazgo & verificar tu solución. Los tickets que saltan (3) o (4) requieren que el mantenedor repita tu análisis de complejidad antes de poder fusionar. Esa fricción reduce la probabilidad de fusión.

La credibilidad se compone. Una primera PR que incluya un ticket claro, una solución bien dirigida, & una prueba de referencia se fusiona. Una segunda PR del mismo autor se revisa con menos fricción. Una tercera PR se revisa por el mantenedor que fusionó las dos primeras. La reputación en código abierto es un libro mayor de artefactos: cada solución aceptada gana confianza para la siguiente.

Escribe un ticket de defecto mínimo para un MOAD-0001 que esperarías encontrar en una biblioteca de gráficos. Incluye: (1) un nombre de archivo/función plausible, (2) la estructura de datos & operación, (3) una declaración de complejidad, (4) un escenario de impacto típico, (5) la solución.

Leyendo un Candidato Real

Aquí hay un candidato real MOAD-0001 en Python. Léelo & completa el protocolo de triage.

class DependencyResolver:
    def resolve(self, package, resolved=None, seen=None):
        if resolved is None:
            resolved = []
        if seen is None:
            seen = []
        if package in seen:
            return
        seen.append(package)
        for dep in self.registry.get_dependencies(package):
            self.resolve(dep, resolved, seen)
        resolved.append(package)
        return resolved

Preguntas de triage:

1. What data structure is `seen`?
2. What operation runs against it on line 6?
3. Does `seen` grow with input size?
4. Does the loop that drives recursive calls also grow with input size?
5. Is this a confirmed MOAD-0001 or a false positive?
Trabaja a través de las cinco preguntas de triage para este código. Luego escribe la solución de una línea & explica por qué no cambia la salida de la función.

Tu Solución

Un defecto confirmado con una surge score alta necesita una solución completa: la corrección de código, una prueba que demuestre la mejora, & un esquema MOAD post.

La prueba debe ser una prueba de desempeño, no una prueba de corrección. Una prueba de corrección pasa antes & después de la solución — ese es el punto; la salida no cambia. Una prueba de desempeño en dos tamaños de entrada demuestra la mejora:

import time

def build_graph(n):
    # n packages, each depending on the previous one
    return {f'pkg{i}': [f'pkg{i-1}'] if i > 0 else [] for i in range(n)}

for n in [100, 1000, 5000]:
    registry = build_graph(n)
    resolver = DependencyResolver(registry)
    start = time.perf_counter()
    resolver.resolve(f'pkg{n-1}')
    elapsed = time.perf_counter() - start
    print(f'n={n}: {elapsed:.4f}s')

Antes de la solución, el tiempo transcurrido crece cuadráticamente con n. Después de la solución, crece linealmente. Imprime ambos & incluye los números en tu descripción PR.

Un esquema MOAD post cubre: el nombre del patrón, el sustrato (resolvedor de dependencias de Python), el método de detección (grep para in seen donde seen comienza como []), la solución, & un vínculo a tu PR. El post va a undefect.com como dominio público. Los futuros ingenieros que busquen 'prueba de membresía de lista de Python en bucle lento' lo encontrarán.

Has confirmado & parcheado MOAD-0001 en una herramienta popular de empaquetado de Python. Antes de abrir la PR, ¿qué tres cosas incluyes en la descripción de la PR, & por qué cada una importa al mantenedor?