Bagaimana Sedimen Kode Terbentuk
Batuan sedimen terbentuk melalui pengendapan, bukan ledakan. Setiap lapisan: benar untuk zamannya. Setiap lapisan: lebih tua dari lapisan di atasnya. Lapisan tertua mengeras sebelum ekosistem matang di sekitarnya. Bukan kesalahan yang menyebabkannya. Waktu yang menyebabkannya.
MOAD-0001 bekerja dengan cara yang sama.
Kisah Pembentukan
Sebuah penelusuran graf yang ditulis pada tahun 1993:
List<Node> visited = new ArrayList<>();
Stack<Node> stack = new Stack<>();
stack.push(start);
while (!stack.isEmpty()) {
Node n = stack.pop();
if (!visited.contains(n)) { // pemindaian linear O(N)
visited.add(n);
for (Node neighbor : n.getNeighbors())
stack.push(neighbor);
}
}
Kode ini: benar. Tes: lulus. Pada tahun 1993, graf memiliki 50 simpul.
50 node: 50 × 25 rata-rata dipindai = 1.250 operasi. Tidak terlihat.
Kode tersebut masuk ke version control. Disalin ke tutorial. Dibungkus dalam library. Dikirim dalam build tools, package manager, & dependency resolver. Pada 2024, pola yang sama berjalan pada dependency graph dengan 50.000 node.
50.000 node: 50.000 × 25.000 rata-rata dipindai = 1.250.000.000 operasi.
Build 1 detik menjadi 17 menit.
Kodenya tidak berubah. Dunia di sekitarnya yang berkembang. Setiap lapisan sedimen: benar saat pengendapan. Mahal saat penggalian.
Sedimen Anda
Kode sedimen tidak mengandung kesalahan logika. Ia mengandung asumsi performa yang tidak lagi berlaku ketika skala berubah. Kode tersebut tetap menghasilkan hasil yang benar; hanya biayanya yang berubah.
Perbedaan ini penting untuk diagnosis. Kesalahan logika menghasilkan jawaban yang salah. Cacat sedimen menghasilkan jawaban yang benar dengan biaya yang tidak dapat diterima.
Lima Bentuk MOAD-0001
MOAD-0001 muncul dalam lima bentuk terdokumentasi di lebih dari 60 ekosistem perangkat lunak. Strukturnya: uji keanggotaan menggunakan wadah sekuensial, yang disarangkan di dalam perulangan atas koleksi yang sama atau terkait.
Lima Bentuk
| Domain | Pola | Wadah Sekuensial | Wadah yang Benar |
|---|---|---|---|
| Penelusuran graf | if (!stack.contains(n)) dalam DFS/Tarjan | ArrayList | HashSet |
| Deduplikasi rute/event | TAILQ_FOREACH strcmp per permintaan | linked list | HashMap |
| Pelacakan tabrakan | findLinearSearch() per tick fisika | array | unordered_set |
| Resource allocation filter | List.contains() dalam stream filter | ArrayList | HashSet |
| A* pathfinding open-list | LocalVector::find() per tetangga | vector | stored heap index |
Semua lima bentuk berbagi struktur yang sama: pemeriksaan keanggotaan yang disisipkan di dalam loop, menggunakan kontainer yang memerlukan pemindaian linear untuk menjawab pertanyaan keanggotaan.
Daftar Kata Kunci Pemindaian
Mengaudit untuk MOAD-0001 berarti mencari kata kunci pengujian keanggotaan di dalam loop:
- Python: in dengan variabel list, .count(), list.index()
- Java: ArrayList.contains(), List.contains(), LinkedList.contains()
- JavaScript: Array.includes(), Array.indexOf(), Array.find()
- C++: std::vector::find(), manual loop dengan perbandingan ==
- Go: slices.Contains(), manual loop pada slice
Perbaikan di setiap kasus: ganti sequential container dengan hash container. list → set. ArrayList → HashSet. Array → Set. vector → unordered_set. slice → map[T]struct{}.
Satu kata kunci. Satu substitusi. Nol perubahan perilaku. 1.000× percepatan pada N=1.000.
Audit sebuah Fragmen Kode
Terapkan pengenalan pola MOAD-0001 pada fragmen kode nyata.
Satu Baris, Empat Bahasa
Perbaikan untuk MOAD-0001 dalam empat bahasa:
# Python
visited = [] # SEBELUM: keanggotaan O(N)
visited = set() # AFTER: O(1) membership
// Java
List<Node> visited = new ArrayList<>(); // BEFORE
Set<Node> visited = new HashSet<>(); // AFTER
// JavaScript
const visited = []; // SEBELUM: Array.includes() O(N)
const visited = new Set(); // SETELAH: Set.has() O(1)
// visited.push(n) → visited.add(n)
// visited.includes(n) → visited.has(n)
// Go
visited := []NodeID{} // SEBELUM: slices.Contains() O(N)
visited := make(map[NodeID]struct{}) // SETELAH: map lookup O(1)
// _, ok := visited[n] untuk pengecekan keanggotaan
// visited[n] = struct{}{} untuk penyisipan
Dalam setiap kasus: perilaku sama, keluaran sama, tes tetap lulus. Hanya laju pertumbuhan yang berubah.
Apa yang TIDAK Diubah oleh Perbaikan Ini
- Perilaku logis algoritma: depth-first tetap mengunjungi secara depth-first
- Ketepatan keluaran: node yang sama dikunjungi dalam urutan yang sama (dalam DFS)
- Hasil pengujian: setiap pengujian yang memeriksa ketepatan tetap lulus
Apa yang Diubah oleh Perbaikan Ini
- Pengujian keanggotaan: O(N) → O(1)
- Total loop: O(N²) → O(N)
- Pada N=1.000: 1.000× lebih cepat
- Pada N=10.000: 10.000× lebih cepat
Satu Batasan: Urutan
Kontainer hash (set, HashSet, unordered_set) tidak mempertahankan urutan penyisipan. Di Python 3.7+, dict mempertahankan urutan penyisipan; set biasa tidak. Di Java, HashSet tidak mempertahankan urutan; LinkedHashSet melakukannya.
Jika urutan penting bersamaan dengan keanggotaan: pertahankan dua struktur. Sebuah set (atau HashSet) untuk pengujian keanggotaan O(1). Sebuah list terpisah (atau ArrayList) untuk traversal berurutan. Atau gunakan LinkedHashSet di Java, yang menyediakan keduanya.
Untuk MOAD-0001 dalam traversal graf: visited menjawab pertanyaan biner (apakah node ini sudah pernah dilihat?). Urutan tidak penting untuk pertanyaan keanggotaan. Urutan traversal berasal dari stack atau queue, bukan dari visited.
Keanggotaan vs Pengurutan
Dalam algoritma komponen terhubung kuat Tarjan, onStack melacak node mana yang masih berada di DFS call stack saat ini. Ia harus menjawab dua pertanyaan: (1) keanggotaan — apakah node ini saat ini berada di stack? (2) di akhir jalur DFS, pop node secara berurutan hingga node ini muncul.
Implementasi naif menggunakan List untuk onStack, menjawab pertanyaan keanggotaan dengan contains() — O(N) per pemeriksaan, O(N²) total untuk graf besar.
Mengapa Ini Adalah Pengungkapan, Bukan Patch
MOAD-0001 exists in over 1,000 verified sites across 60+ software ecosystems. Graph traversal in build tools, route deduplication in network routing daemons, collision detection in game engines, resource allocation in operating system schedulers.
Each site: correct code. Each site: O(N²) growth waiting for N to cross a threshold.
The Disclosure Pipeline
A patch without upstream disclosure fixes one site. The pattern recurs in the next version, the next library, the next language port. Disclosure: name the pattern, document it as CWE-407 (Algorithmic Complexity: Inefficient Algorithmic Complexity), publish the recognition heuristics & the one-line fix. Then every developer who reads the disclosure can recognize & fix their own instance.
Hamming called this 'giving a fish vs teaching fishing.' The patch gives a fish. The disclosure — MOAD-0001 named, pattern documented, fix generalized — teaches the heuristic.
Ekstensi Permacomputer
Hamming bekerja pada solusi titik: memperbaiki filter ini, meningkatkan kode ini. Unhamming menambahkan lapisan pengungkapan: menamai pola, mempublikasikan heuristik, & memberikannya kepada khalayak umum.
Prinsip pengetahuan-komponen berlaku di sini pada skala ekosistem. Satu peneliti menamai sebuah pola. Seratus pengembang mengenalinya di basis kode mereka sendiri. Seribu baris kode O(N²) menjadi O(N). Infrastruktur menjadi lebih cepat bagi semua orang yang membangun di atasnya.
Ini adalah naga yang sedang tumbuh: api yang sama (bekerja pada masalah penting, pengetahuan komponen, pemikiran sistem), penerbangan yang berbeda (pengungkapan terbuka, kepemilikan bersama, tanpa patron yang diperlukan).