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

un

ospite
1 / ?
torna alle lezioni

Il Naming Non È la Ricerca

Ora conosci sette schemi MOAD. Conoscere i nomi è importante: ti permette di riconoscere uno schema quando lo vedi. Ma il riconoscimento in una lezione controllata differisce dal rilevamento in una base di codice che non hai mai aperto.

Una base di codice non etichetta i suoi difetti. Un MOAD sedimentario non viene fornito con un commento che dica // O(N²) — fix this. Un thundering herd non si annuncia come una cache miss stampede. Li trovi leggendo il codice con una domanda specifica in mente: quale struttura di dati contiene questi valori e quali operazioni vengono eseguite su di essa all'interno di un ciclo?

La rilevazione è un'abilità separata dal riconoscimento. Il riconoscimento dice: sì, quello schema è MOAD-0001. La rilevazione dice: permettimi di trovare tutti i posti in questa base di codice dove lo schema potrebbe esistere, sia che riesca a vedere il codice completo o solo un nome di simbolo.

Sette MOAD: substrati, firme, correzioni

Prima Scansione

Un primo passaggio usa grep. Ogni MOAD ha un substrato: una struttura di dati o un'API la cui presenza, vicino a determinate operazioni, è un segnale degno di indagine.

MOAD-0001 (Sedimentario): List.contains in un ciclo

# Segnale: test di appartenenza su una variabile di lista all'interno di un ciclo
grep -rn '.contains(' src/ | grep -v HashSet | grep -v TreeSet
grep -rn 'visited =' src/ | grep -v set | grep -v Set

MOAD-0002 (Intertangle): flag mutabile condiviso tra fasi

# Segnale: campo statico mutabile scritto da un sottosistema, letto da un altro
grep -rn 'static ' src/ | grep -v final | grep -v class | grep -v void

MOAD-0003 (Contesto Fugato): ThreadLocal in un executor pooled

# Segnale: ThreadLocal.set() senza ThreadLocal.remove() garantito
grep -rn 'ThreadLocal' src/
grep -rn 'ThreadLocal.set' src/ -l

MOAD-0004 (Segreto Registrato): intestazioni HTTP nell'output del log

# Segnale: chiamata di log con variabile headers vicino agli endpoint di autenticazione
grep -rn 'log.*header' src/
grep -rn 'Authorization' src/ --include='*.log'

MOAD-0005 (Mandria Tuonante): cache miss senza sincronizzazione

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

Questi schemi producono candidati, non difetti confermati. Ogni candidato necessita di triage: leggi il codice circostante, verifica il tipo di struttura dati, conferma che l'operazione viene eseguita su larga scala.

Scegli un MOAD da MOAD-0001 a MOAD-0005. Descrivi un passo di rilevamento concreto che faresti in una base di codice che non hai mai letto prima: cosa cerchi, come appare un hit positivo e cosa distingue un difetto confermato da un falso positivo.

Leggere il Codice per la Complessità

Grep trova candidati. La lettura li conferma. Quando apri un file candidato, leggi con una domanda: il costo di questa operazione cresce con la dimensione dell'input?

Per MOAD-0001, il protocollo di conferma:

1. Trova il ciclo esterno. Cosa limita il suo conteggio di iterazioni?
2. Trova l'operazione interna (.contains, .indexOf, 'in'). Su quale struttura di dati viene eseguita?
3. Quella struttura di dati cresce con lo stesso input che guida il ciclo esterno?
4. Se sì: il costo è O(N²) dove N = dimensione dell'input. Difetto confermato.
5. Se no: la struttura interna è limitata (config, enum, piccola costante). Falso positivo.

Un attraversamento di grafo che visita N nodi, controllando una lista visited ad ogni passo: sia il ciclo che la struttura di dati interna crescono con N. Confermato.

Un gestore di richieste che controlla un allowlist di 5 IP di amministrazione: l'allowlist non cresce mai con il volume di richieste. Falso positivo.

Lo stesso protocollo si applica a ogni MOAD: identifica il driver esterno, identifica la struttura interna, chiediti se entrambi scalano insieme.

Surge Score: Dare Priorità ai Tuoi Risultati

Non tutti i difetti confermati garantiscono una correzione immediata. Un MOAD in una libreria con 10.000 dipendenti downstream ha un surge score più alto rispetto allo stesso MOAD in uno strumento interno privato.

Surge score = speedup × in-degree. Speedup: quanto più veloce viene eseguita la correzione su scala di produzione tipica? In-degree: quanti pacchetti o servizi downstream erediterebbero la correzione automaticamente quando l'upstream la unisce?

Un MOAD-0001 confermato nel risolutore di dipendenze di Apache Maven, in esecuzione su grafici di 50.000 nodi, con 1.000+ plugin Maven downstream che ereditano i cambiamenti automaticamente: il surge score è molto alto. Questa correzione appartiene alla testa della tua coda.

Un MOAD-0001 confermato in uno strumento CLI per utente singolo senza dipendenti: surge score vicino a zero. Vale la pena correggerlo, ma non è urgente.

Nodi workaholici vs. ghiottoni. Un nodo con alta betweenness e alto speedup è un workaholic: gestisce il flusso critico e scaricherà le code downstream quando sbloccato. Correggilo solo dopo aver confermato la capacità downstream. Un nodo con alto out-degree e basso speedup è un ghiottone: consuma tutto ciò che gli viene somministrato e non sente dolore. Correggere un workaholic senza preparare la capacità downstream crea MOAD-0005 (mandria tuonante) su scala infrastrutturale.

DAG Factory: schemi di nodi workaholici e ghiottoni

Hai confermato MOAD-0001 in due posti: (A) un risolutore di dipendenze in uno strumento di build con 200.000 progetti attivi che dipendono da esso, in esecuzione su grafici di alberi di dipendenza di 10.000 nodi; (B) un'utilità di grafo in una pipeline di dati interna presso una singola azienda, in esecuzione su grafici di 50 nodi. Confronta i loro surge score. Quale correggi per primo e quali passaggi fai prima di divulgare?

Da Scansione a Merge: Una Pipeline MOAD

Un difetto confermato con un alto surge score passa attraverso una pipeline. Ogni fase produce un artefatto. Nessuna fase è facoltativa.

scan    → lista di candidati (output di grep, risultati di analisi statica)
ticket  → descrizione del difetto (numero MOAD, posizione, analisi di complessità)
patch   → cambio di codice (swap di strutture di dati, adozione primitiva)
test    → test unitario (prova O(1): cronometra la correzione a N=100 e N=10.000)
UNDF    → post di divulgazione pubblica (undefect.com, dominio pubblico)
disclose → riferimento CVE o CWE se rilevante per la sicurezza
PR      → pull request upstream con patch + test + link UNDF
merge   → accettazione del maintainer; la correzione si propaga via version bump

Ogni artefatto alimenta la fase successiva. Una patch senza un test non può essere verificata. Un test senza una divulgazione non può propagarsi ad altre istanze dello stesso schema. Una divulgazione senza una PR upstream trattiene la correzione in un fork.

Un post MOAD (UNDF) è la fase che la maggior parte degli ingegneri omette. Correggono il difetto, inviano una PR, e si considerano soddisfatti. Ma una correzione senza un post denominato significa che ogni futuro ingegnere che incontra lo stesso schema deve riscoprire sia il problema che la correzione in modo indipendente. Un post MOAD chiude il ciclo della conoscenza: nomina lo schema, mostra il metodo di rilevamento e si collega alla patch. I futuri ricercatori trovano la correzione cercando il nome dello schema.

Planet patching su larga scala. Una singola correzione MOAD-0001 in una libreria ampiamente utilizzata si propaga a ogni progetto che la importa. Un post MOAD garantisce che gli ingegneri nei progetti che non aggiorneranno mai quella libreria imparino comunque la correzione. Entrambi i percorsi vengono eseguiti in parallelo.

Scrivere un Ticket di Difetto

Un buon ticket di difetto risponde a cinque domande:

1. Dove: file esatto, classe, funzione e intervallo di righe
2. Cosa: il tipo di struttura di dati e l'operazione su di essa
3. Perché: l'analisi di complessità (O(N²) o peggio, con N definito)
4. Impatto: quali input attivano il comportamento del caso peggiore e su quale scala
5. Correzione: la struttura di dati o primitiva da sostituire

Un ticket che risponde a tutte e cinque è autonomo: un maintainer che non ha mai letto la tua analisi può riprodurre il tuo risultato e verificare la tua correzione. I ticket che saltano (3) o (4) richiedono al maintainer di ripetere l'analisi di complessità prima che possano fare il merge. Quell'attrito riduce la probabilità di merge.

La credibilità si accumula. Una prima PR che include un ticket chiaro, una patch ben mirata e un test di benchmark viene unita. Una seconda PR dello stesso autore viene revisionata con meno attrito. Una terza PR viene revisionata dal maintainer che ha unito i primi due. La reputazione in open source è un registro di artefatti: ogni patch accettata guadagna fiducia per la prossima.

Scrivi un ticket di difetto minimo per un MOAD-0001 che ti aspetteresti di trovare in una libreria di grafici. Includi: (1) un nome file/funzione plausibile, (2) la struttura di dati e l'operazione, (3) una dichiarazione di complessità, (4) uno scenario di impatto tipico, (5) la correzione.

Leggere un Candidato Reale

Ecco un vero candidato MOAD-0001 in Python. Leggilo e completa il protocollo di 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

Domande di triage:

1. Quale struttura di dati è `seen`?
2. Quale operazione viene eseguita su di essa alla riga 6?
3. `seen` cresce con la dimensione dell'input?
4. Il ciclo che guida le chiamate ricorsive cresce anche con la dimensione dell'input?
5. Questo è un MOAD-0001 confermato o un falso positivo?
Affronta le cinque domande di triage per questo codice. Quindi scrivi la correzione in una riga e spiega perché non cambia l'output della funzione.

La Tua Patch

Un difetto confermato con un alto surge score ha bisogno di una patch completa: la correzione del codice, un test che provi il miglioramento e uno schema di post MOAD.

Il test deve essere un test di prestazione, non un test di correttezza. Un test di correttezza passa prima e dopo la correzione — questo è il punto; l'output non cambia. Un test di prestazione a due dimensioni di input prova il miglioramento:

import time

def build_graph(n):
    # n pacchetti, ognuno dipendente dal precedente
    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')

Prima della correzione, il tempo trascorso cresce quadraticamente con n. Dopo la correzione, cresce linearmente. Stampa entrambi e includi i numeri nella descrizione della tua PR.

Uno schema di post MOAD copre: il nome dello schema, il substrato (risolutore di dipendenze Python), il metodo di rilevamento (grep per in seen dove seen inizia come []), la correzione e un link alla tua PR. Il post va a undefect.com come dominio pubblico. I futuri ingegneri che cercano 'l'appartenenza alla lista Python nel ciclo è lento' lo troveranno.

Hai confermato e patchato MOAD-0001 in uno strumento di packaging Python popolare. Prima di aprire la PR, quali tre cose includi nella descrizione della PR e perché ognuna è importante per il maintainer?