
Hari baik untuk semua Beberapa waktu lalu saya berbicara kepada siswa tentang topik “Apa yang kita harapkan dari kode yang baik” dan memutuskan untuk menduplikasinya di sini. Dalam proses penerjemahan, teksnya agak berubah, tetapi esensinya tetap sama. Artikel itu ternyata sederhana (dan tentu saja tidak lengkap), tetapi ada butir rasional di sini.
Kode harus berfungsi

Mari kita bicara tentang apa yang kita harapkan dari kode. Yah, sebagai permulaan, itu harus bekerja.
Kedengarannya jelas, tentu saja, tetapi masing-masing dari kita pernah mencoba atau berhasil meluncurkan kode yang bahkan tidak akan, jadi jangan tertawa. Poin kedua - kode harus bekerja dengan benar dengan situasi yang salah. Itu untuk menangkap kesalahan. Tapi mari kita kembali ke poin pertama dan membicarakannya sedikit.
Secara berkala, saya mendapatkan tugas yang saya tidak tahu caranya. Artinya, secara umum (saya mencoba melihat-lihat dan terus-menerus mencoba sesuatu yang baru). Dan di sini saya langsung tertarik untuk menulis beberapa abstraksi, semacam infrastruktur, untuk menunda momen pekerjaan nyata. Jadi ini salah. Kode harus bekerja. Saya tahu bahwa saya mengulangi sendiri, tetapi ini adalah poin penting. Jika Anda tidak tahu cara menyelesaikan masalah, jangan buru-buru membuat antarmuka, modul, dan itu saja. Ini adalah ide yang buruk, yang akan berakhir di akhir waktu Anda, dan Anda tidak akan pergi ke mana pun. Ingat, kode yang berfungsi buruk berkali-kali lebih baik daripada baik, tetapi bukan kode yang berfungsi.
Ada perumpamaan lama tentang dua perusahaan perangkat lunak yang membuat produk yang sama. Yang pertama melakukan apa pun, tetapi yang pertama masuk pasar, dan yang kedua melakukan semuanya dengan sempurna dan sudah terlambat. Akibatnya, kampanye pertama berhasil menaklukkan pasar dan membeli perusahaan kedua. Ini sedikit tentang yang lain, tetapi gagasan utamanya masih sama. Pertama kita memecahkan masalah, lalu kita membuat kodenya indah.
Secara umum, pertama-tama buat prototipe yang berfungsi. Biarkan itu lumpuh, bengkok dan tidak bahagia, tetapi ketika ditanya, Anda dapat mengatakan bahwa solusinya sudah ada, ia tetap mengintegrasikannya. Dan menulis ulang sebagaimana mestinya. Anda dapat mencoba untuk mengekspresikan ini dengan pepatah seperti itu - jika Anda tahu bagaimana melakukan tugas - lakukan dengan baik. Jika Anda tidak tahu, pertama-tama atasi saja.
Dan ada poin penting. Saya ingin Anda mengerti. Ini bukan panggilan untuk menulis kode yang buruk. Kode harus bagus. Ini adalah panggilan ke First Thing First - pertama kodenya berfungsi, kemudian ia menjadi refactor.
Sekarang mari kita bicara tentang Sial Terjadi. Jadi, kita punya kodenya, bahkan berfungsi. Sebaliknya, itu "bekerja." Mari kita lihat contoh sederhana:
public string Do(int x) { using (WebClient xx = new WebClient()) { return xx.DownloadString("https://some.super.url"); } }
Ini adalah contoh yang bagus untuk kode "berfungsi". Mengapa Karena itu tidak memperhitungkan bahwa cepat atau lambat, titik akhir kami akan jatuh. Contoh ini tidak memperhitungkan yang disebut tepi kasus - batas, "kasus buruk". Ketika Anda mulai menulis kode, pikirkan apa yang salah. Sebenarnya, saya tidak hanya berbicara tentang panggilan jarak jauh, tetapi tentang semua sumber daya yang berada di luar kendali Anda - input pengguna, file, koneksi jaringan, bahkan database. Semua yang dapat dipatahkan akan pecah pada saat yang paling tidak tepat dan satu-satunya hal yang dapat Anda lakukan dengannya adalah bersiaplah untuk itu sebanyak mungkin.
Sayangnya, tidak semua masalah begitu jelas. Ada sejumlah bidang masalah yang hampir pasti menghasilkan bug. Misalnya, bekerja dengan lokal, dengan zona waktu. Menyedihkan dan berteriak "semuanya berfungsi di mesin saya." Mereka hanya perlu tahu dan bekerja dengan mereka dengan cermat.
Omong-omong tentang input pengguna. Ada prinsip yang sangat baik, yang mengatakan bahwa input pengguna apa pun dianggap salah hingga dibuktikan sebaliknya. Dengan kata lain, selalu validasikan apa yang dimasukkan pengguna. Dan ya, di server juga.
Total:
- Pertama buat kode berfungsi,
- Lalu buat dia baik-baik saja
- Jangan lupa tentang kasus tepi dan penanganan kesalahan.
Sekarang mari kita bicara tentang dukungan kode
Dukungan adalah konsep yang kompleks, tetapi saya akan memasukkan tiga komponen di sini - kode harus mudah dibaca, mudah diubah, dan konsisten.
Siapa yang menulis komentar dalam bahasa Rusia? Tidak ada yang menulis? Bagus Secara umum, salah satu masalahnya adalah kode non-Inggris. Jangan lakukan itu. Saya memiliki sepotong kode dengan kelas-kelas di Norwegia, dan saya tidak bisa mengucapkan nama mereka. Menyedihkan. Jelas, mendukung kode semacam itu (untuk non-Norwegia) tidak akan menjadi tugas yang sepele. Tapi ini jarang terjadi.
Secara umum, kemudahan membaca adalah tentang penamaan dan struktur. Nama-nama entitas - kelas, metode, variabel, harus sederhana, mudah dibaca dan membawa makna. Ambil contoh kami sebelumnya.
public string Do(int x) { using (WebClient xx = new WebClient()) { return xx.DownloadString("https://some.super.url"); } }
Bisakah Anda memahami apa yang dilakukan metode Do meskipun penerapannya? Hampir tidak. Begitu pula dengan nama variabel. Untuk memahami objek xx apa yang Anda butuhkan untuk mencari deklarasi. Ini membutuhkan waktu kita, mencegah kita dari memahami apa, secara umum, yang terjadi dalam kode. Oleh karena itu, nama harus mencerminkan esensi dari tindakan atau makna. Misalnya, jika Anda mengganti nama metode Do ke GetUserName, kode menjadi sedikit lebih jelas dan dalam beberapa kasus kami tidak lagi harus melihat implementasinya. Demikian pula dengan nama variabel dalam bentuk x dan xx. Benar, ada pengecualian yang diterima secara umum dalam bentuk e untuk kesalahan, i, k untuk penghitung siklus, n untuk dimensi, dan beberapa lainnya.
Sekali lagi, sebagai contoh, ambil kode Anda yang Anda tulis sebulan yang lalu dan cobalah untuk membacanya dengan lancar. Apakah Anda mengerti apa yang sedang terjadi di sana? Jika demikian, saya ucapkan selamat kepada Anda. Jika tidak, maka Anda memiliki masalah dengan keterbacaan kode.
Secara umum, ada kutipan yang menarik:
"Hanya ada dua hal yang sulit dalam Ilmu Komputer: pembatalan cache dan penamaan hal-hal." © Phil Karlton
Hanya ada dua hal kompleks dalam Ilmu Komputer: pembatalan dan penamaan cache.
Ingat dia ketika Anda memberi nama pada entitas Anda.
Komponen kedua dari kode yang dapat dibaca adalah kompleksitas atau strukturnya. Saya berbicara tentang mereka yang suka menulis enam ifas bersarang, atau menulis panggilan balik ke panggilan balik di dalam panggilan balik. JavaScript bahkan memiliki istilah yang disebut Callback Hell .

Kasihanilah kolega Anda dan diri Anda sendiri. Setelah satu minggu, Anda harus benar-benar mengarungi kode ini untuk memperbaiki atau menambahkan sesuatu di dalamnya. Menghindari ini tidak begitu sulit:
- Tulis fungsi singkat,
- Hindari banyak bercabang atau bersarang,
- Pisahkan blok kode logis menjadi fungsi-fungsi terpisah bahkan jika Anda tidak akan menggunakannya kembali,
- Gunakan polimorfisme alih-alih jika
Sekarang mari kita bicara tentang satu hal yang lebih rumit - kode yang baik itu mudah diubah. Siapa yang tahu istilah Big ball of mud? Jika seseorang tidak terbiasa - lihat gambar.

Setiap modul tergantung pada masing-masing modul dan perubahan kontrak di satu tempat cenderung menyebabkan munculnya rubah kutub atau, setidaknya, untuk debug yang sangat lama. Secara teoritis, berurusan dengan ini cukup sederhana - kurangi ketergantungan kode Anda pada kode Anda sendiri. Semakin sedikit kode Anda yang tahu tentang detail implementasi, semakin baik untuk itu. Namun dalam praktiknya, ini jauh lebih rumit, dan mengarah pada komplikasi ulang kode.
Dalam bentuk tips, saya akan begini:
- Sembunyikan kode Anda sedalam mungkin. Bayangkan besok Anda harus menghapusnya secara manual dari proyek. Berapa banyak tempat yang harus Anda perbaiki dan seberapa sulitnya? Cobalah untuk meminimalkan jumlah ini.
- Hindari ketergantungan melingkar. Pisahkan kode menjadi beberapa lapisan (logika, antarmuka, akses data) dan pastikan bahwa lapisan pada level "bawah" tidak bergantung pada lapisan pada level "atas". Misalnya, akses ke data tidak harus bergantung pada antarmuka pengguna.
- Kelompokkan fungsi ke dalam modul (proyek, folder) dan sembunyikan kelas di dalamnya, hanya menyisakan fasad dan antarmuka.
Dan menggambar. Cukup gambarkan di selembar kertas bagaimana data Anda diproses oleh aplikasi dan kelas apa yang digunakan untuk ini. Ini akan membantu Anda memahami tempat-tempat yang terlalu rumit sebelum semuanya menjadi tidak dapat diperbaiki.
Dan akhirnya tentang keseragaman. Selalu berusaha untuk mematuhi gaya seragam yang diadopsi oleh tim, bahkan jika itu tampak salah bagi Anda. Ini berlaku untuk pemformatan, dan pendekatan untuk memecahkan masalah. Jangan gunakan ~~ untuk pembulatan, bahkan jika itu lebih cepat. Tim tidak akan menghargainya. Dan ketika mulai menulis kode baru, selalu perhatikan proyeknya, mungkin sesuatu yang Anda butuhkan telah diimplementasikan dan Anda dapat menggunakannya kembali.
Total:
- Penamaan yang tepat
- Struktur yang baik
- Keseragaman.
Kode harus cukup produktif
Mari kita sedikit kedinginan. Persyaratan selanjutnya yang akan kita pertimbangkan adalah bahwa kodenya harus cukup produktif.
Apa yang saya maksud dengan kata "cukup"? Mungkin setiap orang telah mendengar bahwa optimasi prematur itu jahat, mereka membunuh keterbacaan dan menyulitkan kode. Ini benar Tetapi juga benar bahwa Anda harus tahu alat Anda dan tidak menulis di atasnya sehingga klien web mail memuat Core I7 sebesar 60%. Anda harus mengetahui masalah khas yang menyebabkan masalah kinerja dan menghindarinya bahkan pada tahap penulisan kode.
Mari kita kembali ke contoh kita:
public string GetUserName(int userId) { using (WebClient http = new WebClient()) { return http.DownloadString("https://some.super.url"); } }
Kode ini memiliki satu masalah - unduhan sinkron melalui jaringan. Ini adalah operasi I / O yang membekukan aliran kami sampai dijalankan. Dalam aplikasi desktop, ini akan menyebabkan antarmuka yang menggantung, dan dalam aplikasi server, untuk reservasi memori yang tidak berguna dan kelelahan jumlah permintaan ke server. Hanya dengan mengetahui masalah seperti itu, Anda sudah dapat menulis kode yang lebih optimal. Dan dalam kebanyakan kasus ini sudah cukup.
Tapi terkadang, tidak. Karena itu, sebelum menulis kode, Anda harus tahu terlebih dahulu persyaratan apa yang ditetapkan untuknya dalam hal kinerja.
Sekarang mari kita bicara tentang tes.
Ini tidak kurang topik holivny dari yang sebelumnya, dan mungkin bahkan lebih. Semuanya rumit dengan tes. Mari kita mulai dengan pernyataan - Saya percaya bahwa kode harus dicakup oleh sejumlah tes yang masuk akal.
Mengapa kita membutuhkan Kode Cakupan dan tes? Di dunia yang ideal, mereka tidak dibutuhkan. Di dunia yang ideal, kode ditulis tanpa bug, dan persyaratan tidak pernah berubah. Tapi kita hidup di dunia yang jauh dari ideal, jadi kita perlu tes untuk memastikan bahwa kodenya berfungsi dengan benar (tidak ada bug) dan kodenya bekerja dengan benar setelah mengubah sesuatu. Inilah manfaat yang diberikan tes kepada kami. Di sisi lain, bahkan 100% (karena spesifikasi penghitungan metrik) yang dicakup oleh tes tidak menjamin bahwa Anda benar-benar mencakup semuanya. Selain itu, setiap tes tambahan memperlambat pengembangan karena setelah mengubah fungsional Anda juga harus memperbarui tes. Oleh karena itu, jumlah tes harus masuk akal dan kesulitan utama terdiri dalam menemukan kompromi antara jumlah kode dan stabilitas sistem. Menemukan aspek ini cukup sulit dan tidak ada resep universal untuk melakukan hal ini. Tetapi ada beberapa tips yang dapat membantu Anda melakukan ini.
- Tutupi logika aplikasi bisnis. Logika bisnis adalah tujuan dari aplikasi yang dibuat, dan itu harus se-stabil mungkin.
- Meliputi hal-hal yang rumit dan dihitung. Perhitungan, transformasi, penggabungan data yang kompleks. Di tempat yang mudah membuat kesalahan.
- Tutupi bug. Bug adalah bendera yang memberi tahu kita bahwa kodenya rentan di sini. Dan ini adalah tempat yang bagus untuk menulis ujian di sini.
- Tutup kode yang sering digunakan kembali. Sangat mungkin bahwa itu akan sering diperbarui dan kita perlu memastikan bahwa menambahkan satu hal tidak akan merusak yang lain.
Jangan tutup tanpa banyak kebutuhan
- Perpustakaan asing - cari perpustakaan yang kodenya sudah dicakup oleh tes.
- Infrastruktur - DI, pemetaan otomatis (jika tidak ada pemetaan rumit) dan sebagainya. Ada tes e2e atau integrasi untuk ini.
- Hal-hal sepele - menugaskan data ke bidang, meneruskan panggilan, dan sebagainya. Anda hampir pasti akan menemukan tempat yang jauh lebih berguna untuk meliput mereka dengan tes.
Yah, pada dasarnya itu.
Untuk meringkas. Kode yang bagus
- Kode kerja
- Mudah dibaca
- Mudah diubah
- Cukup cepat
- Dan tercakup dalam tes dalam jumlah yang tepat.
Semoga beruntung dengan cara yang sulit ini. Dan kemungkinan besar, Anda akan membenci ini. Jika masih belum, selamat datang.
