11 poin oleh GN⁺ 10 jam lalu | 2 komentar | Bagikan ke WhatsApp
  • Pada sistem berskala besar dengan puluhan juta baris kode, tidak ada seorang pun yang bisa memuat keseluruhannya di kepala, sehingga engineer harus mampu bekerja efektif hanya dengan pemahaman yang sebagian tetapi akurat
  • Programming as Theory Building karya Peter Naur memandang bahwa ketika pemahaman tim lama hilang, lebih baik program dibuang dan dibuat ulang, tetapi sistem besar yang melibatkan pengguna dan banyak sekali pengecualian sulit dibangun ulang dari nol
  • Bahkan codebase yang semua penanggung jawabnya sudah pergi pun bisa dipulihkan dengan memahami satu alur dari awal sampai akhir lalu secara hati-hati memperluas cakupan perubahan, dan dalam organisasi besar pembangunan ulang pemahaman seperti ini terjadi berulang kali
  • LLM dapat menghambat pembentukan model mental yang rinci sekaligus membantu membangun dan memanfaatkan pemahaman parsial dengan cepat, dan kolaborasi, persyaratan hukum, pembaruan keamanan, serta adopsi dependensi juga menuntut kompromi antara pemahaman kode dan nilai lain
  • Model mental yang akurat membantu pengembangan yang menyenangkan dan stabil, tetapi bukan standar mutlak; dalam praktiknya, demi kecepatan, kepatuhan hukum, dan kebutuhan organisasi, kadang perlu melepaskan pemahaman yang lengkap

Pemahaman penuh dan pemahaman parsial

  • Pada codebase yang kecil dan jarang mengalami pergantian anggota, mudah untuk menganggap bahwa pekerjaan yang baik hanya mungkin jika seluruh sistem dipahami
  • Pada codebase seperti backend pencarian web Google atau GitHub, yang besar dan sering mengalami pergantian anggota, keseluruhan sistem tidak mungkin dipahami, sehingga orang bekerja dengan cara memahami area lokal yang masing-masing tangani sedalam mungkin
  • Kedua lingkungan ini sangat berbeda dalam cara pengembangan, praktik, dan budaya, tetapi dalam diskusi software engineering online, budaya pertama yang menekankan pemahaman penuh terlalu terwakili
    • Engineer open source punya motivasi kuat untuk membagikan pekerjaannya lewat tulisan, dan pekerjaan engineering yang murni lebih mudah menonjol dibanding sistem proprietari berskala besar
    • Sistem proprietari sulit dipublikasikan karena alasan hukum, dan bahkan jika bisa, menjelaskan codebase besar memerlukan terlalu banyak konteks spesifik
  • Di banyak lingkungan perangkat lunak, pemahaman parsial bukan kondisi yang salah, dan pada sistem besar itulah hasil terbaik yang secara realistis bisa dicapai
  • Perbedaan ini mengarah pada benturan antara budaya pemahaman penuh dan budaya pemahaman parsial seperti yang dibedakan dalam Pure and impure software engineering

Argumen Programming as Theory Building

  • Makalah Peter Naur Programming as Theory Building memandang hasil utama yang dibuat programmer bukanlah kode, melainkan teori tentang program
    • Teori ini tersusun dari pemahaman intuitif tentang apa yang terjadi dan mengapa hal itu terjadi
    • Kode dan dokumentasi hanya dapat memuat sebagian dari pemahaman tersebut
    • Bahkan jika kodenya hilang, tim yang memiliki teorinya bisa menulis ulang program, tetapi jika tim diganti total dan pemahamannya hilang, code lama menjadi sulit dipahami
  • Menurut Naur, teori yang sudah ada tidak bisa dibangun ulang hanya dari dokumentasi atau kode, sehingga program asli sebaiknya dibuang dan tim baru harus memecahkan masalahnya lagi dari awal
  • The Concept of Mind karya Gilbert Ryle yang dikutip Naur memandang cakupan pembangunan teori secara lebih luas
    • Saat benar-benar melakukan sesuatu, teori atau know-how bisa terbentuk secara alami
    • Karena itu, proses memahami codebase yang ada dengan menelusuri kode itu sendiri juga selaras dengan pendekatan ini

Mengapa sistem besar tidak bisa ditulis ulang dari nol

  • Sistem yang cukup besar dan sudah memiliki pengguna mengakumulasi ribuan kasus pengecualian dan perilaku aneh yang sulit diimplementasikan ulang
  • Bahkan tim yang sangat memahami sistem pun sulit menulis ulang seluruhnya sekaligus karena tidak bisa mempertimbangkan semua detail pada saat yang sama
  • Penulisan ulang yang berhasil dilakukan dengan membagi codebase lama menjadi bagian-bagian kecil yang terisolasi lalu mengganti satu bagian demi satu
    • Pada akhirnya, rewrite juga merupakan pekerjaan melakukan serangkaian perubahan pada sistem yang sudah ada
    • Jika sistem lama tidak bisa diubah, maka menggantinya sepenuhnya dengan sistem baru akan lebih sulit lagi

Cara memulihkan codebase yang ditinggalkan

  • Di perusahaan teknologi yang memiliki ratusan juta baris kode dan ribuan engineer, tidak jarang terjadi situasi ketika tidak ada lagi orang yang benar-benar memahami codebase tertentu
    • Cukup beberapa penanggung jawab keluar pada waktu yang buruk, atau codebase tidak dirawat selama setahun, untuk sampai pada kondisi ini
  • Naur beranggapan bahwa hampir tidak akan ada orang yang menyerahkan pemulihan program yang benar-benar mati kepada programmer baru tanpa ada satu pun orang yang masih sedikit memahami teori lamanya, tetapi di organisasi besar hal ini benar-benar terjadi
  • Bahkan codebase yang ditinggalkan pun dapat dikembalikan ke kondisi di mana pemahaman baru bisa dibangun dan pekerjaan efektif bisa dilakukan jika diberi waktu
    • Pertama, pahami satu alur pemrosesan dari awal sampai akhir
    • Lalu perluas cakupan pemahaman ke area sekitarnya sambil melakukan perubahan dengan hati-hati

Semua orang bekerja dengan teori yang tidak sempurna

  • Perangkat lunak modern berskala besar begitu besar sehingga bukan hanya individu, bahkan seluruh tim pun tidak bisa menyimpan semua perilakunya di dalam kepala
  • Pada codebase yang cukup besar, semua orang akhirnya bekerja sambil membawa teori yang agak tidak akurat tentang program
  • Engineer yang efektif tidak menunggu sampai seseorang dengan pemahaman sempurna memberi jawaban, melainkan membuat penilaian paling beralasan berdasarkan informasi yang ada saat ini lalu merespons hasilnya
  • Pekerjaan seperti ini menuntut kemampuan mengambil posisi dan kepercayaan diri bahkan dalam situasi yang tidak pasti
  • Kenyataan bahwa tidak ada seorang pun yang sepenuhnya memahami perilaku keseluruhan produk besar sama dengan situasi yang dibahas dalam Nobody knows how software products work

Skala kode pada era Naur dan masa kini

  • Ketika Naur menulis makalah itu pada 1985, ukuran rata-rata program kemungkinan beberapa orde besaran lebih kecil daripada saat ini
  • Contoh program besar pertama yang diberikan Naur adalah program pemantauan industri sekitar 200 ribu baris, dan contoh kedua adalah compiler
  • Versi pertama GCC pada 1987 memiliki sekitar 100 ribu baris, tetapi pada 2015 jumlahnya bertambah menjadi lebih dari 14 juta baris
  • Jika pengujian yang ada dapat digunakan ulang, program berukuran 100 ribu hingga 200 ribu baris relatif mudah ditulis ulang, tetapi sulit menerapkan penilaian yang sama pada sistem berukuran 1 juta hingga 2 juta baris atau lebih

Sisi ganda LLM dan pembangunan teori

  • LLM sering dinilai sebagai alat yang buruk karena mengganggu proses umum pembangunan teori
  • Namun seperti alat perangkat lunak lainnya, LLM juga punya dua sisi
    • Membangun model mental yang rinci tentang perangkat lunak bisa menjadi lebih sulit
    • Teori parsial dapat dibangun dengan cepat
    • LLM dapat membantu orang bekerja lebih efektif bahkan dengan pemahaman yang tidak lengkap
  • Hubungan antara LLM dan pemahaman kode tidak bisa diringkas sebagai daftar pro dan kontra sederhana; ini tetap merupakan trade-off kompleks yang memerlukan penilaian

Pilihan-pilihan yang perlu diambil meski membuat pemahaman kode lebih sulit

  • Selain LLM, ada banyak hal lain yang membuat teori yang akurat tentang codebase lebih sulit dipertahankan
    • Mengizinkan orang lain menulis kode pada codebase yang sama
    • Mengimplementasikan fitur yang diwajibkan secara hukum seperti aksesibilitas atau perlindungan data
    • Mengizinkan rekan kerja keluar atau pindah tim
    • Meng-upgrade versi perangkat lunak untuk patch keamanan
    • Mengadopsi library atau dependensi lain
  • Alat atau praktik tidak bisa langsung dinilai buruk hanya karena mengganggu pembangunan teori
  • Pemahaman terhadap codebase, seperti keterbacaan, kemudahan pemeliharaan, dan ketepatan, hanyalah salah satu dari banyak nilai dalam engineering
    • Tergantung situasinya, pemahaman yang akurat bisa diprioritaskan dengan mengorbankan nilai lain
    • Sebaliknya, pemahaman kode juga kadang dikorbankan demi kecepatan, kepatuhan hukum, atau alasan politik organisasi
  • Sanggahan bahwa pemahaman kode adalah inti untuk mewujudkan semua nilai lain juga berlaku sama pada keterbacaan, kemudahan pemeliharaan, dan ketepatan; dalam praktik kerja, bahkan nilai-nilai inti ini pun terus-menerus dikompromikan

Preferensi pribadi dan tanggung jawab pekerjaan

  • Khususnya engineer murni cenderung lebih suka bekerja sambil mempertahankan model mental yang akurat
    • Pengembangan terasa lebih menyenangkan dan lebih sedikit stres
    • Rasanya lebih dekat dengan engineering yang mereka anggap sejati
  • Alasan banyak engineer membuat proyek open source kecil sendirian di waktu luang juga karena mereka bisa bekerja sambil mempertahankan teori ala Naur yang akurat tentang codebase
  • Dalam pekerjaan, orang harus mengikuti kumpulan nilai yang diminta organisasi dan dibiayai olehnya, bukan semata nilai engineering pribadi
    • Meski mengutamakan performa, seseorang tetap bisa menulis kode yang lebih lambat demi memenuhi jadwal atau mengakomodasi persyaratan yang rumit
    • Pemahaman penuh atas codebase juga bukan standar mutlak yang selalu harus dijaga, melainkan pilihan yang bisa ditukar dengan nilai lain sesuai tujuan pekerjaan

2 komentar

 
ndrgrd 51 menit lalu

Karena itulah orang begitu terpaku pada abstraksi.

 
GN⁺ 10 jam lalu
Opini di Lobste.rs
  • Judul artikel aslinya sayangnya terasa agak clickbait, dan isi sebenarnya lebih dekat pada gagasan bahwa kita harus bisa tetap membuat kemajuan meski hanya memahami sebagian dari codebase berskala besar.
    Dari sudut pandang pembangunan teori pun, jika teori dianggap memiliki lebar dan kedalaman, itu tidak bertentangan dengan inti tulisan. Lebar berarti sejauh mana kita cukup memahami cakupan sistem untuk menjawab pertanyaan dan melakukan perubahan dengan mahir, sedangkan kedalaman berarti seberapa rumit pertanyaan yang bisa dijawab tentang bagian tertentu dan seberapa kompleks perubahan yang bisa dilakukan sambil tetap menjaga integritasnya.
    Jika kita menulis ulang kode per modul sambil menyediakan masa transisi, berarti kita sedang membangun teori yang sempit tetapi dalam tentang modul tersebut, lalu bekerja berdasarkan teori itu. Pada fungsi kecil, menambahkan satu parameter atau nilai balik mungkin tidak masalah, tetapi ketika skalanya membesar, lebih masuk akal untuk memulai ulang dari kondisi bersih setidaknya pada modul tertentu, lalu menghubungkan bagian lain agar memanggil implementasi baru. Pada dasarnya, pendekatan yang mencoba meningkatkan kebenaran implementasi yang secara fundamental penuh bug secara bertahap tidak berjalan baik, dan ini juga sering berlaku untuk sifat seperti performa.
    Namun ketika Naur mengatakan bahwa “alih-alih menghidupkan kembali program, teks program yang ada sebaiknya dibuang dan tim programmer baru diminta menyelesaikan masalah yang diberikan dari awal,” masih bisa diperdebatkan apakah maksudnya kode lama harus dihapus dulu sebelum penulisan ulang dimulai, atau boleh dibuang setelah program baru terbukti menjadi pengganti yang memadai.
    Terlebih lagi, dalam kenyataan masalah yang diberikan itu sendiri tidak benar-benar diberikan. Naur berasumsi definisi masalah asli masih tersisa, tetapi pada codebase besar sering kali tidak demikian. Yang paling mendekati biasanya adalah test suite, sehingga komponen bisa diganti sambil terus memastikan tes tetap lolos.
    Pada masa itu continuous deployment juga belum ada. Saat ini, karena layanan harus tetap berjalan, kita harus tetap on-call, menjawab pertanyaan, dan memperbaiki bug mendesak, kalkulasi untung-rugi soal penulisan ulang pun ikut berubah.

  • Sanggahan ini memiliki beberapa bagian yang diungkapkan dengan baik, tetapi sebagian besar terasa jelas dengan sendirinya. Dalam sistem yang cukup besar, pemahaman parsial adalah satu-satunya kondisi yang ada, tetapi organisasi harus selalu mengejar pemahaman yang lebih dalam.
    Terlepas dari logika “kita dibayar untuk menyelesaikan pekerjaan,” software berskala besar sering gagal memuaskan pengguna atau mencapai tujuan bisnis. Windows dan OS X pun bisa dianggap membusuk akibat kompleksitas yang menumpuk.
    Manajemen juga pasti akan menghilangkan kompleksitas secara ajaib jika bisa. Hanya saja ini adalah masalah software engineering yang belum terselesaikan; lebih tepatnya, manajemen menerima kompromi seperti itu dalam kondisi saat ini, bukan karena mereka ingin merilis kode buruk.
    Bisa saja orang berpendapat, “kalau sudah monopoli, cukup saja merilis software buruk dan penuh bug,” tetapi itu terlalu nihilistis. Ada banyak perusahaan software yang bukan monopoli atau tidak bisa menahan pengguna agar tetap tinggal, sehingga di tempat-tempat seperti itu kualitas benar-benar penting.

    • Berdasarkan pengalaman saya, manajemen tidak percaya pada praktik pengembangan software yang baik, dan sering meminta agar praktik itu ditinggalkan lebih dulu demi bergerak lebih cepat. Kebanyakan keputusan seperti itu dibuat hanya berdasarkan asumsi, tanpa validasi.
    • Tujuan “harus selalu memahami lebih banyak” bisa disalahgunakan sampai membuat orang tidak bisa melakukan apa pun. Jika yang diminta bukan pemahaman yang memadai melainkan pemahaman sempurna, orang tidak bisa berbuat apa-apa dan akhirnya menyerah atau putus asa.
      Dalam tafsir seperti ini, konsep pemahaman juga tampak seperti semacam mekanisme penjaga gerbang.
  • Pendekatan yang dijelaskan dalam tulisan tersebut sangat berkaitan dengan kemampuan bernalar secara lokal atas sebagian kode.
    Penalaran lokal, yaitu memahami satu bagian dari codebase besar tanpa memahami seluruh sekelilingnya, adalah konsep inti yang sejak awal dikejar oleh ilmu komputer.
    Keunggulan utama structured programming adalah memungkinkan penalaran lokal, dan anjuran untuk menghindari variabel global juga umumnya berangkat dari tujuan yang sama. Functional programming memungkinkan penalaran lokal dengan menghilangkan efek samping, sementara salah satu prinsip object-oriented programming, yakni menggabungkan struktur data dengan kode yang menanganinya, juga menyediakan sarana lain untuk bernalar secara lokal.
    Kekuatan sejati dari konsep dasar ini adalah memungkinkan kita bernalar dan bekerja pada bagian kecil tanpa memahami seluruh codebase, meskipun itu bukan situasi yang ideal.

  • Saya membacanya sebagai sanggahan menarik terhadap nasihat “kita harus memahami setiap baris dalam codebase,” dan karena argumen utamanya bersinggungan dengan praktik kerja pengembangan, saya menambahkan tag #practices.
    Saya tahu komunitas ini tidak menyukai LLM, tetapi saya ragu apakah tulisan ini benar-benar termasuk #vibecoding.

    • Mungkin Anda sudah tahu, tetapi di lobste.rs semua konten yang terkait penggunaan LLM secara luas diklasifikasikan sebagai vibecoding; saya juga tidak setuju, tetapi itulah praktiknya. Pertanyaan inti tulisan ini juga sangat berkaitan dengan coding berbantuan LLM.
      Namun saya setuju bahwa vibecoding tidak semestinya menjadi satu-satunya tag. Tulisan ini baru membahas LLM secara eksplisit menjelang akhir, sementara poin utamanya sudah menarik dan layak dibahas bahkan pada era sebelum LLM. Karena itu saya menilai ada cukup alasan untuk mengembalikan tag practices, saya sudah melakukannya sendiri, dan saya menyarankan orang lain melakukan hal yang sama.
    • Inti tulisan ini relevan bagi semua programmer, terutama bagi mereka yang ingin memahami cara menangani codebase raksasa dan bagaimana hal itu berbeda dari proyek kecil.
      Tulisan ini tetap relevan bahkan di dunia tempat penggunaan LLM bisa menghambat pemahaman penuh atas codebase.
      Jika tag tersebut berarti “ini mungkin relevan bagi orang yang tertarik pada vibe coding,” maka jelas cocok. Sebaliknya, jika artinya “ini tidak relevan kecuali bagi orang yang tertarik pada vibe coding,” maka tidak cocok. Semua tag lain dipakai dalam makna yang pertama, tetapi cukup banyak pengguna Lobsters memakai tag ini saja dalam makna yang kedua, sehingga pada akhirnya mereka pasti akan melewatkan tulisan ini.
  • Ciri lain pengembangan modern yang berbeda dari tahun 1985 adalah bahwa meskipun Anda menjadi pakar atas codebase 300 ribu baris, minggu berikutnya Anda bisa saja bekerja di codebase 300 ribu baris lain yang sama sekali berbeda.
    Programmer profesional berpengalaman sudah terbiasa bahwa kapan saja mereka bisa diterjunkan ke wilayah yang belum dikenal, dan mereka mengandalkan kombinasi idiom umum (Google C++ Style Guide), alat otomatis seperti compiler yang memunculkan error jika API digunakan keliru, serta intuisi tentang “bagaimana program berskala besar seharusnya disusun.”
    Saya juga pernah melihat diskusi seperti “sekarang tidak ada lagi orang yang memahami perilaku seluruh codebase, seperti Bun yang ditulis ulang dengan LLM, lalu bagaimana kita bisa terus mengembangkannya?” tetapi itu mirip dengan bertanya bagaimana mungkin seseorang memahami novel jika ia bukan penulisnya. Pada akhirnya itu kode, jadi bisa dibaca. Jika suatu fungsi tidak dipahami, kita bisa membaginya menjadi beberapa bagian, mencoba menulis tes, menggambar alur kontrol di kertas, atau melakukan apa pun yang membantu.
    Karena kita akan berpindah proyek secara berkala, tidak ada alasan untuk terus mempertahankan pemahaman atas codebase lama. Pada suatu titik semuanya tercampur dan terasa mirip. Bahkan jika Anda harus membantu kode Scala milik startup yang diakuisisi perusahaan agar dapat berkomunikasi melalui protokol RPC berbasis Thrift kustom dengan layanan Ruby berbasis JSON yang sedang ditulis ulang ke Go, satu jam mencari Scala syntax reference dan Thrift wire encoding sudah cukup untuk mulai bergerak.
    Tidak perlu menjadi pakar juga. Sebulan kemudian, Anda mungkin sedang men-debug mengapa type checker berbasis OCaml untuk JavaScript crash di implementasi Go dari kernel Linux. Pada akhirnya semuanya hanya kode.