ousterhout-quality-program
Apa fungsinya
Gunakan kapan pun kode yang ditulis atau ditinjau menciptakan atau mengubah batas — modul baru, kelas, komponen, helper, hook, layanan, atau pembungkus; setiap ekstraksi atau sentralisasi kode bersama; setiap momen "mari kita buat ini dapat digunakan ulang" — dan saat secara eksplisit meninjau, merombak, atau merancang modul. Menilai apakah sebuah abstraksi layak dipertahankan: kedalaman modul, apakah keputusan desain harus disembunyikan, apakah kode yang diduplikasi melindungi invarian bersama atau hanya mirip, apakah sebuah antarmuka stabil. Melindungi dari SOLID/Clean Code mekanis yang menghasilkan banyak kelas dangkal. Juga mendefinisikan tes biaya pembaca (kode yang murah untuk dibaca dan diubah oleh manusia dan agen) serta prosedur untuk merombak basis kode yang ada agar sesuai standar ini.
Pemasangan membuka entri ini di aplikasi desktop AgentsRoom Anda. Jika aplikasinya belum terpasang, Anda akan diarahkan ke halaman unduhan.
SKILL.md
---
name: ousterhout-quality-program
description: Gunakan kapan pun kode yang ditulis atau ditinjau menciptakan atau mengubah batas — modul baru, kelas, komponen, helper, hook, layanan, atau pembungkus; setiap ekstraksi atau sentralisasi kode bersama; setiap momen "mari kita buat ini dapat digunakan ulang" — dan saat secara eksplisit meninjau, merombak, atau merancang modul. Menilai apakah sebuah abstraksi layak dipertahankan: kedalaman modul, apakah keputusan desain harus disembunyikan, apakah kode yang diduplikasi melindungi invarian bersama atau hanya mirip, apakah sebuah antarmuka stabil. Melindungi dari SOLID/Clean Code mekanis yang menghasilkan banyak kelas dangkal. Juga mendefinisikan tes biaya pembaca (kode yang murah untuk dibaca dan diubah oleh manusia dan agen) serta prosedur untuk merombak basis kode yang ada agar sesuai standar ini.
---
# Program Kualitas Ousterhout
## Ikhtisar
Tugas sebuah modul adalah menyembunyikan kompleksitas di balik antarmuka yang kecil. Ukuran inti adalah **kedalaman**: modul yang dalam menawarkan antarmuka sederhana atas fungsionalitas yang substansial; antarmuka modul yang dangkal hampir sama kompleksnya dengan implementasinya, sehingga tidak memberikan manfaat apa pun. Kompleksitas adalah apa yang Anda rasakan ketika sebuah perubahan memaksa Anda untuk memahami atau menyentuh kode yang tidak Anda duga — Ousterhout menyebut dua sumbernya: **ketergantungan** (Anda tidak bisa mengubah A tanpa mengubah B) dan **ketidakjelasan** (informasi penting tidak jelas).
Ousterhout sendiri memberi tahu Anda seperti apa *perasaan* modul yang baik. Ini paling kuat bila digabungkan dengan beberapa lensa lain yang memberi tahu Anda di mana batas-batasnya dan bagaimana bergerak ke arah itu dengan aman. Skill ini adalah lensa gabungan tersebut.
## Di Mana Review Sebenarnya Salah
Dua kegagalan yang skill ini ada untuk memperbaiki — yang diamati berulang kali dalam kode yang ditulis agen — adalah pada **perbaikan**, bukan pada putusan pisah/jangan pisah itu sendiri:
1. **Perbaikan dangkal.** Diberikan enam `as unknown as` cast, reviewer tanpa bantuan mengumpulkannya menjadi satu helper generik `castRows<T>()` — lebih rapi, tapi ketidakjelasan tetap ada. Perbaikan dalam adalah pemetaan row→domain yang bertipe dengan tes yang dipasang terlebih dahulu (menerapkan Parnas: cast adalah bau dari batas yang hilang; Beck: buktikan pemetaan sebelum memindahkannya). Merapikan bau bukan berarti menghilangkannya.
2. **Ekstraksi refleksif.** Diberikan logika pembaruan yang sama diulang di tiga komponen saudara, setiap reviewer tanpa bantuan berkata "ekstrak helper bersama" — refleks DRY. Aturan program ini, memperluas Metz: tunggu invariant, bukan kemunculan ketiga yang mirip — pusatkan ketika kode melindungi aturan bersama, bukan ketika hanya mirip.
Ketika Anda mendapati diri Anda merekomendasikan perbaikan, jalankan melalui keduanya: apakah itu menghilangkan ketidakjelasan atau hanya memindahkannya, dan apakah ekstraksi melindungi invariant atau hanya menghilangkan duplikasi bentuk?
## Gerbang Proporsionalitas
Lewati lensa ini ketika sebuah perubahan tidak menambah nama yang diekspor/diimpor baru, tidak membuat modul/kelas/komponen/helper/hook/service/wrapper baru, dan tidak memusatkan apa pun. Penggantian nama murni, codemod mekanis, edit konfigurasi/data, dan perbaikan satu baris dikecualikan. Jika ragu, jalankan hanya dua tes inti (kedalaman, invariant) dan berhenti di situ.
## Aturan Lengkap
Setiap potongan kode yang dihasilkan atau direview harus melewati lensa Ousterhout sebelum tugas dianggap selesai — bukan hanya review desain eksplisit — kecuali perubahan di bawah gerbang proporsionalitas (tidak ada batas baru, tidak ada pemusatan: penggantian nama, codemod, edit konfigurasi). Dua tes: (1) **Kedalaman** — antarmuka baru harus menyembunyikan jauh lebih banyak daripada yang diekspos; antarmuka yang sama kompleksnya dengan apa yang dibungkusnya tidak memberikan manfaat apa pun. (2) **Invariant** — ekstrak kode bersama hanya ketika melindungi aturan bersama, jangan karena tiga tempat mirip; dan perbaikan harus menghilangkan ketidakjelasan, bukan memindahkannya (memusatkan enam cast menjadi satu helper tetap enam cast). Ketika sebuah perubahan membuat atau membentuk ulang batas, pertama cari bagaimana produk yang sudah mapan menyelesaikan masalah dengan bentuk dan skala ini dan adopsi konvensinya kecuali ada alasan yang dinyatakan untuk tidak melakukannya (pola yang diingat dari pelatihan adalah klaim, bukan sumber), lalu jalankan pemeriksaan di bawah.
## Kapan Digunakan
- Memutuskan apakah kelas/fungsi/hook baru layak dengan antarmukanya, atau hanya penerusan dangkal.
- Sebuah file melewati ambang ukuran dan Anda memutuskan *bagaimana* membaginya, bukan hanya bahwa Anda harus membaginya.
- Kode yang berulang menggoda Anda untuk mengekstrak helper bersama.
- Merancang atau mereview batas di sekitar aturan bisnis (pemeriksaan cakupan otorisasi, aturan uang/pembulatan, penjaga transisi mesin status, aturan retensi data).
- Antarmuka akan menambah parameter atau kasus khusus.
- Membawa basis kode yang ada ke standar ini — lihat "Refactoring an Existing Codebase to This Standard" di bawah.
**Tidak untuk:** edit mekanis sepele, atau ketika konvensi proyek sudah menentukan struktur — lihat Gerbang Proporsionalitas di atas. Serahkan pada `karpathy-guidelines` untuk disiplin perubahan bedah dan skill pengembangan berbasis tes untuk jaring pengaman refaktor, ketika tersedia.
## Lensa-Lensa
Setiap lensa menambahkan tepat satu pertanyaan. Ousterhout adalah tulang punggung; yang lain memperbaiki titik butanya.
| Lensa | Pertanyaan yang ditambahkan | Kapan menggantikan |
|---|---|---|
| **Ousterhout** — modul dalam | Apakah antarmuka ini menyembunyikan lebih banyak daripada yang diungkapkan? | Tulang punggung default. |
| **Parnas** — penyembunyian informasi | Keputusan desain apa (yang kemungkinan berubah) yang disembunyikan modul ini? | *Alasan* sebuah modul harus dalam. Jika tidak menyembunyikan apa pun yang berubah, kedalaman bersifat kosmetik. |
| **Brooks** — esensial vs kebetulan | Apakah ini menghilangkan kompleksitas kebetulan, atau hanya memindahkan kompleksitas domain esensial? | Menghentikan "refaktor" yang memindahkan kekacauan tanpa menguranginya. |
| **Evans** — Domain-Driven Design | Apakah batas ini dinamai dengan bahasa domain, bukan bahasa utilitas generik? | Ganti nama `utils`/`helpers` — beri nama batas berdasarkan invarian yang sebenarnya dimiliki repo ini. |
| **Fowler** — refaktoring / bau kode | Apa langkah terkecil yang aman menuju desain yang lebih dalam? | Mengubah "seharusnya lebih dalam" menjadi langkah konkret di balik tes yang lolos. |
| **Beck** — desain sederhana, test-first | Apakah saya sudah membuktikan perilaku saat ini sebelum memperdalam sambungan? | Rem pada arsitektur prematur. Buat dulu berfungsi dan teruji, lalu perdalam sambungan yang tepat. |
| **Hickey** — sederhana vs mudah | Apakah ini menggabungkan konsep yang tidak terkait, atau benar-benar satu konsep? | Pembantu dangkal biasanya *mudah* (dekat, cepat), bukan *sederhana* (sedikit konsep yang saling terkait). Pilih sederhana. |
| **Metz** — duplikasi daripada abstraksi yang salah | Apakah kode yang diulang ini melindungi invarian bersama, atau hanya terlihat mirip (aturan program ini, memperluas Metz)? | Metz: duplikasi lebih murah daripada abstraksi yang salah — masukkan kembali abstraksi yang salah daripada memaksakannya. Program ini memperluasnya: jangan **mengpusatkan** hanya karena ada pengulangan; pusatkan hanya saat melindungi invarian nyata. Toleransi duplikasi sampai invarian terungkap. |
| **Hukum Hyrum** — perilaku yang dapat diamati | Apakah pemanggil akan bergantung pada perilaku di luar kontrak antarmuka ini? | Berargumen untuk antarmuka kecil dan stabil: setiap perilaku yang dapat diamati akhirnya menjadi penopang beban. |
## Resep Penggabungan
Terapkan dalam urutan ini — lensa berikutnya hanya penting setelah yang sebelumnya lolos:
1. **Metz — gerbang penerimaan.** Apakah batas/abstraksi ini layak ada? Aturan program ini, memperluas Metz: ekstrak hanya saat kode melindungi aturan bersama — tiga yang mirip bukan invarian yang terungkap. Jika tidak, berhenti di sini.
2. **Parnas / Ousterhout** — Sembunyikan keputusan yang mudah berubah (ruang lingkup otorisasi, aturan pembulatan, penjaga transisi, aturan retensi) di balik modul dalam.
3. **Evans** — Namai modul itu dengan bahasa domain, bukan `utils`.
4. **Beck / Fowler** — Untuk kode yang ada, kunci perilaku saat ini dengan tes, lalu refaktor ke arahnya dengan langkah kecil yang aman. Untuk kode yang baru dibuat tidak ada perilaku saat ini untuk dikunci — tulis tes yang mendefinisikan perilaku yang diinginkan.
5. **Hickey** — Tolak antarmuka yang mencampur konsep yang tidak terkait hanya karena alur kerjanya terlihat mirip.
## Anti-Polanya Struktural
**SOLID / Clean Code mekanis menghasilkan modul dangkal.** Bacaan dogmatis — satu kelas per tanggung jawab, ekstrak setiap fungsi, buat semuanya kecil — menghasilkan banyak kelas dengan antarmuka yang serumit isi kelasnya. Ketika aturan mengatakan "pisahkan ini," tanyakan keputusan *apa* yang disembunyikan pemisahan itu (Parnas) dan apakah menyembunyikan lebih banyak daripada yang diungkapkan (Ousterhout). Jika tidak menyembunyikan apa pun yang berubah, jangan pisahkan. Penjaga ini paling penting saat tekanan refaktor ("bersihkan ini", "file ini terlalu besar") — dalam analisis tenang, peninjau sudah menolaknya; saat refaktor tengah berlangsung, dengan mandat untuk menghasilkan perubahan yang terlihat, saat itulah banyak file dangkal dibuat.
## Kesalahan Umum
- **Memisahkan hanya berdasarkan ukuran.** Modul query 400 baris yang menyembunyikan satu keputusan koheren mungkin lebih dalam daripada empat modul 100 baris yang masing-masing bocor pada join yang sama.
- **Menamai pemisahan `helpers`/`utils`.** Jika Anda tidak bisa menamainya dengan bahasa domain (Evans), batasnya mungkin salah.
- **Ekstrak pada kemunculan kedua.** Aturan program ini, memperluas Metz: tunggu invarian, bukan kemunculan ketiga yang mirip.
- **Memperdalam sebelum mengunci perilaku.** Beck: tanpa tes yang membuktikan perilaku saat ini, refaktor "pendalaman" adalah penulisan ulang.
- **Menghitung penerusan sebagai modul.** Pembungkus yang meneruskan argumennya menambah antarmuka dan tidak menyembunyikan apa pun — dangkal secara definisi.
- **Salah mengira sajak sebagai invarian.** Bukti terbaik invarian bersama adalah perubahan bersama: salinan telah diperbaiki atau diubah bersama dalam sejarah (bug yang sama diperbaiki di dua tempat). Yang mirip tapi berubah sendiri-sendiri adalah sajak; biarkan tetap duplikat.
- **Merapikan bau daripada menghilangkannya.** Mengpusatkan enam cast ke satu pembantu cast generik adalah versi rapi dari ketidakjelasan yang sama. Perbaikan mendalam menamai batas yang ditutupi cast.
## Biaya Pembaca: Tes Ketiga
Kedalaman dan invarian menentukan apakah sebuah batas harus ada. Biaya pembaca menentukan apakah kode di sekitarnya mudah diubah. Pembaca berikutnya, manusia atau agen, membayar untuk setiap baris yang harus mereka muat untuk mengubah sesuatu dengan aman. Agen membayar dengan token dan menavigasi dengan pencarian teks, pembacaan parsial, dan siklus typecheck/test, jadi cacat yang sama lebih mahal bagi mereka. Tanyakan:
- **Dapat ditemukan?** Satu nama per konsep, dieja sama di mana-mana, dapat dijangkau dengan pencarian teks biasa. Cacat: nama yang dirakit dari string, pengkabelan oleh efek samping impor, rantai ekspor ulang yang menyembunyikan definisi, dua nama untuk satu konsep.
- **Apakah pembaca bisa berhenti lebih awal?** Kontrak berada di bagian atas file atau di atas ekspor: apa yang dijanjikan, apa yang disembunyikan, apa yang tidak pernah dilakukan. Cacat: kontrak hanya bisa diturunkan dengan membaca isi.
- **Dapat diperiksa mesin?** Tipe yang tepat masuk dan keluar dari setiap batas, sehingga pemeriksaan tipe menggantikan pembacaan pemanggil. Cacat: `any`, kamus polos, flag boolean yang maknanya ada di isi.
- **Apakah keterkaitan terlihat?** Tempat yang harus berubah bersama ditegakkan (tipe bersama, tes, sumber tunggal) atau, jika gagal, ditandai di kedua situs. Bukti keterkaitan tersembunyi adalah perubahan bersama dalam sejarah yang tidak disebutkan dalam kode.
- **Bebas dari kebisingan?** Tidak ada komentar yang mengulang kode, tidak ada kode yang dikomentari, tidak ada cabang mati, tidak ada komentar riwayat perubahan, tidak ada jalur usang yang disimpan di samping penggantinya.
- **Dapat diprediksi?** Tata letak mengikuti pola repo yang ada; tes ada di tempat pembaca akan mencarinya dan berjalan sendiri.
Ukuran file sengaja tidak disebutkan. File yang sangat besar adalah alasan untuk mencari keputusan tersembunyi kedua, bukan alasan untuk memotong: pembaca dapat mencari dan membaca rentang, dan pemisahan yang tidak menyembunyikan apa pun menambahkan antarmuka tanpa mengurangi beban.
Untuk penanda dalam kode dan peta kode repo, gunakan `context-audit` jika tersedia: jangkar `AIDEV-NOTE:` (satu fakta yang tidak dapat dipulihkan plus referensi asal, maksimal dua baris, di situs) adalah konvensi untuk keterkaitan yang tidak dapat ditegakkan.
## Refaktorisasi Basis Kode yang Ada ke Standar Ini
Retrofit dinilai sama seperti kode baru; yang berbeda adalah urutan dan pengendalian. Sebagian besar basis kode harus dibiarkan apa adanya.
1. **Sensus, hanya baca.** Daftar batas (modul, layanan, pembantu bersama). Untuk setiap catatan: keputusan yang disembunyikan, atau "tidak ada"; ukuran antarmuka terhadap isi; mitra perubahan bersama dari sejarah; cacat biaya pembaca. Jangan ubah apa pun dulu.
2. **Peringkat berdasarkan perubahan, bukan berdasarkan jelek.** Prioritas adalah seberapa sering kode berubah dikalikan dengan biaya membacanya. Kode dingin yang berfungsi tetap seperti adanya, walaupun dangkal. Kompleksitas domain penting tetap di tempatnya (Brooks).
3. **Tetapkan satu solusi per temuan:**
- lapisan pass-through atau pembungkus yang tidak menyembunyikan apa pun: hapus, pemanggil menggunakan apa yang dibungkus;
- abstraksi salah yang dibengkokkan oleh flag dan kasus khusus: masukkan kembali (Metz), lalu cari invarian sebenarnya;
- saudara dangkal yang berbagi satu keputusan: gabungkan di balik satu antarmuka;
- keputusan bocor (pemanggil tahu format, aturan, skema): tarik ke modul yang memilikinya;
- nama generik (`utils`, `helpers`, `manager`): ganti nama sesuai keputusan yang disembunyikan, atau larutkan ke pemanggilnya;
- batas tanpa tipe: beri tipe, dan ganti cast dengan pemetaan yang mereka tutupi;
- keterkaitan tersembunyi: tegakkan, atau tandai kedua situs;
- kebisingan: hapus.
Rima yang berubah secara independen tidak mendapat solusi.
4. **Tetapkan perilaku dulu.** Tidak ada solusi yang dimulai sampai tes membuktikan perilaku kode yang disentuh (Beck). Refaktor mempertahankan perilaku; perubahan perilaku adalah komit terpisah.
5. **Potong pekerjaan menjadi unit yang bisa diselesaikan satu agen sendiri.** Satu batas per unit. Setiap unit menamai file yang dimilikinya, kontrak yang harus dipertahankan, dan perintah yang membuktikannya sendiri. Tidak ada dua unit bersamaan yang menulis file yang sama; file bersama (barrel, registri, tabel rute) mendapat satu pemilik atau menunggu integrasi. Perubahan antarmuka yang bergantung pada beberapa unit mendarat dulu, sebagai unit sendiri.
6. **Ukur hasilnya.** Pilih perubahan representatif sebelum mulai dan hitung file dan baris yang harus dimuat pembaca untuk melakukannya; hitung lagi setelahnya. Nama yang diekspor dan total baris harus turun atau tetap. Refaktor yang menambah antarmuka harus menyatakan alasannya.
7. **Berhenti** ketika yang tersisa adalah dingin, penting, atau rima.
Keahlian terkait, jika tersedia: `repo-review` (tipe desain) menghasilkan sensus sebagai artefak hanya saran; `design-cleanup` menjalankan siklus perbaikan dan pemindaian ulang untuk kompleksitas tidak sengaja; `context-audit` menambah jangkar dan peta kode; `ousterhout-build-deep` adalah daftar periksa waktu penulis untuk agen yang mengerjakan unit.
## Posisi Keahlian Ini
Keahlian ini adalah lapisan tinjau dan penilaian: gunakan untuk memutuskan apakah sebuah abstraksi dalam, dinamai untuk keputusan yang tepat, dan layak diekstrak. `find-shared-code` menggunakannya sebagai tes masuk saat menyapu sejarah terbaru untuk kode yang layak dibagikan. Lampiran di bawah memberikan alasan masing-masing penulis.
---
## Lampiran: Lensa Secara Mendalam
Mode kegagalan yang ditangkap setiap penulis, dan satu langkah yang diberikan masing-masing. Tabel di atas adalah referensi cepat; ini adalah alasan di baliknya.
### Ousterhout — Modul Dalam (tulang punggung)
*Filsafat Desain Perangkat Lunak.*
- **Kedalaman** = manfaat (fungsi yang disembunyikan) ÷ biaya (kompleksitas antarmuka). Modul dalam menyembunyikan banyak hal di balik sedikit. Modul dangkal antarmukanya hampir sama kompleks dengan isinya, jadi tidak mendapat nilai.
- **Kompleksitas** adalah apa pun tentang sistem yang membuatnya sulit dipahami atau dimodifikasi. Dua sumber:
- **Ketergantungan** — Anda tidak bisa mengubah satu bagian tanpa menyentuh bagian lain.
- **Ketersembunyian** — informasi penting tidak jelas dari kode.
- **Gejala:** amplifikasi perubahan (satu keputusan, banyak suntingan), beban kognitif (berapa banyak yang harus diingat), ketidaktahuan yang tidak diketahui (Anda tidak tahu kode mana yang akan terpengaruh perubahan).
- **Langkah kunci:** tarik kompleksitas *ke bawah* — modul menyerap kasus sulit sehingga pemanggil tidak perlu. Parameter konfigurasi dan pass-through mendorong kompleksitas *ke atas* ke pemanggil; itu adalah kedangkalan.
Menangkap: antarmuka yang membocorkan implementasi; pembantu yang tidak membantu.
### Parnas — Penyembunyian Informasi (mengapa kedalaman penting)
*On the Criteria To Be Used in Decomposing Systems into Modules (1972).*
- Pecah menjadi sekitar **keputusan desain yang kemungkinan besar berubah**, bukan berdasarkan langkah-langkah
sebuah perhitungan. Setiap modul menyembunyikan satu keputusan seperti itu.
- Ini adalah leluhur langsung dari modul dalam. Sebuah modul menjadi dalam *karena*
menyembunyikan keputusan yang jika tidak akan menyebar ke pemanggil.
Perangkap: sebuah "modul" yang tidak menyembunyikan apa pun yang mudah berubah — kedalamannya hanya kosmetik. Tanyakan:
apa yang berubah di balik antarmuka ini yang tidak pernah dilihat pemanggil? Jika jawabannya
"tidak ada," batasannya hanya hiasan.
### Brooks — Kompleksitas Esensial vs Akidental
*Tidak Ada Peluru Perak.*
- Kompleksitas **esensial** melekat pada domain (penilaian memang sesulit ini).
Kompleksitas **akidental** adalah apa yang dipaksakan oleh alat dan struktur kita.
- Hanya kompleksitas akidental yang bisa dihilangkan. Refaktor yang "membersihkan" dengan memindahkan
kompleksitas domain esensial dari satu file ke file lain tidak melakukan apa-apa.
Perangkap: pengaturan ulang yang disamarkan sebagai penyederhanaan. Tanyakan: apakah total kompleksitas berkurang,
atau hanya berpindah?
### Evans — Domain-Driven Design
*Domain-Driven Design.*
- Batasan harus dinamai dalam **bahasa umum** domain, bukan dalam istilah utilitas generik.
Modul bernama `helpers` tidak memberi nama apa pun; modul bernama
`AccessScope` atau `PricingPolicy` memberi nama sebuah invarian.
- Bounded contexts menjaga invarian bisnis agar tidak bocor melintasi sambungan.
Perangkap: dekomposisi yang benar dengan nama yang tidak bermakna. Jika Anda tidak bisa memberi nama
modul dalam bahasa domain, kemungkinan Anda memotong batas di tempat yang salah.
### Fowler — Refactoring dan Code Smells
*Refactoring.*
- Memberikan langkah konkret, aman, dan bernama (Extract Function, Move Field, Replace
Conditional with Polymorphism) untuk beralih dari desain saat ini ke yang lebih dalam.
- Setiap langkah mempertahankan perilaku dan kecil, sehingga tetap dapat dibalik.
Perangkap: kesenjangan antara "ini harus lebih dalam" dan mengetahui commit berikutnya.
Ousterhout menetapkan target; Fowler adalah jalannya.
### Beck — Desain Sederhana, Test-First
*Test-Driven Development; XP.*
- Empat aturan desain sederhana, dalam urutan yang diterbitkan Beck: lulus tes, tidak ada
duplikasi, mengungkapkan niat, elemen paling sedikit. Program ini mengikuti
pengurutan ulang Fowler/Haines yang lebih baru — niat sebelum duplikasi — karena
melayani aturan invarian program ini yang memperluas Metz (lihat Metz, di bawah):
jangan bertindak pada duplikasi sampai Anda bisa memberi nama niat yang dilindunginya.
- Test-first adalah rem terhadap arsitektur prematur. Buat berfungsi dan buktikan
perilaku *terlebih dahulu*, lalu perdalam sambungan yang sekarang dilindungi oleh tes.
Perangkap: arsitektur dibangun sebelum perilaku dipastikan. Tanpa tes yang membuktikan
perilaku saat ini, refaktor "pendalaman" adalah penulisan ulang yang belum diverifikasi.
### Hickey — Sederhana vs Mudah
*Simple Made Easy.*
- **Sederhana** = tidak terjalin: satu konsep, tidak bercampur dengan yang lain (objektif).
- **Mudah** = dekat, familiar, cepat dijangkau (relatif terhadap Anda).
- Keduanya independen. Helper dangkal biasanya *mudah* — cepat ditulis,
dekat — tapi tidak *sederhana* jika menggabungkan kepentingan yang tidak terkait.
Perangkap: kenyamanan yang menyamar sebagai desain. Pilih konstruksi yang menjaga konsep
agar tidak terjalin meskipun yang terjalin lebih cepat diketik.
### Metz — Lebih Baik Duplikasi Daripada Abstraksi yang Salah
*"The Wrong Abstraction" (2016).*
- Duplikasi jauh lebih murah daripada abstraksi yang salah. Abstraksi yang diambil
terlalu dini memaksa setiap pemanggil di masa depan menyesuaikan asumsi yang tidak pernah
benar untuk semuanya.
- Ketika sebuah abstraksi ternyata salah, solusi Metz adalah mengembalikannya secara inline dan membiarkan
duplikasi kembali, daripada memaksakan agar cocok dengan kasus yang tidak pernah dibuat untuk itu.
- **Aturan program ini, memperluas Metz: jangan sentralisasi hanya karena kode berulang.
Sentralisasi ketika melindungi invarian nyata yang dibagi bersama.** Sampai invarian
itu terungkap, toleransi terhadap duplikasi.
Perangkap: sentralisasi berlebihan — helper bersama yang dangkal yang sekarang harus
dikerjakan oleh semua orang. Ini adalah penyeimbang terhadap "DRY dengan segala cara" yang mekanis.
### Hukum Hyrum — Perilaku Teramati Menjadi Kontrak
*"Dengan jumlah pengguna yang cukup, setiap perilaku yang dapat diamati dari sistem Anda
akan diandalkan oleh seseorang."*
- Apa pun yang *terjadi* pada sebuah antarmuka — urutan, waktu, teks kesalahan — seseorang
akhirnya akan bergantung padanya. Jadi permukaan yang Anda tampilkan lebih besar daripada permukaan
yang Anda dokumentasikan.
- Ini mendukung preferensi Ousterhout untuk **antarmuka kecil dan stabil**: semakin sedikit
yang Anda tampilkan, semakin sedikit yang bisa menjadi beban secara tidak sengaja.
Perangkap: antarmuka luas yang akan mengeras. Setiap tambahan yang dapat diamati menjadi
kendala di masa depan.
### Bagaimana Mereka Terpadu
- **Parnas → Ousterhout:** sembunyikan keputusan yang mudah berubah → modul menjadi dalam.
- **Brooks:** pastikan kedalaman menghilangkan kompleksitas bukan hanya memindahkannya.
- **Evans:** beri nama batasan dalam bahasa domain.
- **Beck → Fowler:** pastikan perilaku, lalu refaktor dengan langkah kecil yang aman.
- **Metz:** tahan sentralisasi sampai invarian nyata.
- **Hickey:** jaga antarmuka hanya untuk satu konsep.
- **Hyrum:** jaga antarmuka itu kecil agar tetap stabil.
Bahaya adalah mencampur Ousterhout dengan pembacaan mekanis SOLID atau Clean Code:
yang menghasilkan banyak kelas dan fungsi kecil dengan antarmuka dangkal — kebalikan
persis dari modul dalam. Ousterhout, dengan Metz sebagai penyeimbang, adalah penawarnya.
Tag
Bacaan lanjutan
Claude Ads: skill Claude Code yang mengaudit akun iklanmu
Claude Ads adalah skill open source untuk Claude Code: 250+ pemeriksaan di Google, Meta, LinkedIn, TikTok, atau Amazon Ads, skor dari 100, dan rencana aksi berprioritas dalam sekitar sepuluh menit. Instalasi, perintah, batasan, dan cara mengorkestrasinya di AgentsRoom.
AGENTS.md: Satu File Konteks untuk Semua Coding Agent (Codex, Antigravity, Claude)
AGENTS.md adalah file instruksi portabel yang dibaca coding agent AI kamu sebelum menyentuh kodemu. Apa saja yang perlu ditaruh di dalamnya, bedanya dengan CLAUDE.md, dan cara menjaga satu konteks tetap konsisten di Codex, Antigravity, dan Claude.
Unduh AgentsRoom
Jalankan semua agen AI Anda, di semua proyek Anda, dari satu jendela.
Aplikasi pendamping: pantau agen Anda saat bepergian
Gunakan Claude, Codex, Antigravity CLI, atau penyedia AI lainnya.
Kirim bug dan permintaan langsung ke backlog publik Anda.