Naming Is Not Finding
You now know seven MOAD patterns. Knowing names matters: it lets you recognize a pattern when you see it. But recognition in a controlled lesson differs from detection in a codebase you have never opened.
A codebase does not label its defects. A sedimentary MOAD does not come with a comment that says // O(N²) — fix this. A thundering herd does not announce itself as a cache miss stampede. You find them by reading code with a specific question in mind: what data structure holds these values, and what operations run against it inside a loop?
Detection is a skill separate from recognition. Recognition says: yes, that pattern is MOAD-0001. Detection says: let me find all the places in this codebase where that pattern might exist, whether I can see the full code or only a symbol name.
First Scan
A first pass uses grep. Each MOAD has a substrate: a data structure or API whose presence, near certain operations, is a signal worth investigating.
MOAD-0001 (Sedimentary): List.contains in a loop
# 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'
These patterns produce candidates, not confirmed defects. Every candidate needs triage: read the surrounding code, verify the data structure type, confirm the operation runs at scale.
Reading Code for Complexity
Grep finds candidates. Reading confirms them. When you open a candidate file, you read with one question: does this operation's cost grow with input size?
For MOAD-0001, the confirmation protocol:
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.
A graph traversal visiting N nodes, checking a visited list on each step: both the loop and the inner data structure grow with N. Confirmed.
A request handler checking an allowlist of 5 admin IPs: the allowlist never grows with request volume. False positive.
The same protocol applies to each MOAD: identify the outer driver, identify the inner structure, ask whether both scale together.
Surge Score: Prioritizing Your Findings
Not all confirmed defects warrant immediate patching. A MOAD in a library with 10,000 downstream dependents has a higher surge score than the same MOAD in a private internal tool.
Surge score = speedup × in-degree. Speedup: how much faster does the fix run at typical production scale? In-degree: how many downstream packages or services would inherit the fix automatically when the upstream merges it?
A confirmed MOAD-0001 in Apache Maven's dependency resolver, running on graphs of 50,000 nodes, with 1,000+ downstream Maven plugins that inherit changes automatically: surge score is very high. This fix belongs at the front of your queue.
A confirmed MOAD-0001 in a single-user CLI tool with no dependents: surge score near zero. Worth fixing, but not urgent.
Workaholic vs. glutton nodes. A node with high betweenness & high speedup is a workaholic: it handles critical flow & will flush downstream queues when unblocked. Patch it only after confirming downstream capacity. A node with high out-degree & low speedup is a glutton: it consumes everything fed to it and feels no pain. Patching a workaholic without staging downstream capacity creates MOAD-0005 (thundering herd) at infrastructure scale.
Scan to Merge: A MOAD Pipeline
A confirmed defect with a high surge score moves through a pipeline. Each stage produces an artifact. No stage is optional.
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
Each artifact feeds the next stage. A patch without a test cannot be verified. A test without a disclosure cannot propagate to other instances of the same pattern. A disclosure without an upstream PR strands the fix in a fork.
A MOAD post (UNDF) is the stage most engineers omit. They fix the defect, submit a PR, and consider themselves done. But a fix without a named post means every future engineer who encounters the same pattern must rediscover both the problem and the fix independently. A MOAD post closes the knowledge loop: it names the pattern, shows the detection method, & links to the patch. Future researchers find the fix by searching for the pattern name.
Planet patching at scale. A single MOAD-0001 fix in a widely-used library propagates to every project that imports it. A MOAD post ensures that engineers in projects who will never upgrade that library still learn the fix. Both paths run in parallel.
Writing a Defect Ticket
A good defect ticket answers five questions:
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
A ticket that answers all five is self-contained: a maintainer who has never read your analysis can reproduce your finding and verify your fix. Tickets that skip (3) or (4) require the maintainer to repeat your complexity analysis before they can merge. That friction reduces the probability of merge.
Credibility compounds. A first PR that includes a clear ticket, a well-targeted patch, & a benchmark test gets merged. A second PR from the same author gets reviewed with less friction. A third PR gets reviewed by the maintainer who merged the first two. Reputation in open source is a ledger of artifacts: each accepted patch earns trust for the next.
Reading a Real Candidate
Here is a real MOAD-0001 candidate in Python. Read it and complete the triage protocol.
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 questions:
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?
Your Patch
A confirmed defect with a high surge score needs a complete patch: the code fix, a test that proves the improvement, & a MOAD post outline.
The test must be a performance test, not a correctness test. A correctness test passes before and after the fix — that is the point; output does not change. A performance test at two input sizes proves the improvement:
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')
Before the fix, elapsed time grows quadratically with n. After the fix, it grows linearly. Print both and include the numbers in your PR description.
A MOAD post outline covers: the pattern name, the substrate (Python dependency resolver), the detection method (grep for in seen where seen starts as []), the fix, & a link to your PR. The post goes to undefect.com as public domain. Future engineers searching for 'Python list membership in loop slow' will find it.