Ketika saya menulis kode, saya selalu berusaha membuat kode saya sebersih dan semudah mungkin dibaca.
Kadang-kadang ada saatnya Anda harus melewati batas dan beralih dari kode bersih yang bagus ke kode yang sedikit lebih buruk untuk membuatnya lebih cepat.
Kapan boleh melewati batas itu?
performance
optimization
quality
readability
maintainability
Ken Cochrane
sumber
sumber
Jawaban:
Anda melewati batas kapan
Berikut ini adalah contoh dunia nyata: sistem eksperimental yang saya jalankan menghasilkan data terlalu lambat, mengambil lebih dari 9 jam per proses dan hanya menggunakan 40% dari CPU. Daripada mengacaukan kode terlalu banyak, saya memindahkan semua file sementara ke sistem file dalam memori. Menambahkan 8 baris baru kode non-jelek, dan sekarang utilisasi CPU di atas 98%. Masalah terpecahkan; tidak perlu kejelekan.
sumber
foo
dan menamainyafoo_ref
- biasanya tinggal tepatfoo
di atas dalam file sumber. Dalam uji harness saya, saya memanggilfoo
danfoo_ref
untuk validasi dan pengukuran kinerja relatif.Ini dikotomi yang salah. Anda dapat membuat kode dengan cepat dan mudah dirawat.
Cara Anda melakukannya adalah menulisnya bersih, terutama dengan struktur data sesederhana mungkin.
Kemudian Anda mencari tahu di mana waktu pengeringan (dengan menjalankannya, setelah Anda menulisnya, bukan sebelumnya), dan memperbaikinya satu per satu. (Ini sebuah contoh.)
Ditambahkan: Kami selalu mendengar tentang pengorbanan, benar, seperti pengorbanan antara waktu dan memori, atau pengorbanan antara kecepatan dan rawatan? Meskipun kurva seperti itu mungkin ada, tidak boleh diasumsikan bahwa program tertentu ada pada kurva , atau bahkan di dekat itu.
Program apa pun yang ada di kurva dapat dengan mudah (dengan memberikannya kepada programmer jenis tertentu) dibuat jauh lebih lambat, dan jauh lebih sedikit perawatannya, dan kemudian tidak akan berada di dekat kurva. Program seperti itu kemudian memiliki banyak ruang untuk dibuat lebih cepat dan lebih dapat dipelihara.
Dalam pengalaman saya, di situlah banyak program dimulai.
sumber
Dalam keberadaan OSS saya, saya melakukan banyak pekerjaan perpustakaan yang bertujuan untuk kinerja, yang sangat terkait dengan struktur data pemanggil (yaitu eksternal ke perpustakaan), dengan (dengan desain) tidak ada mandat atas jenis yang masuk. Di sini, cara terbaik untuk membuat ini performant adalah meta-programming, yang (karena saya di NET-tanah) berarti IL-memancarkan. Itu adalah beberapa kode jelek, jelek, tapi sangat cepat.
Dengan cara ini, saya dengan senang hati menerima kode perpustakaan mungkin "lebih jelek" daripada kode aplikasi , hanya karena ia memiliki lebih sedikit (atau mungkin tidak ada) kontrol atas input , sehingga perlu mencapai beberapa tugas melalui mekanisme yang berbeda. Atau seperti yang saya ungkapkan kemarin:
Sekarang kode aplikasi sedikit berbeda, karena di situlah pengembang "biasa" (waras) biasanya menginvestasikan banyak waktu kolaboratif / profesional mereka; tujuan dan harapan masing-masing (IMO) sedikit berbeda.
IMO, jawaban di atas yang menyarankan itu bisa cepat dan mudah dipelihara mengacu pada kode aplikasi di mana pengembang memiliki kontrol lebih besar atas struktur data, dan tidak menggunakan alat seperti meta-programming. Yang mengatakan, ada berbagai cara melakukan pemrograman meta, dengan berbagai tingkat kegilaan dan berbagai tingkat overhead. Bahkan di arena itu Anda harus memilih level abstraksi yang sesuai. Tetapi ketika Anda secara aktif, positif, benar-benar ingin itu menangani data tak terduga dengan cara tercepat mutlak; itu bisa jadi jelek. Menghadapinya; hlm
sumber
Ketika Anda telah membuat profil kode dan memverifikasi bahwa itu sebenarnya menyebabkan pelambatan yang signifikan.
sumber
Kode bersih tidak harus eksklusif dengan kode yang dapat dijalankan dengan cepat. Biasanya kode yang sulit dibaca ditulis karena lebih cepat ditulis, bukan karena dieksekusi lebih cepat.
Menulis kode "kotor" dalam upaya membuatnya lebih cepat bisa dibilang tidak bijaksana, karena Anda tidak tahu pasti bahwa perubahan Anda sebenarnya meningkatkan apa pun. Knuth mengatakan yang terbaik:
Dengan kata lain, tulis kode bersih-bersih terlebih dahulu. Kemudian, buat profil program yang dihasilkan dan lihat apakah segmen itu, sebenarnya, merupakan hambatan kinerja. Jika demikian, optimalkan bagian sebagaimana diperlukan, dan pastikan untuk menyertakan banyak komentar dokumentasi (mungkin termasuk kode asli) untuk menjelaskan optimisasi. Kemudian buat profil hasil untuk memverifikasi bahwa Anda benar-benar melakukan peningkatan.
sumber
Karena pertanyaannya mengatakan "cepat sulit membaca kode", jawaban sederhana tidak pernah. Tidak pernah ada alasan untuk menulis kode yang sulit dibaca. Mengapa? Dua alasan.
sumber
Ketika itu adalah kode membuang. Maksud saya secara harfiah: ketika Anda menulis skrip untuk melakukan perhitungan atau tugas satu kali, dan tahu dengan pasti Anda tidak akan pernah harus melakukan tindakan itu lagi bahwa Anda dapat 'rm source-file' tanpa ragu-ragu, maka Anda dapat memilih rute yang buruk.
Kalau tidak, itu adalah dikotomi yang salah - jika Anda merasa harus melakukannya dengan jelek untuk melakukannya lebih cepat, Anda salah melakukannya. (Atau prinsip Anda tentang apa kode yang baik perlu direvisi. Menggunakan goto sebenarnya cukup elegan ketika itu adalah solusi yang tepat untuk masalah tersebut. Namun jarang terjadi.)
sumber
Kapan pun perkiraan biaya kinerja yang lebih rendah di pasar lebih besar daripada perkiraan biaya pemeliharaan kode untuk modul kode yang dimaksud.
Orang-orang masih memutar SSE / NEON / etc. perakitan untuk mencoba dan mengalahkan beberapa perangkat lunak pesaing pada chip CPU populer tahun ini.
sumber
Jangan lupa Anda bisa membuat kode yang sulit dibaca mudah dimengerti dengan dokumentasi dan komentar yang sesuai.
Secara umum, profil setelah Anda menulis kode yang mudah dibaca yang melakukan fungsi yang diinginkan. Kemacetan mungkin mengharuskan Anda melakukan sesuatu yang membuatnya terlihat lebih rumit, tetapi Anda memperbaikinya dengan menjelaskan diri Anda sendiri.
sumber
Bagi saya itu adalah proporsi stabilitas (seperti dalam semen beton, tanah liat yang dipanggang dalam oven, dibuat dari batu, ditulis dengan tinta permanen). Semakin tidak stabil kode Anda, karena semakin tinggi kemungkinan Anda perlu mengubahnya di masa mendatang, semakin mudah kelenturannya, seperti tanah liat basah, agar tetap produktif. Saya juga menekankan kelenturan dan bukan keterbacaan. Bagi saya kemudahan mengubah kode lebih penting daripada kemudahan membacanya. Kode bisa mudah dibaca dan mimpi buruk berubah, dan apa gunanya bisa membaca dan dengan mudah memahami detail implementasi jika mereka mimpi buruk untuk berubah? Kecuali itu hanya latihan akademis, biasanya titik untuk dapat dengan mudah memahami kode dalam basis kode produksi adalah dengan maksud untuk dapat lebih mudah mengubahnya sesuai kebutuhan. Jika sulit diubah, maka banyak manfaat keterbacaan keluar jendela. Keterbacaan umumnya hanya berguna dalam konteks kelenturan, dan kelenturan hanya berguna dalam konteks ketidakstabilan.
Tentu saja bahkan yang paling sulit untuk mempertahankan kode yang bisa dibayangkan, terlepas dari seberapa mudah atau sulitnya untuk membaca, tidak menimbulkan masalah jika tidak pernah ada alasan untuk mengubahnya, hanya gunakan saja. Dan dimungkinkan untuk mencapai kualitas seperti itu, terutama untuk kode sistem tingkat rendah di mana kinerja sering cenderung paling menghitung. Saya memiliki kode C yang masih saya gunakan secara teratur yang tidak berubah sejak akhir 80-an. Tidak perlu berubah sejak saat itu. Kode ini jelek, ditulis pada masa-masa sulit, dan saya hampir tidak memahaminya. Namun itu masih berlaku hari ini, dan saya tidak perlu memahami implementasinya untuk mendapatkan banyak manfaat darinya.
Tes penulisan yang menyeluruh adalah salah satu cara untuk meningkatkan stabilitas. Lainnya adalah decoupling. Jika kode Anda tidak bergantung pada hal lain, maka satu-satunya alasan untuk mengubahnya adalah jika itu sendiri perlu diubah. Kadang-kadang sejumlah kecil duplikasi kode dapat berfungsi sebagai mekanisme decoupling untuk secara dramatis meningkatkan stabilitas dengan cara yang membuatnya menjadi pertukaran yang layak jika, sebagai gantinya, Anda mendapatkan kode yang sekarang benar-benar independen dari hal lain. Sekarang kode itu kebal terhadap perubahan ke dunia luar. Sementara itu kode yang bergantung pada 10 pustaka eksternal yang berbeda memiliki 10 kali alasan untuk mengubahnya di masa depan.
Hal lain yang bermanfaat dalam praktik adalah untuk memisahkan perpustakaan Anda dari bagian basis kode Anda yang tidak stabil, bahkan mungkin membangunnya secara terpisah, seperti yang mungkin Anda lakukan untuk perpustakaan pihak ketiga (yang juga dimaksudkan untuk hanya digunakan, tidak diubah, setidaknya tidak oleh Anda tim). Jenis organisasi seperti itu dapat mencegah orang merusaknya.
Lain adalah minimalis. Semakin sedikit kode yang Anda coba lakukan, semakin besar kemungkinan dapat melakukan apa yang dilakukannya dengan baik. Desain monolitik hampir tidak stabil secara permanen, karena semakin banyak fungsi ditambahkan ke dalamnya, semakin tidak lengkap tampaknya.
Stabilitas harus menjadi tujuan utama Anda setiap kali Anda ingin menulis kode yang pasti akan sulit diubah, seperti kode SIMD paralel yang telah disetel mikro hingga mati. Anda menangkal kesulitan mempertahankan kode dengan memaksimalkan kemungkinan Anda tidak perlu mengubah kode, dan karenanya tidak harus mempertahankannya di masa mendatang. Itu membuat biaya pemeliharaan turun ke nol tidak peduli betapa sulitnya kode untuk dipelihara.
sumber