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

un

Gast
1 / ?

Benennung ist nicht das gleiche wie Finden

Sie kennen jetzt sieben MOAD-Muster. Namen zu kennen ist wichtig: Das ermöglicht es Ihnen, ein Muster zu erkennen, wenn Sie es sehen. Aber die Erkennung in einer kontrollierten Lektion unterscheidet sich von der Erkennung in einer Codebasis, die Sie noch nie geöffnet haben.

Eine Codebasis kennzeichnet ihre Defekte nicht. Eine Sediment-MOAD kommt nicht mit einem Kommentar wie // O(N²) — beheben Sie dies. Ein tobender Schwarm kündigt sich nicht als Cache-Miss-Stampede an. Sie finden sie, indem Sie Code mit einer bestimmten Frage im Kopf lesen: Welche Datenstruktur hält diese Werte, und welche Operationen laufen dagegen in einer Schleife?

Erkennung ist eine Fähigkeit, die sich von Wiedererkennung unterscheidet. Wiedererkennung sagt: Ja, dieses Muster ist MOAD-0001. Erkennung sagt: Lassen Sie mich alle Orte in dieser Codebasis finden, wo dieses Muster existieren könnte, egal ob ich den vollständigen Code sehe oder nur einen Symbolnamen.

Sieben MOADs: Substrate, Signaturen, Fixes

Erste Analyse

Eine erste Analyse verwendet grep. Jede MOAD hat ein Substrat: eine Datenstruktur oder API, deren Präsenz in der Nähe bestimmter Operationen ein Signal wert zu untersuchen ist.

MOAD-0001 (Sedimentär): List.contains in einer Schleife

# Signal: Zugehörigkeitsprüfung bei einer List-Variable in einer Schleife
grep -rn '.contains(' src/ | grep -v HashSet | grep -v TreeSet
grep -rn 'visited =' src/ | grep -v set | grep -v Set

MOAD-0002 (Intertangle): gemeinsames veränderbares Flag zwischen Phasen

# Signal: statisches veränderbares Feld, geschrieben von einem Subsystem, gelesen von einem anderen
grep -rn 'static ' src/ | grep -v final | grep -v class | grep -v void

MOAD-0003 (Leaked Context): ThreadLocal in einem gepoolten Executor

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

MOAD-0004 (Logged Secret): HTTP-Header in Log-Ausgabe

# Signal: Log-Aufruf mit Header-Variable in der Nähe von Auth-Endpunkten
grep -rn 'log.*header' src/
grep -rn 'Authorization' src/ --include='*.log'

MOAD-0005 (Thundering Herd): Cache-Miss ohne Synchronisierung

# Signal: cache.get() + Null-Prüfung + cache.put() ohne Lock
grep -rn 'cache.get' src/ -A4 | grep 'cache.put'

Diese Muster liefern Kandidaten, keine bestätigten Defekte. Jeder Kandidat braucht Triage: Lesen Sie den umgebenden Code, überprüfen Sie den Datenstrukturtyp, bestätigen Sie, dass die Operation in großem Maßstab läuft.

Wählen Sie eine MOAD aus MOAD-0001 bis MOAD-0005. Beschreiben Sie einen konkreten Erkennungsschritt, den Sie in einer Codebasis durchführen würden, die Sie noch nie gelesen haben: Was Sie suchen, wie ein positiver Treffer aussieht, & was einen bestätigten Defekt von einem falsch positiven unterscheidet.

Code für Komplexität lesen

Grep findet Kandidaten. Das Lesen bestätigt sie. Wenn Sie eine Kandidatendatei öffnen, lesen Sie mit einer Frage: Wächst die Kosten dieser Operation mit der Eingabegröße?

Für MOAD-0001 das Bestätigungsprotokoll:

1. Finden Sie die äußere Schleife. Was begrenzt ihre Iterationszahl?
2. Finden Sie die innere Operation (.contains, .indexOf, 'in'). Gegen welche Datenstruktur läuft sie?
3. Wächst diese Datenstruktur mit derselben Eingabe, die die äußere Schleife antreibt?
4. Falls ja: Die Kosten sind O(N²), wobei N = Eingabegröße. Defekt bestätigt.
5. Falls nein: Die innere Struktur ist begrenzt (Konfiguration, Aufzählung, kleine Konstante). Falsch positiv.

Eine Graphtraversierung, die N Knoten besucht, eine visited-Liste bei jedem Schritt prüft: Sowohl die Schleife als auch die innere Datenstruktur wachsen mit N. Bestätigt.

Ein Request-Handler, der eine Zulassungsliste von 5 Admin-IPs prüft: Die Zulassungsliste wächst nie mit dem Request-Volumen. Falsch positiv.

Das gleiche Protokoll gilt für jede MOAD: Identifizieren Sie den äußeren Treiber, identifizieren Sie die innere Struktur, fragen Sie, ob beide zusammen skaliert werden.

Surge Score: Priorisierung Ihrer Ergebnisse

Nicht alle bestätigten Defekte verdienen eine sofortige Behebung. Eine MOAD in einer Bibliothek mit 10.000 nachgelagerten Abhängigen hat einen höheren Surge Score als die gleiche MOAD in einem privaten internen Tool.

Surge Score = Speedup × In-Degree. Speedup: Wie viel schneller läuft der Fix bei typischer Produktionsskala? In-Degree: Wie viele nachgelagerte Pakete oder Dienste würden Änderungen automatisch erben, wenn der Upstream sie zusammenführt?

Eine bestätigte MOAD-0001 in Apaches Maven Dependency Resolver, läuft auf Graphen von 50.000 Knoten, mit 1000+ nachgelagerten Maven-Plugins, die Änderungen automatisch erben: Der Surge Score ist sehr hoch. Dieser Fix gehört an die Spitze Ihrer Warteschlange.

Eine bestätigte MOAD-0001 in einem einzelnen CLI-Tool mit keinen Abhängigen: Surge Score nahe Null. Wert zu beheben, aber nicht dringend.

Workaholic- vs. Glutton-Knoten. Ein Knoten mit hohem Betweenness & hohem Speedup ist ein Workaholic: Er verarbeitet kritische Flüsse & wird nachgelagerte Warteschlangen spülen, wenn er freigegeben wird. Beheben Sie ihn nur, nachdem Sie die Kapazität im Downstream bestätigt haben. Ein Knoten mit hohem Out-Degree & niedrigem Speedup ist ein Glutton: Er verbraucht alles, das in ihn hineingefüttert wird, & spürt keinen Schmerz. Das Beheben eines Workaholics ohne Staging der Downstream-Kapazität erzeugt MOAD-0005 (Thundering Herd) in Infrastruktur-Skala.

Factory DAG: Workaholic & Glutton-Knoten-Muster

Sie haben MOAD-0001 an zwei Orten bestätigt: (A) ein Dependency Resolver in einem Build-Tool mit 200.000 aktiven Projekten, die darauf angewiesen sind, der auf Graphen von 10.000 Knoten Abhängigkeitsbäumen läuft; (B) ein Graph-Utility in einer internen Data Pipeline bei einem Unternehmen, der auf Graphen von 50 Knoten läuft. Vergleichen Sie ihre Surge Scores. Welches beheben Sie zuerst, und welche Schritte unternehmen Sie vor der Offenlegung?

Scan bis Merge: Eine MOAD-Pipeline

Ein bestätigter Defekt mit einem hohen Surge Score durchläuft eine Pipeline. Jede Stufe erzeugt ein Artefakt. Keine Stufe ist optional.

Scan    → Kandidatenliste (grep-Ausgabe, Ergebnisse statischer Analyse)
Ticket  → Defektbeschreibung (MOAD-Nummer, Ort, Komplexitätsanalyse)
Patch   → Code-Änderung (Datenstruktur-Tausch, Primitive Adoption)
Test    → Einheitstest (O(1)-Proof: Zeit den Fix bei N=100 & N=10.000)
UNDF    → Öffentliche Offenlegungspost (undefect.com, public domain)
Offenlegung → CVE oder CWE Referenz, falls sicherheitsrelevant
PR      → Upstream Pull Request mit Patch + Test + UNDF-Link
Merge   → Maintainer-Akzeptanz; Fix breitet sich über Version-Bump aus

Jedes Artefakt füttert die nächste Stufe. Ein Patch ohne Test kann nicht verifiziert werden. Ein Test ohne Offenlegung kann sich nicht zu anderen Instanzen desselben Musters ausbreiten. Eine Offenlegung ohne einen Upstream-PR lässt den Fix in einem Fork stecken.

Eine MOAD-Post (UNDF) ist die Stufe, die die meisten Ingenieure auslassen. Sie beheben den Defekt, reichen einen PR ein, & betrachten sich als fertig. Aber ein Fix ohne eine benannte Post bedeutet, dass jeder zukünftige Ingenieur, der auf das gleiche Muster trifft, sowohl das Problem als auch den Fix unabhängig neu entdecken muss. Eine MOAD-Post schließt die Wissenssschleife: Sie benennt das Muster, zeigt die Erkennungsmethode, & verlinkt den Patch. Zukünftige Forscher finden den Fix, indem sie nach dem Musternamen suchen.

Planetenpflastern in Großmaßstab. Ein einzelner MOAD-0001 Fix in einer weit verbreiteten Bibliothek breitet sich zu jedem Projekt aus, das sie importiert. Eine MOAD-Post stellt sicher, dass Ingenieure in Projekten, die diese Bibliothek nie aktualisieren werden, immer noch den Fix lernen. Beide Wege laufen parallel.

Schreiben eines Defekttickets

Ein gutes Defektticket beantwortet fünf Fragen:

1. Wo: exakte Datei, Klasse, Funktion, und Zeilenbereich
2. Was: der Datenstrukturtyp & die Operation dagegen
3. Warum: die Komplexitätsanalyse (O(N²) oder schlimmer, mit N definiert)
4. Auswirkung: welche Eingaben triggern Worst-Case-Verhalten, & bei welcher Skala
5. Fix: die Datenstruktur oder Primitive zum Ersetzen

Ein Ticket, das alle fünf beantwortet, ist in sich geschlossen: Ein Maintainer, der Ihre Analyse nie gelesen hat, kann Ihren Fund reproduzieren & Ihren Fix überprüfen. Tickets, die (3) oder (4) überspringen, erfordern vom Maintainer, Ihre Komplexitätsanalyse zu wiederholen, bevor er zusammenführen kann. Diese Reibung reduziert die Wahrscheinlichkeit eines Merge.

Glaubwürdigkeit wächst zusammen. Ein erster PR, der ein klares Ticket, einen gut gezielten Patch, & einen Benchmark-Test enthält, wird zusammengeführt. Ein zweiter PR des gleichen Autors wird mit weniger Reibung überprüft. Ein dritter PR wird vom Maintainer überprüft, der die ersten zwei zusammengeführt hat. Ruf in Open Source ist ein Ledger von Artefakten: Jeder akzeptierte Patch verdient Vertrauen für den nächsten.

Schreiben Sie ein minimales Defektticket für eine MOAD-0001, die Sie in einer Graph-Bibliothek erwarten würden zu finden. Enthalten Sie: (1) einen plausiblen Datei-/Funktionsnamen, (2) die Datenstruktur & Operation, (3) eine Komplexitätsaussage, (4) ein typisches Impact-Szenario, (5) den Fix.

Einen echten Kandidaten lesen

Hier ist ein echter MOAD-0001-Kandidat in Python. Lesen Sie es & vervollständigen Sie das Triage-Protokoll.

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

Triage-Fragen:

1. Welche Datenstruktur ist `seen`?
2. Welche Operation läuft dagegen in Zeile 6?
3. Wächst `seen` mit der Eingabegröße?
4. Wächst die Schleife, die rekursive Aufrufe antreibt, auch mit der Eingabegröße?
5. Ist dies ein bestätigter MOAD-0001 oder ein falsch positiv?
Durcharbeiten Sie die fünf Triage-Fragen für diesen Code. Schreiben Sie dann den One-Line-Fix & erklären Sie, warum er die Ausgabe der Funktion nicht ändert.

Ihr Patch

Ein bestätigter Defekt mit einem hohen Surge Score braucht einen vollständigen Patch: Die Code-Änderung, ein Test, der die Verbesserung beweist, & eine MOAD-Post-Gliederung.

Der Test muss ein Leistungstest sein, kein Korrektheitstest. Ein Korrektheitstest besteht vor & nach dem Fix — das ist der Punkt; die Ausgabe ändert sich nicht. Ein Leistungstest bei zwei Eingabegrößen beweist die Verbesserung:

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')

Vor dem Fix wächst die verstrichene Zeit quadratisch mit n. Nach dem Fix wächst sie linear. Geben Sie beide aus & fügen Sie die Zahlen in die PR-Beschreibung ein.

Eine MOAD-Post-Gliederung behandelt: den Musternamen, das Substrat (Python Dependency Resolver), die Erkennungsmethode (grep nach in seen, wo seen als [] beginnt), den Fix, & einen Link zu Ihrem PR. Der Post geht zu undefect.com als Public Domain. Zukünftige Ingenieure, die nach 'Python List Membership in Loop slow' suchen, werden ihn finden.

Sie haben MOAD-0001 in einem beliebten Python-Packaging-Tool bestätigt & behoben. Bevor Sie den PR öffnen, was drei Dinge schließen Sie in die PR-Beschreibung ein, & warum ist jede für den Maintainer wichtig?