3 poin oleh GN⁺ 2024-09-12 | 1 komentar | Bagikan ke WhatsApp
  • Komentar dapat memakai bahasa manusia yang lebih ekspresif daripada identifier, sehingga cocok untuk meninggalkan pilihan yang tidak ada di kode dan alternatif yang ditinggalkan
  • “comment the why, not the what” adalah pendekatan untuk menaruh sebanyak mungkin informasi ke dalam identifier, tetapi belakangan ada kecenderungan untuk memindahkan bahkan alasannya ke nama fungsi yang panjang atau nama test
  • Dalam build epub Logic for Programmers, digunakan implementasi lambat yang mengganti 16 simbol matematika secara berurutan pada tiap string, tetapi saat ini hanya ada 25 string matematika sehingga cukup cepat
  • Komentar semacam ini nantinya memberi tahu bagian yang harus diperbaiki ketika string matematika bertambah menjadi ratusan dan menjadi bottleneck build, serta mencatat bahwa kode lambat itu adalah trade-off yang disengaja
  • Nama fungsi atau test melekat pada apa yang benar-benar dilakukan kode, sehingga sulit untuk mendokumentasikan sendiri informasi negatif berupa alternatif yang tidak dipilih dan hal-hal yang tidak dilakukan

Informasi yang lebih mudah dimuat oleh komentar daripada kode

  • Kode adalah bahasa mesin yang terstruktur, sedangkan komentar ditulis dalam bahasa manusia yang ekspresif
  • “comment the why, not the what” dapat ditafsirkan sebagai anjuran untuk menaruh sebanyak mungkin informasi ke dalam identifier
  • Identifier lebih mirip bahasa manusia yang terbatas di dalam kode; memang tidak bisa memuat semua “what”, tetapi dalam banyak kasus bisa memuat cukup banyak
  • Belakangan, semakin banyak pandangan bahwa bahkan “why” pun bisa dimasukkan bukan ke komentar, melainkan ke nama fungsi yang panjang atau nama test case
  • Codebase yang self-documenting pada umumnya menambah dokumentasi lewat penambahan identifier
    • Sebagai pengecualian, ada contoh mengubah komentar menjadi logging agar kode lebih self-documenting

Apa yang ditangani komentar “Why Not”

  • Informasi yang sulit diekspresikan dengan kode adalah informasi negatif
  • Informasi negatif menarik perhatian pada apa yang tidak ada dalam sistem, dan mengapa alternatif tertentu tidak dipilih
  • “why not” bukan menjelaskan apa yang dilakukan kode, melainkan meninggalkan catatan tentang pilihan yang tidak diambil kode dan alasannya

Kasus penggantian simbol matematika di epub

  • Dalam build epub Logic for Programmers, karena alasan teknis notasi matematika seperti \forall tidak diubah menjadi simbol seperti
  • Untuk mengatasinya, dibuat skrip yang secara langsung mengganti token di dalam string matematika dengan simbol Unicode padanannya
  • Implementasi termudah adalah memanggil string = string.replace(old, new) untuk masing-masing dari 16 simbol matematika yang diperlukan
  • Cara ini tidak efisien karena tiap string dilintasi 16 kali, sementara pendekatan yang menangani semua 16 penggantian dalam satu lintasan jauh lebih kompleks
  • Inti komentar yang ditinggalkan adalah sebagai berikut
    • Tiap string dilintasi 16 kali
    • Saat ini buku tersebut hanya punya 25 string matematika, dan sebagian besar panjangnya di bawah 5 karakter
    • Jadi tetap cukup cepat
  • Komentar ini menjelaskan bukan hanya “mengapa memakai kode yang lambat”, tetapi juga “mengapa tidak memakai kode yang cepat”

Penanda untuk pembaca di masa depan

  • Kode lambat mungkin tidak menimbulkan masalah sekarang, tetapi bisa menjadi masalah nanti
  • Jika di versi masa depan Logic for Programmers jumlah string matematika bertambah menjadi ratusan, tahap build tersebut bisa menjadi bottleneck seluruh build
  • Jika penandanya ditinggalkan sekarang, nanti akan langsung jelas bagian mana yang perlu diperbaiki
  • Bahkan jika kode terus berjalan tanpa masalah, komentar itu tetap melestarikan fakta bahwa penulis mengetahui trade-off tersebut
  • Saat membuka lagi epub_math_fixer.py dua tahun kemudian, tidak perlu terlalu banyak menyelidiki ulang apakah kode lambat itu berasal dari kurang mahir, kekurangan waktu, atau kesalahan
  • Komentar negatif meninggalkan informasi bahwa implementasi lambat itu disadari, alternatifnya telah dipertimbangkan, dan diputuskan untuk tidak dioptimalkan

Mengapa sulit digantikan dengan nama fungsi dan test

  • Nama fungsi seperti RunFewerTimesSlowerAndSimplerAlgorithmAfterConsideringTradeOffs terlalu panjang dan tetap tidak cukup menjelaskan trade-off yang sebenarnya
  • Jika nanti kodenya dioptimalkan, nama itu mungkin harus diubah di banyak tempat
  • Masalah yang lebih besar adalah nama seperti itu tidak memberi tahu apa yang sebenarnya dilakukan fungsi tersebut, sehingga justru melemahkan sifat self-documenting
  • Identifier seperti nama fungsi dan nama variabel hanya bisa memuat satu klausa informasi
  • Sulit memuat sekaligus “apa yang dilakukan fungsi” dan “trade-off yang diterima fungsi” dalam satu identifier

Informasi negatif yang sulit ditinggalkan bahkan lewat test

  • Bisa saja dibuat test yang me-grep blok matematika dalam buku dan gagal jika jumlahnya melebihi 80
  • Tetapi test seperti itu tidak menguji EpubMathFixer itu sendiri secara langsung
  • Tidak ada titik di dalam fungsi tempat test tersebut bisa dipasang
  • Self-documenting menempel pada kode yang ditulis dan menjelaskan apa yang dilakukan kode tersebut
  • Karena informasi negatif membahas hal-hal yang tidak dilakukan kode, pendekatan self-documenting pada dasarnya tidak cocok dengannya

Pertanyaan yang lebih luas

  • Komentar “why not” dapat dilihat sebagai salah satu contoh kontrafaktual (counterfactual)
  • Masih tersisa pertanyaan apakah elemen abstrak dalam komunikasi manusia pada umumnya bisa dibuat self-documenting
  • Masih menjadi tanda tanya apakah informasi seperti metafora, ketidakpastian, atau klaim etis juga bisa dibuat self-documenting

1 komentar

 
GN⁺ 2024-09-12
Opini Hacker News
  • Saya ingat lelucon yang sepertinya pernah saya lihat di Twitter beberapa tahun lalu: “Engineer junior menulis komentar yang menjelaskan apa yang dilakukan kode, engineer menengah menulis komentar yang menjelaskan mengapa kode melakukannya seperti itu, dan engineer senior menulis komentar yang menjelaskan mengapa kode tidak ditulis dengan cara lain,” kurang lebih begitu

    • Itu benar sekali. Saya pernah harus menambahkan komentar 5 kali lebih panjang daripada kodenya sendiri, untuk mencegah orang yang tidak tahu kode, domain, atau hal-hal yang perlu diwaspadai saat menangani cakupan dinamis besar melakukan refactoring dengan niat baik
      Sebaliknya, kalau makna bisa dibuat jelas hanya dengan nama fungsi dan variabel, saya juga pernah menulis fungsi yang cukup besar tanpa komentar
    • Saya melakukan ketiganya. Komentar ringkasan sangat berguna dan juga sudah divalidasi lewat studi empiris, tetapi banyak orang terlalu tenggelam dalam pola pikir ala Clean Code sampai tampak sulit diselamatkan
    • Programmer junior biasanya tidak mendokumentasikan apa pun atau mendokumentasikan semuanya. Seiring pengalaman bertambah, mereka belajar bahwa cukup mendokumentasikan hal-hal yang tidak biasa; dan dengan pengalaman lebih banyak lagi, hal yang tidak biasa makin sedikit, sehingga komentar juga berkurang
      Jadi sisi dengan komentar lebih sedikit memang menang, tetapi ketika melihat codebase tanpa komentar, kita harus memeriksanya sendiri untuk membedakan apakah itu mahakarya yang dipoles indah atau kode rapuh buatan pemula
    • Ada juga komentar yang menjelaskan mengapa perilaku yang jelas terlihat bodoh harus terus direproduksi. Karena sesuatu yang lain bergantung pada perilaku bodoh itu
    • Kalau engineer level C, mereka akan meninggalkan komentar seperti “X jam terbuang untuk me-refactor kode ini. Jika Anda memutuskan mengikuti jejak para pendahulu, naikkan counter ini”
      Meski terlihat seperti tambalan total, kadang-kadang memang itulah yang terbaik yang benar-benar bisa didapat
  • Kalau menurut saya akan berguna saat melihat kode itu lagi setahun kemudian, semuanya saya tinggalkan sebagai komentar. Biasanya tentang mengapa dan mengapa tidak bisa, dan saat kodenya rumit saya juga menulis “apa” secara singkat agar alurnya lebih mudah terlihat
    Yang tidak berguna adalah komentar wajib. API publik memang harus didokumentasikan dengan memadai, tetapi ada organisasi yang memaksa semua fungsi, bahkan fungsi private, diberi komentar, sampai tujuannya terlalu jelas dan hanya mengulang nama fungsi. Ini bukan hanya membuang waktu, tetapi juga membuat orang kebal terhadap komentar dan mengajarkan kebiasaan mengabaikannya
    Saya juga tidak suka komentar mubazir yang ditambahkan tool. Misalnya menempelkan //for atau //try pada setiap loop, itu sangat tidak saya suka

    • Anehnya, banyak skema warna syntax highlighting membuat komentar tampak pudar dan menurunkan kontras. Mungkin karena komentar wajib atau komentar yang dihasilkan biasanya rendah kandungan informasinya
      Lebih baik menghapus komentar wajib dan komentar hasil generasi, lalu pada tema gelap mengubah komentar menjadi warna neon terang agar menonjol. Jika ada komentar, itu seharusnya berarti penting
    • Dulu posisi saya adalah “semua komentar adalah code smell,” dan sekarang pun masih cukup banyak begitu, tetapi setelah bekerja pada codebase yang sangat besar yang aktif dikembangkan dan dipelihara oleh ratusan orang, pandangan saya sedikit melunak
      Untuk memelihara sistem besar yang sudah tua dalam lingkungan bisnis dengan jadwal ketat, kadang kita harus melakukan hal-hal aneh, dan saat itu kita perlu menjelaskan alasannya
      Alasan besar menentang komentar adalah karena komentar juga menjadi bagian dari kode dan perlu dipelihara. Namun kebanyakan orang hanya membaca komentar ketika mereka buntu, dan editor juga membuat komentar abu-abu pudar sehingga secara psikologis tidak terlihat. Karena itu komentar mudah kedaluwarsa
      Saya penasaran apakah konteks untuk “diri saya di masa depan” juga berguna dalam codebase bersama yang disentuh banyak developer, atau apakah itu hanya bekerja baik ketika hanya sedikit orang yang menyentuh kode
    • Sepenuhnya setuju. Jika komentar terlalu banyak, jadi sulit melihat apa yang ada di dalam class atau fungsi. Kalau class atau fungsi yang semestinya muat dalam satu layar menjadi melewati satu layar karena komentar, ada biaya keterbacaan
    • Kemarin di proyek pribadi, saya melihat baris dengan komentar “apakah ini benar-benar berguna?”, dan tampaknya mudah dihapus. Saya mencoba memakai class baru yang bersih, tetapi ternyata cara lama tertentu memang benar-benar diperlukan
      Jadi saya menambahkan “=> yes!” pada komentar yang ada, dan berterima kasih kepada diri saya di masa lalu karena telah mendokumentasikan pertanyaan itu. Di pekerjaan, terutama saat memperbaiki bug, saya sering meninggalkan satu-dua baris komentar di atas perubahan yang tidak jelas, bersama nomor tiket
  • Format komentar favorit yang pernah saya tinggalkan di kode adalah template ini: “DEAR MAINTAINER: Kode ini dibuat seperti ini karena [alasan]. Jika Anda mencoba ‘memperbaikinya’ lalu menyadari bahwa itu kesalahan mengerikan, tolong naikkan counter total_hours_wasted_here = n sebagai peringatan untuk orang berikutnya”
    Saya bukan pembuat aslinya, tetapi pernah menggunakannya dengan rasa syukur satu-dua kali, dan lucu melihat commit satu baris yang hanya menaikkan counter

    • Andai saja ini ada beberapa tahun lalu. Saya pernah membuat kode pembangkit SQL yang harus menggunakan rekursi cukup bebas untuk memenuhi requirement, dan walau ada banyak rekursi mutual sehingga kodenya berantakan, itu adalah kejahatan yang diperlukan
      Engineer yang lebih senior mengambil alih codebase dan “memperbaiki” semuanya menjadi gaya loop, lalu mencoba menguliahi saya lewat email tentang mengapa rekursi itu buruk, tetapi kodenya tidak benar-benar memenuhi semua requirement dan akhirnya pada dasarnya membuat ulang hal-hal yang dulu saya lakukan dengan rekursi
      Belakangan dia memang meminta maaf atas sebagian ucapannya, tetapi kalau saya menaruh komentar seperti ini di bagian paling atas, mungkin seluruh kejadian itu bisa dihindari
  • Saya setuju judulnya ambigu, dan justru itu membuat saya membaca tulisannya. Secara pribadi saya cenderung lebih suka memakai sedikit komentar secara keseluruhan, tetapi komentar penjelas yang disebut dalam tulisan itu jelas bernilai. Ini pengingat bagus untuk menjelaskan mengapa dibuat begitu, dan mengapa bukan cara lain
    Ini terutama berlaku pada kode sendiri yang masih harus dipelihara 5, 10, 15 tahun kemudian. Baru-baru ini saat meninjau kode baru dari rekan kerja, saya berpikir “kenapa dibuat begini?”, lalu 10 baris di atasnya ada alasan yang persis sama yang saya tulis 8 tahun lalu. Rekan itu mengikuti aturan inti pemeliharaan, yaitu membuatnya terlihat seperti kode yang sudah ada

    • Saat memelihara codebase lama, membuatnya terlihat seperti kode yang sudah ada sangat diremehkan. Demi kesehatan mental orang-orang yang datang setelahnya, tolong buatlah terlihat seperti kode yang sudah ada
  • Ini hanyalah kasus khusus dari prinsip yang lebih luas: beri komentar pada hal-hal yang mengejutkan saat membaca kode
    Saat menulis kode, orang yang terus bertanya dalam kepala “apakah nanti saya bisa memahami kode ini?” dan setiap kali secara naluriah menjawab “ya” itu sombong dan sering keliru. Jika jawabannya “belum tentu”, pertanyaan berikutnya secara alami adalah “mengapa?”, dan jawabannya adalah hal yang harus ditulis dalam komentar
    Kadang jawabannya adalah “karena pembaca mungkin bertanya-tanya mengapa tidak ditulis dengan cara lain”, dan itulah kasus khusus yang dibahas tulisan ini. Namun kadang jawabannya adalah “karena tidak jelas bagaimana ini bekerja atau mengapa ini benar”, dan saat itu diperlukan jenis komentar lain

    • Jika awalnya Anda mencoba menulis kode dengan satu cara tetapi tidak berhasil sehingga perlu pendekatan kedua, itu adalah sinyal kuat bahwa di tempat itu perlu komentar. Jika Anda terkejut saat menulisnya, besar kemungkinan setahun kemudian Anda sudah melupakan keterkejutan itu dan akan terkejut lagi saat membaca kodenya
    • Dengan prinsip serupa, jadikan “jika ini tidak bekerja seperti yang diharapkan, ke mana saya harus melihat?” sebagai patokan. Jika jawabannya tidak ada di dokumentasi, atau berjarak lebih dari 10 baris dari jalur wiki → package/modul → file → class → fungsi/metode, tambahkan komentar inline atau perbarui dokumentasinya
      Hal seperti ini biasanya terjadi saat memotong string atau menelusuri struktur data yang tidak biasa sebagai tahap perantara
  • Identifier saja bisa membawa kita sangat jauh, tetapi tidak bisa sampai tuntas. Secara pribadi, saya cenderung suka mewajibkan komentar dokumentasi seperti jsdoc/xmldoc untuk method publik, variabel, field, dan parameter
    Memberi nama method dengan baik memang penting, tetapi mencoba menuliskan secara singkat apa yang dilakukannya membuatnya lebih jelas, dan terutama menyingkap cacat yang jelas. Sering kali begitu menulis kalimat pertama, nama yang lebih baik langsung terpikir; dan jika penjelasannya mulai memuat kata “dan”, itu sinyal bahwa method tersebut melakukan terlalu banyak hal dan bisa dipecah secara lebih logis
    Properti mudah dianggap terlalu jelas sehingga tidak perlu dokumentasi, tetapi sesuatu seperti /** The API key */ string ApiKey; terlalu banyak kekurangannya. Kita tidak tahu kunci ini berasal dari mana, apakah hanya untuk internal atau dipertukarkan dengan sistem eksternal, apakah wajib, apakah boleh null atau kosong, apakah ada panjang maksimum, apa yang terjadi jika nilainya tidak valid, atau apakah ada kode atau dokumen lain yang perlu dibaca
    Bagi penulis asli, informasi ini bisa ditulis dalam 1–2 menit, tetapi bagi orang baru, saat harus mengubah atau menggunakannya, atau saat ditugaskan memperbaiki bug bertahun-tahun kemudian, bisa perlu berjam-jam untuk mengetahuinya

  • Dalam code review, jika saya bisa menebak apa yang akan dikatakan reviewer yang terlalu cerewet, saya sering menulis komentar seperti “tidak melakukan X karena Y”. Tujuannya mengurangi bolak-balik diskusi yang merepotkan

    • Dari pengalaman, jumlah bolak-balik diskusinya tetap sama, tetapi setidaknya kita bisa beberapa kali menulis “seperti yang tertulis di komentar”
    • Hal seperti itu saya tambahkan secara proaktif di PR, tetapi saya tidak yakin apakah nilainya cukup besar untuk dibiarkan di dalam kode
  • Komentar seperti “kita mengiterasi setiap string 16 kali, tetapi sejauh ini hanya ada 25 string formula di buku dan kebanyakan kurang dari 5 karakter, jadi ini cukup cepat” juga punya variasi lain
    Yaitu memasang log debug yang aktif ketika input menjadi jauh lebih besar daripada batasan desain awal. Pesannya hampir sama untuk developer masa depan, tetapi bisa ditemukan lebih cepat sehingga waktu diagnosis dan debugging berkurang lebih banyak

    • Dalam banyak kasus, ini ide yang bagus. Kadang kita menulis loop yang saat ini bekerja tetapi sangat lambat; kita bisa memasang timer dan “menulis log peringatan jika memakan waktu lebih dari X detik”
      Dalam sistem logging dan observability yang ideal, semua komponen aplikasi akan diukur waktunya dan sering meninggalkan informasi debug, tetapi siapa yang benar-benar memakai sistem sesempurna itu? Upaya memasang log secara spesifik di bagian yang kelak bisa memburuk performanya atau yang belum sempat dioptimalkan lebih penting
      Kalau dipikir-pikir, ini ide yang obvious, tetapi selama ini pendekatannya adalah meninggalkan komentar di tempat yang perlu dilihat lagi nanti, lalu berharap kita mengingat komentar itu ketika keadaan memburuk
    • Alat yang bermaksud baik seperti bazel sering memperlakukan output yang bukan error sebagai noise yang harus disembunyikan. Pesan seperti ini kerap langsung dibuang ke tempat sampah terdekat, sehingga di sebagian area log menjadi sarana yang sangat tidak andal untuk menyampaikan batasan
  • Apa pun kata orang, saya banyak menulis komentar dan doc comment di berbagai bagian kode. Namun pendekatannya dibalik: pertama-tama saya menulis daftar tahapan aplikasi secara kasar sebagai komentar, lalu selama pengembangan saya memecah langkah besar menjadi langkah kecil, kadang menghapus komentar awal, kadang membiarkannya, dan terus merincinya sampai hampir menjadi algoritme yang selesai
    Biasanya saya mengode dari luar ke dalam, jadi sambil memecah komentar saya juga menulis kodenya. Kadang saya mengode sekaligus dulu, lalu belakangan menambahkan komentar sampai tingkat yang mungkin dianggap merepotkan oleh kebanyakan orang. Saya memberi penjelasan pada semua fungsi dan variabel, bahkan fungsi deg_to_rad pun saya beri """Converts degrees to radians.""". Toh ruang penyimpanan murah
    Saya tahu kebanyakan orang tidak menyukainya, tapi tidak masalah. Kalau tidak suka melihatnya, hapus saja dengan skrip atau saat code review. Meski begitu, membaca kode lama saya sendiri jauh lebih menyenangkan daripada kode orang lain tanpa komentar. Di Python, kode boilerplate sederhana seperti Flask API umumnya cukup self-documenting, tetapi justru boilerplate semacam itu sering banyak berubah sehingga bisa memiliki komentar penting. Di industri, bagian algoritme lebih sering ditulis ulang seluruhnya
    Saya akan tetap menyukai komentar dan doc comment ke depannya

    • Saya melakukan hal yang mirip, tetapi terutama hanya pada komponen tingkat teratas. Karena di bagian seperti itulah komentar paling berguna
      Saya suka membuat konseptualisasi menyeluruh di kepala, dan pada tahap awal saya merasa lambat kalau harus bereksperimen dengan benar-benar mencoba berbagai pilihan desain. Jadi begitu pilihan desain ditetapkan, itu harus didokumentasikan. Karena orang lain belum bisa mengakses isi kepala saya
      Untuk detailnya, saya berharap akan menjadi lebih jelas setelah orang lain juga selesai mengonsepkannya. Namun kalau karena suatu alasan konseptualisasi itu tidak terjadi, kodenya bisa menjadi lebih sulit dibaca, jadi saya memolesnya lagi agar setidaknya keterbacaan dasarnya tetap terjaga
    • Komentar itu bagus jika dipelihara dengan baik. Namun kecuali pada kasus seperti open source, di mana ada sangat banyak orang yang mengelola komentar dibanding pembacanya, pada akhirnya semua orang akan lupa atau malas memeliharanya
      Memperbarui komentar sering kali menjadi pekerjaan tersendiri, sama seperti memperbaiki kode. Jadi secara realistis, komentar biasanya adalah sesuatu yang menunggu untuk menjadi kebohongan. Pada akhirnya komentar dan kode menjadi tidak selaras, dan itu bisa lebih buruk daripada kode tanpa komentar
      Lebih baik tes otomatis yang menunjukkan intent. Tes pada umumnya tidak bisa berbohong, karena kalau tidak demikian tentu tidak akan di-merge. Jika ada sekumpulan tes yang cukup baik yang menunjukkan bagaimana kode dimaksudkan untuk digunakan, saya ingin melihatnya, karena itu bersifat menjelaskan sekaligus hampir dijamin benar
    • Saya masih setuju sampai bagian “kalau tidak suka, hapus saja dengan skrip di versi sendiri atau hapus saat code review”, tetapi mulai dari situ, sebagai rekan tim ini terlihat seperti sinyal bahaya besar
    • Saya juga mirip. Sekitar setengahnya, saya mulai dengan menulis komentar yang menjelaskan apa yang ingin saya lakukan, lalu setelahnya menambahkan hal-hal yang tidak berjalan sesuai perkiraan dan apa yang harus dilakukan agar benar-benar berfungsi
      Itu sangat membantu ketika harus melihatnya lagi 5 minggu kemudian
    • Saya tidak menganggap doc comment diperlukan dalam semua kasus, dan saya juga tidak berpikir semua parameter dan nilai kembalian dari setiap fungsi harus didokumentasikan. Namun untuk API yang kompleks, itu jelas berguna
  • Saya mengikuti konsep “komentar adalah permintaan maaf kepada diri sendiri di masa depan”
    Kalau kodenya aneh atau lambat, atau ada bagian yang ketika dijelaskan kepada seseorang membuat saya berkata “ini memang agak berantakan”, biasanya saya meninggalkan komentar. Terutama jika saya pernah mencoba mengubahnya sebelumnya, saya mendokumentasikan kasus yang tidak berhasil, apa yang diperbaiki, dan sebagainya
    Dengan pendekatan kriteria seperti ini, komentar yang tidak perlu akan hilang dengan sendirinya, dan biasanya kita hanya mendokumentasikan mengapa ketika memang benar-benar diperlukan. Cobalah sekitar sebulan di codebase sendiri, nanti akan terasa