
Kode digunakan untuk membuat antarmuka. Tetapi kode itu sendiri adalah sebuah antarmuka.
Terlepas dari kenyataan bahwa keterbacaan kode sangat penting, konsep ini tidak didefinisikan dengan baik - dan seringkali dalam bentuk hanya seperangkat aturan: menggunakan nama variabel yang bermakna, memecah fungsi besar menjadi yang lebih kecil, dan menggunakan pola desain standar.
Pada saat yang sama, pasti, semua orang harus berurusan dengan kode yang sesuai dengan aturan-aturan ini, tetapi untuk beberapa alasan adalah semacam kekacauan.
Anda dapat mencoba menyelesaikan masalah ini dengan menambahkan aturan baru: jika nama variabel menjadi sangat panjang, Anda perlu memperbaiki logika utama; jika banyak metode bantu terakumulasi dalam satu kelas, mungkin itu harus dibagi menjadi dua; Pola desain tidak dapat diterapkan dalam konteks yang salah.
Instruksi semacam itu berubah menjadi labirin keputusan subyektif, dan untuk menavigasinya, Anda akan membutuhkan pengembang yang dapat membuat pilihan yang tepat - yaitu, ia harus sudah dapat menulis kode yang dapat dibaca.
Dengan demikian, seperangkat instruksi bukan pilihan. Oleh karena itu, kita harus merumuskan gambaran yang lebih luas tentang keterbacaan kode.
Mengapa keterbacaan dibutuhkan
Dalam praktiknya, keterbacaan yang baik biasanya berarti bahwa kode itu enak dibaca. Namun, seseorang tidak dapat melangkah jauh dengan definisi seperti itu: pertama, itu subjektif, dan kedua, itu mengikat kita untuk membaca teks biasa.
Kode yang tidak terbaca dianggap sebagai novel yang berpura-pura menjadi kode: banyak komentar yang mengungkapkan esensi dari apa yang terjadi, lembaran teks yang perlu dibaca secara berurutan, formulasi cerdas, satu-satunya makna yang harus "pintar", takut menggunakan kembali kata-kata. Pengembang mencoba membuat kode dapat dibaca, tetapi menargetkan jenis pembaca yang salah.
Keterbacaan teks dan pembacaan kode bukan hal yang sama.
Diterjemahkan ke AlconostKode digunakan untuk membuat antarmuka. Tetapi kode itu sendiri adalah sebuah antarmuka.
Jika kodenya terlihat indah, apakah ini berarti dapat dibaca? Estetika adalah efek samping yang menyenangkan dari keterbacaan, tetapi sebagai kriteria tidak terlalu berguna. Mungkin dalam kasus ekstrim, estetika kode dalam proyek akan membantu mempertahankan karyawan - tetapi dengan kesuksesan yang sama, Anda dapat menawarkan paket sosial yang baik. Selain itu, setiap orang memiliki ide mereka sendiri tentang apa artinya "kode indah". Dan seiring berjalannya waktu, definisi keterbacaan ini berubah menjadi pusaran sengketa tentang tabulasi, spasi, tanda kurung, "notasi unta", dll. Tidak mungkin ada orang yang akan kehilangan kesadaran ketika mereka melihat lekukan yang salah, meskipun hal ini menarik perhatian ketika memeriksa kode.
Jika kode menghasilkan lebih sedikit kesalahan, dapatkah itu dianggap lebih mudah dibaca? Semakin sedikit kesalahan, semakin baik, tetapi mekanisme apa yang ada? Bagaimana saya bisa menghubungkan sensasi menyenangkan samar yang Anda alami ketika membaca kode? Selain itu, tidak peduli seberapa alisnya berkerut saat membaca kode, ini tidak akan menambah kesalahan.
Jika kodenya mudah diedit, apakah bisa dibaca? Tapi ini, mungkin, adalah arah pemikiran yang benar. Persyaratan berubah, fungsi ditambahkan, kesalahan muncul - dan pada titik tertentu seseorang harus mengedit kode Anda. Dan agar tidak menimbulkan masalah baru, pengembang perlu memahami apa yang sebenarnya dia edit dan bagaimana perubahan akan mengubah perilaku kode. Jadi, kami menemukan aturan heuristik baru: kode yang mudah dibaca harus mudah diedit.
Kode mana yang lebih mudah diedit?
Saya segera ingin menjelaskan: "Kode lebih mudah diedit ketika nama variabel diberikan secara bermakna," tetapi kami hanya mengganti nama "keterbacaan" menjadi "kemudahan mengedit." Kita membutuhkan pemahaman yang lebih dalam, dan bukan seperangkat aturan yang sama dalam kedok yang berbeda.
Mari kita mulai dengan melupakan sejenak bahwa kita berbicara tentang kode. Pemrograman, yang sudah berumur beberapa dekade, hanyalah titik pada skala sejarah manusia. Membatasi diri kita pada "titik" ini, kita tidak bisa menggali lebih dalam.
Oleh karena itu, mari kita lihat keterbacaan melalui prisma merancang antarmuka yang kita temui di hampir setiap langkah - dan tidak hanya dengan yang digital. Mainan itu memiliki fungsi yang membuatnya naik atau mencicit. Pintu memiliki antarmuka yang memungkinkan Anda untuk membuka, menutup, dan menguncinya. Data dalam buku dikumpulkan dalam halaman, yang menyediakan akses acak lebih cepat daripada menggulir. Mempelajari desain, Anda bisa belajar lebih banyak tentang antarmuka ini - tanyakan pada tim desain apakah Anda bisa. Dalam kasus umum, kita semua lebih suka antarmuka yang baik, bahkan jika kita tidak selalu tahu apa yang membuatnya baik.
Kode digunakan untuk membuat antarmuka. Tetapi kode itu sendiri, dikombinasikan dengan IDE, adalah sebuah antarmuka. Antarmuka yang dirancang untuk sekelompok kecil pengguna - kolega kami. Selanjutnya kami akan memanggil mereka "pengguna" - agar tetap dalam ruang merancang antarmuka pengguna.
Dengan mengingat hal ini, pertimbangkan contoh jalur pengguna ini:
- Pengguna ingin menambahkan fungsi baru. Ini membutuhkan menemukan tempat yang tepat dan menambahkan fungsi tanpa menghasilkan kesalahan baru.
- Pengguna ingin memperbaiki kesalahan. Dia perlu menemukan sumber masalah dan mengedit kode sehingga kesalahan hilang dan kesalahan baru tidak muncul.
- Pengguna ingin memastikan bahwa dalam kasus batas, kode berperilaku dengan cara tertentu. Dia perlu menemukan bagian kode tertentu, kemudian melacak logikanya dan mensimulasikan apa yang terjadi.
Dan seterusnya: sebagian besar jalur mengikuti pola yang sama. Agar tidak menyulitkan hal-hal, pertimbangkan contoh-contoh spesifik - tetapi jangan lupa bahwa ini adalah pencarian prinsip-prinsip umum, bukan daftar aturan.
Kami yakin dapat berasumsi bahwa pengguna tidak akan dapat langsung membuka bagian kode yang diinginkan. Ini juga berlaku untuk proyek hobi Anda sendiri: bahkan jika fungsi itu ditulis oleh Anda, sangat mudah untuk melupakan di mana ia berada. Karena itu, kodenya harus sedemikian rupa sehingga mudah untuk menemukan yang tepat di dalamnya.
Untuk menerapkan pencarian yang mudah, Anda perlu beberapa optimasi mesin pencari - ini dia bagi kami bahwa nama variabel yang bermakna datang untuk menyelamatkan. Jika pengguna tidak dapat menemukan fungsi, bergerak di sepanjang tumpukan panggilan dari titik yang diketahui, ia dapat memulai pencarian dengan kata kunci. Namun, Anda tidak dapat memasukkan terlalu banyak kata kunci dalam nama. Saat mencari berdasarkan kode, satu-satunya titik masuk dicari, dari mana Anda dapat terus bekerja lebih lanjut. Karena itu, pengguna perlu membantu sampai ke tempat tertentu, dan jika Anda berlebihan dengan kata kunci, akan ada terlalu banyak hasil pencarian yang tidak berguna.
Jika pengguna dapat segera memverifikasi bahwa semuanya benar pada tingkat logika tertentu, ia dapat melupakan lapisan abstraksi sebelumnya dan membebaskan pikirannya untuk selanjutnya.
Anda dapat mencari menggunakan pelengkapan otomatis: jika Anda memiliki gagasan umum tentang fungsi yang ingin Anda panggil atau penghitungan yang digunakan, Anda dapat mulai mengetik nama yang dimaksud, dan kemudian memilih opsi yang sesuai dari daftar pelengkapan otomatis. Jika fungsi ini hanya ditujukan untuk kasus-kasus tertentu atau jika Anda perlu membaca dengan cermat implementasinya karena fitur penggunaannya, Anda dapat menunjukkan ini dengan memberinya nama yang lebih otentik: dengan menggulir daftar pelengkapan otomatis, pengguna lebih suka menghindari apa yang terlihat rumit - kecuali, tentu saja, dia yakin apa yang terjadi.
Oleh karena itu, nama biasa pendek lebih cenderung dianggap sebagai opsi default, cocok untuk pengguna "biasa". Seharusnya tidak ada kejutan dalam fungsi dengan nama-nama tersebut: Anda tidak dapat memasukkan setter ke dalam fungsi yang terlihat seperti getter sederhana, karena alasan yang sama bahwa tombol Lihat di antarmuka tidak boleh mengubah data pengguna.

Di antarmuka yang menghadap klien, fungsi-fungsi yang akrab, seperti jeda, melakukan hampir tanpa teks. Ketika fungsi menjadi lebih kompleks, nama-nama memanjang, yang membuat pengguna melambat dan berpikir. Tangkapan layar - PandoraPengguna ingin menemukan informasi yang tepat dengan cepat. Dalam kebanyakan kasus, kompilasi membutuhkan banyak waktu, dan dalam aplikasi yang sedang berjalan Anda harus memeriksa secara manual berbagai kasus perbatasan. Jika memungkinkan, pengguna kami akan lebih suka membaca kode dan memahami bagaimana perilakunya, daripada mengatur breakpoints dan menjalankan kode.
Untuk melakukannya tanpa menjalankan kode, dua syarat harus dipenuhi:
- Pengguna mengerti apa yang coba dilakukan oleh kode.
- Pengguna yakin bahwa kode melakukan apa yang diklaimnya.
Abstraksi membantu memenuhi kondisi pertama: pengguna harus dapat menyelami lapisan abstraksi ke tingkat detail yang diinginkan. Bayangkan sebuah antarmuka pengguna hierarkis: pada tingkat pertama, navigasi dilakukan melalui bagian-bagian yang luas, dan kemudian semakin dikonkritkan - ke tingkat logika yang perlu dipelajari secara lebih rinci.
Pembacaan berurutan file atau metode dilakukan dalam waktu linier. Tetapi jika pengguna dapat bergerak naik dan turun tumpukan panggilan - ini adalah pencarian di pohon, dan jika hirarki seimbang, tindakan ini dilakukan dalam waktu logaritmik. Tentu saja ada ruang untuk daftar di antarmuka, tetapi Anda harus hati-hati mempertimbangkan apakah harus ada lebih dari dua atau tiga pemanggilan metode dalam beberapa konteks.

Dalam menu pendek, navigasi hierarkis jauh lebih cepat. Dalam menu "panjang" di sebelah kanan - hanya 11 baris. Seberapa sering kita memasukkan angka ini ke dalam kode metode? Tangkapan layar - PandoraPengguna yang berbeda memiliki strategi yang berbeda untuk kondisi kedua. Dalam situasi berisiko rendah, komentar atau nama metode adalah bukti yang cukup. Di area yang lebih berisiko dan kompleks, serta ketika kode dibebani dengan komentar yang tidak relevan, yang terakhir cenderung diabaikan. Terkadang bahkan nama metode dan variabel akan diragukan. Dalam kasus seperti itu, pengguna harus membaca lebih banyak kode dan ingat model logika yang lebih luas. Membatasi konteks untuk area kecil yang mudah dipegang juga akan membantu di sini. Jika pengguna dapat segera memverifikasi bahwa semuanya benar pada tingkat logika tertentu, ia dapat melupakan lapisan abstraksi sebelumnya dan membebaskan pikirannya untuk selanjutnya.
Dalam mode operasi ini, token individu mulai memiliki kepentingan yang lebih besar. Misalnya, bendera boolean
element.visible = true/false
mudah dimengerti secara terpisah dari sisa kode, tetapi ini membutuhkan menggabungkan dua token yang berbeda dalam pikiran. Jika digunakan
element.visibility = .visible/.hidden
maka nilai flag dapat langsung dipahami: dalam hal ini, Anda tidak perlu membaca nama variabel untuk mengetahui bahwa itu terkait dengan visibilitas. ยน Kami melihat pendekatan serupa dalam merancang antarmuka berorientasi klien. Selama beberapa dekade terakhir, tombol OK dan Cancel telah berubah menjadi elemen antarmuka yang lebih deskriptif: "Simpan" dan "Batalkan", "Kirim" dan "Lanjutkan mengedit", dll., Untuk memahami apa yang akan dilakukan, cukup bagi pengguna untuk melihat opsi yang diusulkan tanpa membaca keseluruhan konteks.
Baris "Mode Offline" pada contoh di atas menunjukkan bahwa aplikasi sedang offline. Switch dalam contoh di bawah ini memiliki arti yang sama, tetapi untuk memahaminya, Anda perlu melihat konteksnya. Tangkapan layar - PandoraTes unit juga membantu untuk mengkonfirmasi perilaku kode yang diharapkan: mereka bertindak sebagai komentar - yang, bagaimanapun, dapat dipercaya lebih luas, karena mereka lebih relevan. Benar, mereka juga harus menyelesaikan perakitan. Tetapi dalam kasus pipa CI yang sudah mapan, tes dijalankan secara teratur, sehingga Anda dapat melewati langkah ini ketika membuat perubahan pada kode yang ada.
Secara teori, keamanan mengikuti dari pemahaman yang memadai: begitu pengguna kami memahami perilaku kode, ia akan dapat membuat perubahan dengan aman. Dalam praktiknya, Anda harus mempertimbangkan bahwa pengembang adalah orang biasa: otak kita menggunakan trik yang sama dan juga malas. Karena itu, semakin sedikit upaya yang Anda perlu habiskan untuk memahami kode, semakin aman tindakan kami.
Kode yang dapat dibaca harus melewati sebagian besar pemeriksaan kesalahan ke komputer. Salah satu cara untuk melakukan ini adalah dengan menggunakan pemeriksaan debug "menegaskan", namun, mereka juga memerlukan perakitan dan startup. Lebih buruk lagi, jika pengguna lupa tentang kasus batas, menegaskan tidak akan membantu. Tes unit untuk memeriksa kasus perbatasan yang sering dilupakan bisa lebih baik, tetapi begitu pengguna melakukan perubahan, Anda harus menunggu tes berjalan.
Singkatnya: kode yang mudah dibaca harus mudah digunakan. Dan - sebagai efek samping - itu bisa terlihat indah.
Untuk mempercepat siklus pengembangan, kami menggunakan fungsi pengecekan kesalahan yang ada di kompiler. Biasanya untuk kasus seperti itu, perakitan lengkap tidak diperlukan, dan kesalahan ditampilkan secara real time. Bagaimana cara memanfaatkan peluang ini? Secara umum, Anda perlu menemukan situasi di mana pemeriksaan kompiler menjadi sangat ketat. Sebagai contoh, kebanyakan kompiler tidak melihat seberapa komprehensif pernyataan "jika" dijelaskan, tetapi hati-hati memeriksa "saklar" untuk kondisi yang hilang. Jika pengguna mencoba untuk menambah atau mengubah suatu kondisi, akan lebih aman jika semua operator serupa sebelumnya bersifat komprehensif. Dan ketika kondisi "case" berubah, kompiler akan menandai semua kondisi lain yang perlu diperiksa.
Masalah keterbacaan umum lainnya adalah penggunaan primitif dalam ekspresi bersyarat. Masalah ini sangat akut ketika aplikasi mem-parsing JSON, karena Anda hanya ingin menambahkan pernyataan "jika" di sekitar string atau integer equality. Ini tidak hanya meningkatkan kemungkinan kesalahan ketik, tetapi juga mempersulit tugas bagi pengguna untuk menentukan nilai yang mungkin. Ketika memeriksa kasus batas, ada perbedaan besar antara kapan garis mungkin, dan ketika - hanya dua atau tiga opsi terpisah. Bahkan jika primitif ditetapkan dalam konstanta, Anda harus bergegas sekali, mencoba menyelesaikan proyek tepat waktu, dan nilai sewenang-wenang akan muncul. Tetapi jika Anda menggunakan objek atau enumerasi yang dibuat khusus, kompiler memblokir argumen yang tidak valid dan memberikan daftar spesifik yang valid.
Demikian pula, jika beberapa kombinasi bendera Boolean tidak diizinkan, ganti dengan satu enumerasi. Ambil, misalnya, komposisi yang bisa dalam keadaan berikut: itu buffer, terisi penuh, dan dimainkan. Jika Anda membayangkan status pemuatan dan pemutaran sebagai dua bendera Boolean
(loaded, playing)
kompiler akan memungkinkan input nilai yang tidak valid
(loaded: false, playing: true)
Dan jika Anda menggunakan enumerasi
(.buffering/.loaded/.playing)
maka tidak mungkin untuk menunjukkan keadaan yang tidak valid. Di antarmuka berorientasi klien, defaultnya adalah untuk melarang kombinasi pengaturan yang tidak valid. Tetapi ketika kita menulis kode di dalam aplikasi, kita sering lupa untuk memberi diri kita perlindungan yang sama.

Kombinasi yang tidak valid dimatikan sebelumnya; pengguna tidak perlu memikirkan konfigurasi mana yang tidak kompatibel. Tangkapan layar - AppleMengikuti jalur pengguna yang dianggap, kami sampai pada aturan yang sama seperti di awal. Tetapi sekarang kita memiliki prinsip yang dengannya mereka dapat dirumuskan secara independen dan diubah sesuai dengan situasi. Untuk melakukan ini, kami bertanya pada diri sendiri:
- Apakah mudah bagi pengguna untuk mencari bagian kode yang diinginkan? Apakah hasil pencarian akan berantakan dengan fungsi yang tidak terkait dengan permintaan?
- Bisakah seorang pengguna, setelah menemukan kode yang diperlukan, dengan cepat memeriksa kebenaran perilakunya?
- Apakah lingkungan pengembangan menyediakan pengeditan yang aman dan penggunaan kembali kode?
Singkatnya: kode yang mudah dibaca harus mudah digunakan. Dan - sebagai efek samping - itu bisa terlihat indah.
Catatan
- Tampaknya variabel Boolean lebih nyaman untuk digunakan kembali, tetapi opsi penggunaan kembali ini menyiratkan interchangeability. Ambil, misalnya, flag yang dapat disentuh dan di- cache , yang mewakili konsep yang terletak di pesawat yang sama sekali berbeda: kemampuan untuk mengklik elemen dan status cache. Tetapi jika kedua flag adalah Boolean, Anda dapat secara tidak sengaja menukar mereka, mendapatkan ekspresi non-sepele dalam satu baris kode, yang berarti bahwa cache dikaitkan dengan kemampuan untuk mengklik pada suatu elemen. Saat menggunakan penghitungan, untuk membentuk hubungan seperti itu, kami akan dipaksa untuk membuat logika yang eksplisit dan dapat diverifikasi untuk konversi "satuan pengukuran" yang digunakan oleh kami.
Tentang penerjemahArtikel ini diterjemahkan oleh Alconost.
Alconost
melokalkan game ,
aplikasi ,
dan situs dalam 70 bahasa. Penerjemah asli bahasa, pengujian linguistik, platform cloud dengan API, pelokalan berkelanjutan, manajer proyek 24/7, semua format sumber daya string.
Kami juga membuat
video iklan dan pelatihan - untuk situs yang menjual, gambar, iklan, pelatihan, permainan asah, penjelajah, trailer untuk Google Play dan App Store.
โ
Baca lebih lanjut