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

un

gast
1 / ?
terug naar lessen

Naam geven is niet vinden

Je kent nu zeven MOAD-patronen. Namen kennen is belangrijk: je kunt een patroon herkennen als je het ziet. Maar herkenning in een gecontroleerde les verschilt van detectie in een codebase die je nooit hebt geopend.

Een codebase labelt haar defecten niet. Een sedimentaire MOAD komt niet met een opmerking die zegt // O(N²) — fix this. Een thundering herd kondigt zich niet aan als een cache miss stampede. Je vindt ze door code te lezen met een specifieke vraag in gedachten: welke gegevensstructuur bevat deze waarden, en welke bewerkingen werken eraan binnen een lus?

Detectie is een vaardigheid los van herkenning. Herkenning zegt: ja, dat patroon is MOAD-0001. Detectie zegt: laat me alle plaatsen in deze codebase vinden waar dat patroon zou kunnen bestaan, of ik de volledige code kan zien of alleen een symboolnaam.

Zeven MOADs: substraten, signaturen, reparaties

Eerste scan

Een eerste scan gebruikt grep. Elke MOAD heeft een substraat: een gegevensstructuur of API waarvan de aanwezigheid, dicht bij bepaalde bewerkingen, een signaal is dat onderzoek waard is.

MOAD-0001 (Sedimentair): List.contains in een lus

# 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 (Verstrengeld): gedeelde veranderbare vlag over fasen heen

# 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 (Gelekt Context): ThreadLocal in een gepoelde executor

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

MOAD-0004 (Gelogd geheim): HTTP-headers in loguitvoer

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

MOAD-0005 (Thundering Herd): cachemis zonder synchronisatie

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

Deze patronen produceren kandidaten, geen geconfirmeerde defecten. Elke kandidaat heeft triage nodig: lees de omringende code, verifieer het type gegevensstructuur, bevestig dat de bewerking op schaal wordt uitgevoerd.

Kies één MOAD uit MOAD-0001 tot MOAD-0005. Beschrijf een concrete detectiestap die je zou nemen in een codebase die je nog nooit hebt gelezen: wat je zoekt, hoe een positieve treffer eruitziet, & wat een geconfirmeerd defect onderscheidt van een vals positief.

Code lezen voor complexiteit

Grep vindt kandidaten. Lezen bevestigt ze. Wanneer je een kandidaatbestand opent, lees je met één vraag: groeit de kosten van deze bewerking met invoergrootte?

Voor MOAD-0001, het bevestigingsprotocol:

1. Vind de buitenlus. Wat bepaalt het aantal iteraties?
2. Vind de interne bewerking (.contains, .indexOf, 'in'). Op welke gegevensstructuur werkt het?
3. Groeit die gegevensstructuur met dezelfde invoer die de buitenlus aandrijft?
4. Zo ja: de kosten zijn O(N²) waarbij N = invoergrootte. Defect bevestigd.
5. Zo nee: de interne structuur is begrensd (config, enum, kleine constante). Vals positief.

Een graaftraversal die N knooppunten bezoekt, controleert een visited-lijst op elke stap: zowel de lus als de interne gegevensstructuur groeien met N. Bevestigd.

Een verzoekhandler controleert een allowlist van 5 admin IP's: de allowlist groeit nooit met verzoekvolume. Vals positief.

Hetzelfde protocol geldt voor elke MOAD: identificeer het uiterlijke stuurprogramma, identificeer de interne structuur, vraag of beide samen schalen.

Surge score: prioritering van je bevindingen

Niet alle bevestigde defecten rechtvaardigen onmiddellijke patching. Een MOAD in een bibliotheek met 10.000 downstream afhankelijkheden heeft een hogere surge score dan dezelfde MOAD in een privé intern hulpmiddel.

Surge score = speedup × in-degree. Speedup: hoe veel sneller loopt de fix bij typische productievermenigvuldiging? In-degree: hoeveel downstream pakketten of services zouden de fix automatisch erven wanneer upstream het samenvoegt?

Een bevestigde MOAD-0001 in Apache Maven's dependency resolver, uitgevoerd op grafieken van 50.000 knooppunten, met 1.000+ downstream Maven-plugins die wijzigingen automatisch erven: surge score is zeer hoog. Deze fix hoort vooraan je wachtrij.

Een bevestigde MOAD-0001 in een hulpmiddel voor één gebruiker zonder afhankelijkheden: surge score bijna nul. Waard om te repareren, maar niet urgent.

Workaholic vs. glutton knooppunten. Een knooppunt met hoge betweenness & hoge speedup is een workaholic: het handelt kritische flow af & spoelt downstream wachtrijen door wanneer deblokkeerd. Patch het alleen nadat je downstream capaciteit hebt bevestigd. Een knooppunt met hoog out-degree & lage speedup is een glutton: het consumeert alles wat eraan wordt gevoerd en voelt geen pijn. Het patchen van een workaholic zonder downstream capaciteit te faseren creëert MOAD-0005 (thundering herd) op infrastructuurschaal.

Fabriek DAG: workaholic & glutton knooppatronen

Je hebt MOAD-0001 op twee plaatsen bevestigd: (A) een dependency resolver in een buildtool met 200.000 actieve projecten die ervan afhangen, uitgevoerd op grafieken van 10.000-knoop afhankelijkheidsbomen; (B) een graafnutility in een interne datapijplijn bij één bedrijf, uitgevoerd op grafieken van 50 knooppunten. Vergelijk hun surge scores. Welke patch je eerst, en welke stappen onderneem je voor disclosure?

Scan naar samenvoegen: een MOAD-pijplijn

Een bevestigd defect met een hoge surge score gaat door een pijplijn. Elke fase produceert een artefact. Geen fase is optioneel.

scan    → kandidaatlijst (grep-uitvoer, statische analysresultaten)
ticket  → defectbeschrijving (MOAD-nummer, locatie, complexiteitsanalyse)
patch   → codewijziging (gegevensstructuurwisseling, primitieve adoptie)
test    → eenheidstest (O(1)-bewijs: tijd de fix op N=100 en N=10.000)
UNDF    → openbare disclosurebericht (undefect.com, publiek domein)
disclose → CVE- of CWE-referentie indien beveiligingsrelevant
PR      → upstream pull request met patch + test + UNDF-link
merge   → onderhoudsacceptatie; fix verspreidt zich via versiebump

Elk artefact voert de volgende fase in. Een patch zonder test kan niet geverifieerd worden. Een test zonder disclosure kan niet naar andere instanties van hetzelfde patroon verspreiden. Een disclosure zonder upstream PR strandt de fix in een fork.

Een MOAD-bericht (UNDF) is de fase die de meeste engineers overslaan. Ze repareren het defect, dienen een PR in, en beschouwen zichzelf als klaar. Maar een fix zonder benoemd bericht betekent dat elke toekomstige engineer die hetzelfde patroon tegenkomt, zowel het probleem als de fix onafhankelijk moet herontdekken. Een MOAD-bericht sluit de kennislus: het benoemt het patroon, toont de detectiemethode, & koppelt aan de patch. Toekomstige onderzoekers vinden de fix door naar de patternnaam te zoeken.

Planeet patching op schaal. Een enkele MOAD-0001 fix in een veel gebruikte bibliotheek verspreidt naar elk project dat het importeert. Een MOAD-bericht zorgt ervoor dat engineers in projecten die die bibliotheek nooit zullen upgraden, nog steeds de fix leren. Beide paden lopen parallel.

Een defectticket schrijven

Een goed defectticket beantwoordt vijf vragen:

1. Waar: exact bestand, klasse, functie en regelbereich
2. Wat: het type gegevensstructuur en de bewerking eraan
3. Waarom: de complexiteitsanalyse (O(N²) of erger, met N gedefinieerd)
4. Impact: welke invoer triggeert worst-case gedrag, en op welke schaal
5. Fix: de gegevensstructuur of primitieve om te vervangen

Een ticket dat alle vijf beantwoordt, is zelfstandig: een onderhouder die je analyse nooit heeft gelezen, kan je bevinding reproduceren en je fix verifiëren. Tickets die (3) of (4) overslaan, vereisen dat de onderhouder je complexiteitsanalyse herhaalt voordat hij kan samenvoegen. Die wrijving vermindert de waarschijnlijkheid van samenvoeging.

Geloofwaardigheid samengesteld. Een eerste PR die een duidelijk ticket, een goed gericht patch, & een benchmarktest bevat, wordt samengevoegd. Een tweede PR van dezelfde auteur wordt met minder wrijving beoordeeld. Een derde PR wordt beoordeeld door de onderhouder die de eerste twee samengevoegd. Reputatie in open source is een grootboek van artefacten: elke geaccepteerde patch verdient vertrouwen voor de volgende.

Schrijf een minimaal defectticket voor een MOAD-0001 die je zou verwachten in een graafbibliotheek. Inclusief: (1) een plausibele bestand-/functienaam, (2) de gegevensstructuur & bewerking, (3) een complexiteitsverklaring, (4) een typisch impactscenario, (5) de fix.

Een echte kandidaat lezen

Hier is een echte MOAD-0001 kandidaat in Python. Lees het en voltooi het triageprotocol.

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

Triagesvragen:

1. Welke gegevensstructuur is `seen`?
2. Welke bewerking loopt eraan op regel 6?
3. Groeit `seen` met invoergrootte?
4. Groeit de lus die recursieve aanroepen aandrijft ook met invoergrootte?
5. Is dit een bevestigde MOAD-0001 of een vals positief?
Werk door de vijf triagesvragen voor deze code. Schrijf dan de eenregelfix en leg uit waarom de output van de functie niet verandert.

Jouw patch

Een bevestigd defect met een hoge surge score vereist een volledige patch: de codecorrectieing, een test die de verbetering bewijst, & een MOAD-berichtoverzicht.

De test moet een prestatietest zijn, geen correctheidstest. Een correctheidstest slaagt voor en na de fix — dat is het punt; output verandert niet. Een prestatietest op twee invoergroottes bewijst de verbetering:

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

Voor de fix groeit verstreken tijd kwadratisch met n. Na de fix, groeit het lineair. Print beide en neem de getallen op in je PR-beschrijving.

Een MOAD-berichtoverzicht behandelt: de patternnaam, het substraat (Python dependency resolver), de detectiemethode (grep voor in seen waarbij seen begint als []), de fix, & een link naar je PR. Het bericht gaat naar undefect.com als publiek domein. Toekomstige engineers zoeken naar 'Python list membership in loop slow' zullen het vinden.

Je hebt MOAD-0001 bevestigd & gepatcht in een populaire Python verpakkingstool. Voordat je de PR opent, wat drie dingen neem je op in de PR-beschrijving, en waarom is elk ervan belangrijk voor de onderhouder?