Saya telah membaca buku berjudul Clean Code oleh Robert C. Martin. Dalam buku ini saya telah melihat banyak metode untuk membersihkan kode seperti menulis fungsi kecil, memilih nama dengan hati-hati, dll. Tampaknya sejauh ini buku yang paling menarik tentang kode bersih yang pernah saya baca. Namun, hari ini bos saya tidak suka cara saya menulis kode setelah membaca buku ini.
Argumennya adalah
- Menulis fungsi kecil itu menyebalkan karena memaksa Anda untuk pindah ke setiap fungsi kecil untuk melihat apa yang dilakukan kode.
- Letakkan semuanya dalam loop besar utama bahkan jika loop utama lebih dari 300 baris, lebih cepat dibaca.
- Hanya tulis fungsi kecil jika Anda harus menggandakan kode.
- Jangan menulis fungsi dengan nama komentar, letakkan kode kompleks Anda (3-4 baris) dengan komentar di atas; Anda juga dapat memodifikasi kode gagal secara langsung
Ini bertentangan dengan semua yang saya baca. Bagaimana biasanya Anda menulis kode? Satu loop besar utama, tidak ada fungsi kecil?
Bahasa yang saya gunakan sebagian besar adalah Javascript. Saya benar-benar mengalami kesulitan membaca sekarang karena saya telah menghapus semua fungsi kecil saya yang diberi nama dengan jelas dan menempatkan semuanya dalam satu lingkaran besar. Namun, bos saya suka seperti ini.
Salah satu contohnya adalah:
// The way I would write it
if (isApplicationInProduction(headers)) {
phoneNumber = headers.resourceId;
} else {
phoneNumber = DEV_PHONE_NUMBER;
}
function isApplicationInProduction(headers) {
return _.has(headers, 'resourceId');
}
// The way he would write it
// Take the right resourceId if application is in production
phoneNumber = headers.resourceId ? headers.resourceId : DEV_PHONE_NUMBER;
Dalam buku yang saya baca misalnya komentar dianggap sebagai kegagalan untuk menulis kode bersih karena mereka usang jika Anda menulis fungsi kecil dan sering mengarah ke komentar yang tidak diperbarui (Anda memodifikasi kode Anda dan bukan komentar). Namun yang saya lakukan adalah menghapus komentar dan menulis fungsi dengan nama komentar.
Saya ingin saran, cara / praktik mana yang lebih baik untuk menulis kode bersih?
sumber
isApplicationInProduction()
fungsi! Anda harus memiliki tes, dan tes tidak berguna jika kode Anda berperilaku berbeda dari ketika diproduksi. Ini seperti sengaja memiliki kode yang belum diuji / dibuka dalam produksi: itu tidak masuk akal.Jawaban:
Mengambil contoh kode terlebih dahulu. Anda menyukai:
Dan atasan Anda akan menuliskannya sebagai:
Menurut saya, keduanya memiliki masalah. Ketika saya membaca kode Anda, pemikiran langsung saya adalah "Anda dapat menggantinya
if
dengan ekspresi ternary". Lalu saya membaca kode bos Anda dan berpikir "mengapa dia mengganti fungsi Anda dengan komentar?".Saya menyarankan kode optimal antara keduanya:
Itu memberi Anda yang terbaik dari kedua dunia: ekspresi tes disederhanakan dan komentar diganti dengan kode yang dapat diuji.
Mengenai pandangan atasan Anda tentang desain kode:
Jika fungsinya dinamai dengan baik, ini bukan masalahnya.
isApplicationInProduction
sudah jelas dan tidak perlu memeriksa kode untuk melihat apa yang dilakukannya. Kenyataannya kebalikannya adalah benar: memeriksa kode mengungkapkan kurang tentang niat daripada nama fungsi tidak (itulah sebabnya bos Anda harus menggunakan komentar).Mungkin lebih cepat untuk memindai, tetapi untuk benar-benar "membaca" kode, Anda harus dapat secara efektif menjalankannya di kepala Anda. Itu mudah dengan fungsi kecil dan sangat, sangat sulit dengan metode yang panjangnya 100-an.
Saya tidak setuju. Seperti yang ditunjukkan contoh kode Anda, fungsi-fungsi kecil dan bernama baik meningkatkan keterbacaan kode dan harus digunakan kapan pun misalnya Anda tidak tertarik pada "bagaimana", hanya "apa" dari suatu fungsi.
Saya benar-benar tidak dapat memahami alasan di balik yang satu ini, dengan asumsi itu benar-benar serius. Ini adalah hal yang saya harapkan ditulis dalam parodi oleh akun twitter The Expert Beginner . Komentar memiliki kelemahan mendasar: komentar tidak dikompilasi / ditafsirkan sehingga tidak dapat diuji unit. Kode akan diubah dan komentar dibiarkan sendiri dan Anda akhirnya tidak tahu mana yang benar.
Menulis kode untuk mendokumentasikan diri sendiri itu sulit, dan dokumen tambahan (bahkan dalam bentuk komentar) terkadang diperlukan. Tetapi pandangan "Paman Bob" bahwa komentar adalah kegagalan pengkodean terlalu sering terjadi.
Mintalah atasan Anda untuk membaca buku Kode Bersih dan cobalah menolak membuat kode Anda kurang mudah dibaca hanya untuk memuaskannya. Namun pada akhirnya, jika Anda tidak dapat membujuknya untuk berubah, Anda harus sejalan atau menemukan bos baru yang bisa membuat kode lebih baik.
sumber
Ada masalah lain
Tidak ada kode yang baik, karena keduanya pada dasarnya mengasapi kode dengan test case debug . Bagaimana jika Anda ingin menguji lebih banyak hal dengan alasan apa pun?
atau
Apakah Anda ingin menambahkan lebih banyak cabang?
Masalah yang signifikan adalah pada dasarnya Anda menduplikasi bagian dari kode Anda, dan dengan demikian Anda sebenarnya tidak menguji kode sebenarnya. Anda menulis kode debug untuk menguji kode debug, tetapi bukan kode produksi. Ini seperti sebagian membuat basis kode paralel.
Anda berdebat dengan bos Anda tentang cara menulis kode yang buruk dengan lebih cerdik. Sebagai gantinya, Anda harus memperbaiki masalah yang melekat pada kode itu sendiri.
Ketergantungan injeksi
Beginilah tampilan kode Anda:
Tidak ada percabangan di sini, karena logika di sini tidak memiliki percabangan. Program harus menarik nomor telepon dari header. Titik.
Jika Anda ingin memiliki
DEV_PHONE_NUMBER_FROM_OTHER_COUNTRY
hasilnya, Anda harus memasukkannya ke dalamheaders.resourceId
. Salah satu cara melakukannya adalah dengan menyuntikkanheaders
objek yang berbeda untuk kasus uji (maaf jika ini bukan kode yang tepat, keterampilan JavaScript saya agak berkarat):Dengan asumsi bahwa itu
headers
adalah bagian dari respons yang Anda terima dari server: Idealnya Anda memiliki server pengujian lengkap yang memberikanheaders
berbagai jenis untuk keperluan pengujian. Dengan cara ini Anda menguji kode produksi aktual apa adanya dan bukan sebagian kode duplikat yang mungkin atau mungkin tidak berfungsi seperti kode produksi.sumber
Tidak ada jawaban "benar" atau "salah" untuk ini. Namun, saya akan menawarkan pendapat saya berdasarkan 36 tahun pengalaman profesional merancang dan mengembangkan sistem perangkat lunak ...
Berbicara langsung dengan contoh yang Anda berikan ... Menempatkan
isApplicationInProduction()
ke dalam rutinitasnya sendiri adalah hal yang cerdas untuk dilakukan. Hari ini tes itu hanyalah pemeriksaan "header" dan dapat ditangani di?:
operator ternary ( ). Besok, tes mungkin jauh lebih kompleks. Selain itu, "header.resourceId" tidak memiliki hubungan yang jelas dengan aplikasi "dalam status produksi;" Saya berpendapat bahwa tes untuk status seperti itu perlu dipisahkan dari data yang mendasarinya; subrutin akan melakukan ini dan terner tidak akan melakukannya. Selain itu, komentar yang bermanfaat akan mengapa resourceId adalah tes untuk "dalam produksi."Berhati-hatilah untuk tidak berlebihan dengan "fungsi kecil yang diberi nama dengan jelas." Rutin harus merangkum ide lebih dari sekadar "kode". Saya mendukung saran Amon
phoneNumber = getPhoneNumber(headers)
dan menambahkan yanggetPhoneNumber()
seharusnya melakukan tes "status produksi"isApplicationInProduction()
sumber
Kode harus sesederhana mungkin. Bug suka bersembunyi di antara kerumitan, karena mereka sulit dikenali di sana. Jadi apa yang membuat kode sederhana?
Unit kecil (file, fungsi, kelas) adalah ide yang bagus . Unit kecil mudah dimengerti karena ada sedikit hal yang harus Anda pahami sekaligus. Manusia normal hanya bisa menyulap ~ 7 konsep sekaligus. Tetapi ukuran tidak hanya diukur dalam baris kode . Saya dapat menulis kode sesedikit mungkin dengan "bermain golf" kode (memilih nama variabel pendek, mengambil jalan pintas "pintar", menghancurkan kode sebanyak mungkin ke satu baris), tetapi hasil akhirnya tidak sederhana. Mencoba memahami kode seperti itu lebih seperti rekayasa terbalik daripada membaca.
Salah satu cara untuk mempersingkat fungsi adalah mengekstrak berbagai fungsi pembantu. Itu bisa menjadi ide yang bagus ketika mengekstrak kompleksitas yang serba lengkap . Secara terpisah, kerumitan itu jauh lebih sederhana untuk dikelola (dan diuji!) Daripada ketika tertanam dalam masalah yang tidak terkait.
Tetapi setiap panggilan fungsi memiliki overhead kognitif : Saya tidak hanya harus memahami kode di dalam potongan kode saya saat ini, saya juga harus memahami bagaimana itu berinteraksi dengan kode di luar . Saya pikir itu adil untuk mengatakan bahwa fungsi yang Anda ekstrak memperkenalkan kompleksitas lebih ke fungsi daripada ekstrak . Itulah yang bos Anda maksudkan dengan “ fungsi kecil [adalah] menyusahkan karena memaksa Anda untuk pindah ke setiap fungsi kecil untuk melihat apa yang dilakukan kode. ”
Kadang-kadang, fungsi membosankan lama bisa sangat sederhana untuk dipahami, bahkan ketika mereka panjangnya ratusan baris. Ini cenderung terjadi pada inisialisasi dan kode konfigurasi, misalnya ketika membuat GUI dengan tangan tanpa editor drag-and-drop. Tidak ada bagian dari kompleksitas yang dapat Anda ekstrak secara wajar. Tetapi jika formatnya dapat dibaca dan ada beberapa komentar, itu benar-benar tidak sulit untuk mengikuti apa yang terjadi.
Ada banyak metrik kompleksitas lainnya: Jumlah variabel dalam cakupan harus sekecil mungkin. Itu tidak berarti kita harus menghindari variabel. Ini berarti bahwa kita harus membatasi setiap variabel ke ruang lingkup sekecil mungkin di mana diperlukan. Variabel juga menjadi lebih sederhana jika kita tidak pernah mengubah nilai yang dikandungnya.
Metrik yang sangat penting adalah kompleksitas siklomatik (kompleksitas McCabe). Ini mengukur jumlah jalur independen melalui sepotong kode. Jumlah ini tumbuh secara eksponensial dengan masing-masing kondisional. Setiap kondisional atau loop menggandakan jumlah jalur. Ada bukti yang menunjukkan bahwa skor lebih dari 10 poin terlalu rumit. Ini berarti fungsi yang sangat panjang yang mungkin memiliki skor 5 mungkin lebih baik daripada fungsi yang sangat pendek dan padat dengan skor 25. Kita dapat mengurangi kerumitan dengan mengekstraksi aliran kontrol ke fungsi yang terpisah.
Persyaratan Anda adalah contoh dari kompleksitas yang dapat diekstraksi seluruhnya:
Ini masih sangat berguna. Saya tidak yakin apakah itu secara substansial mengurangi kompleksitas karena persyaratan ini tidak terlalu kondisional . Dalam produksi, selalu akan mengambil jalan yang sama.
Kompleksitas tidak pernah bisa hilang. Itu hanya bisa dikocok di sekitar. Apakah banyak hal kecil lebih sederhana daripada beberapa hal besar? Itu sangat tergantung pada keadaan. Biasanya, ada beberapa kombinasi yang terasa pas. Menemukan bahwa kompromi antara berbagai faktor kompleksitas membutuhkan intuisi dan pengalaman, dan sedikit keberuntungan.
Mengetahui cara menulis fungsi yang sangat kecil dan fungsi yang sangat sederhana adalah keterampilan yang berguna, karena Anda tidak dapat membuat pilihan tanpa mengetahui alternatifnya. Mengikuti aturan atau praktik terbaik secara membabi buta tanpa memikirkan bagaimana penerapannya pada situasi saat ini mengarah pada hasil rata - rata paling baik, pemrograman kultus kargo paling buruk .
Di situlah saya tidak setuju dengan atasan Anda. Argumennya tidak valid, tetapi buku Clean Code juga tidak salah. Mungkin lebih baik untuk mengikuti panduan atasan Anda, tetapi kenyataan bahwa Anda sedang memikirkan masalah ini, mencoba menemukan cara yang lebih baik, sangat menjanjikan. Saat mendapatkan pengalaman, Anda akan lebih mudah menemukan anjak piutang yang baik untuk kode Anda.
(Catatan: jawaban ini sebagian didasarkan pada pemikiran dari posting blog Reasonable Code di The Whiteboard oleh Jimmy Hoffa , yang memberikan pandangan tingkat tinggi tentang apa yang membuat kode sederhana.)
sumber
Gaya pemrograman Robert Martin adalah polarisasi. Anda akan menemukan banyak programmer, bahkan yang berpengalaman, yang menemukan banyak alasan mengapa membagi "sebanyak itu" terlalu banyak, dan mengapa menjaga fungsi sedikit lebih besar adalah "cara yang lebih baik". Namun, sebagian besar "argumen" ini sering merupakan ekspresi keengganan untuk mengubah kebiasaan lama, dan untuk belajar sesuatu yang baru.
Jangan dengarkan mereka!
Setiap kali Anda dapat menyimpan komentar dengan refactoring sepotong kode ke fungsi terpisah dengan nama ekspresif, lakukan - itu kemungkinan besar akan meningkatkan kode Anda. Anda tidak perlu melangkah lebih jauh seperti yang dilakukan Bob Martin dalam buku kode bersihnya, tetapi sebagian besar kode yang saya lihat di masa lalu yang menyebabkan masalah pemeliharaan mengandung fungsi terlalu besar, tidak terlalu kecil. Jadi mencoba menulis fungsi yang lebih kecil dengan nama yang menggambarkan diri sendiri adalah hal yang harus Anda coba.
Alat refactoring otomatis membuatnya mudah, sederhana dan aman untuk mengekstrak metode. Dan tolong, jangan menganggap serius orang yang merekomendasikan fungsi penulisan dengan> 300 baris - orang seperti itu pasti tidak memenuhi syarat untuk memberi tahu Anda bagaimana Anda harus kode.
sumber
Dalam kasus Anda: Anda menginginkan nomor telepon. Entah sudah jelas bagaimana Anda akan mendapatkan nomor telepon, maka Anda menulis kode yang jelas. Atau tidak jelas bagaimana Anda akan mendapatkan nomor telepon, maka Anda menulis metode untuk itu.
Dalam kasus Anda, tidak jelas cara mendapatkan nomor telepon, jadi Anda menulis metode untuk itu. Implementasinya tidak jelas, tapi itu sebabnya Anda memasukkannya ke dalam metode terpisah sehingga Anda harus menghadapinya hanya sekali. Komentar akan bermanfaat karena implementasinya tidak jelas.
Metode "isApplicationInProduction" tidak ada gunanya. Memanggilnya dari metode getPhonenumber Anda tidak membuat implementasi lebih jelas, dan hanya membuat lebih sulit untuk mencari tahu apa yang terjadi.
Jangan menulis fungsi kecil. Tulis fungsi yang memiliki tujuan yang jelas dan memenuhi tujuan yang didefinisikan dengan baik itu.
PS. Saya tidak suka implementasinya sama sekali. Diasumsikan bahwa tidak adanya nomor telepon berarti itu adalah versi dev. Jadi, jika nomor telepon tidak ada dalam produksi Anda tidak hanya tidak menanganinya, tetapi mengganti nomor telepon acak. Bayangkan Anda memiliki 10.000 pelanggan, dan 17 tidak memiliki nomor telepon, dan Anda dalam masalah produksi. Apakah Anda dalam produksi atau pengembangan harus diperiksa langsung, bukan berasal dari sesuatu yang lain.
sumber
Bahkan mengabaikan fakta bahwa tidak ada implementasi yang sebagus itu, saya akan mencatat bahwa ini pada dasarnya adalah masalah selera setidaknya pada tingkat abstrak keluar fungsi penggunaan tunggal sepele.
Jumlah baris bukan metrik yang berguna dalam kebanyakan kasus.
300 (atau bahkan 3000) baris kode sekuensial sepenuhnya sepele murni (Setup, atau sesuatu seperti itu) jarang menjadi masalah (Tapi mungkin lebih baik secara otomatis atau sebagai tabel data atau sesuatu), 100 baris loop bersarang dengan banyak rumit kondisi keluar dan matematika seperti yang Anda temukan di Gaussian Elimination atau inversi matriks atau semacam itu mungkin terlalu banyak untuk diikuti dengan mudah.
Bagi saya, saya tidak akan menulis fungsi penggunaan tunggal kecuali jumlah kode yang diperlukan untuk menyatakan hal itu jauh lebih kecil daripada jumlah kode yang membentuk implementasi (Kecuali saya punya alasan seperti mengatakan ingin dapat dengan mudah melakukan injeksi kesalahan). Satu syarat jarang sesuai dengan RUU ini.
Sekarang saya datang dari dunia tertanam inti kecil, di mana kita juga harus mempertimbangkan hal-hal seperti kedalaman tumpukan dan panggilan / pengembalian overhead (yang lagi-lagi menentang jenis fungsi kecil yang tampaknya dianjurkan di sini), dan ini mungkin bias desain saya keputusan, tetapi jika saya melihat bahwa fungsi asli dalam tinjauan kode itu akan mendapatkan nyala usenet gaya lama sebagai tanggapan.
Rasa adalah desain yang sulit untuk diajarkan dan hanya benar-benar dilengkapi dengan pengalaman, saya tidak yakin itu dapat direduksi menjadi aturan tentang panjang fungsi, dan bahkan kompleksitas siklomatik memiliki batasnya sebagai metrik (Kadang-kadang hal-hal hanya rumit namun Anda menanganinya).
Ini bukan untuk mengatakan bahwa kode bersih tidak membahas beberapa hal yang baik, tetapi, dan hal-hal ini harus dipikirkan tetapi adat setempat dan apa yang dilakukan oleh basis kode yang ada harus diberi bobot juga.
Contoh khusus ini bagi saya tampaknya memilih pada detail yang sepele, saya akan lebih peduli dengan hal-hal tingkat yang lebih tinggi karena yang jauh lebih penting bagi kemampuan untuk memahami dan men-debug sistem dengan mudah.
sumber
Jangan meletakkan semuanya dalam satu lingkaran besar, tetapi jangan lakukan ini terlalu sering:
Masalah dengan loop besar adalah bahwa sangat sulit untuk melihat struktur keseluruhannya ketika membentang banyak layar. Jadi cobalah untuk mengambil bongkahan besar, idealnya bongkahan yang memiliki satu tanggung jawab dan dapat digunakan kembali.
Masalah dengan fungsi kecil di atas, adalah bahwa sementara atomisitas dan modularitas umumnya baik, itu bisa diambil terlalu jauh. Jika Anda tidak akan menggunakan kembali fungsi di atas, ini mengurangi pembacaan dan pemeliharaan kode. Untuk menelusuri detail Anda harus melompat ke fungsi alih-alih bisa membaca detail inline, dan pemanggilan fungsi hampir tidak membutuhkan ruang lebih sedikit daripada detail itu sendiri.
Jelas ada keseimbangan yang dapat ditemukan antara metode yang melakukan terlalu banyak dan metode yang melakukan terlalu sedikit . Saya tidak akan pernah keluar dari fungsi kecil seperti di atas kecuali jika itu akan dipanggil dari lebih dari satu tempat, dan bahkan kemudian saya akan berpikir dua kali tentang hal itu, karena fungsinya tidak begitu substansial dalam hal memperkenalkan logika baru dan sebagai waran semacam itu nyaris tidak memiliki keberadaannya sendiri.
sumber
Sepertinya yang sebenarnya Anda inginkan adalah ini:
Ini harus cukup jelas bagi siapa saja yang membacanya: setel
phoneNumber
keresourceId
jika tersedia, atau defaultDEV_PHONE_NUMBER
jika tidak.Jika Anda benar - benar ingin menetapkan variabel itu hanya dalam produksi, Anda harus memiliki beberapa metode utilitas lain yang lebih kanonik (yang tidak memerlukan parameter) untuk menentukan dari mana Anda lari. Membaca header untuk informasi itu tidak masuk akal.
sumber
Biarkan saya berterus terang: menurut saya lingkungan Anda (bahasa / framework / desain kelas, dll.) Tidak benar-benar cocok untuk kode "bersih". Anda mencampur semua jenis hal yang mungkin dalam beberapa baris kode yang seharusnya tidak benar-benar berdekatan. Bisnis apa yang dimiliki fungsi tunggal dengan mengetahui itu
resourceId==undef
berarti Anda tidak dalam produksi, bahwa Anda menggunakan nomor telepon default dalam sistem non-produksi, sehingga resourceId disimpan dalam beberapa "header" dan seterusnya? Saya berasumsiheaders
adalah HTTP header, sehingga Anda bahkan meninggalkan keputusan tentang lingkungan tempat Anda berada pada pengguna akhir?Memfaktorkan satu bagian dari itu ke dalam fungsi tidak akan banyak membantu Anda dengan masalah mendasar itu.
Beberapa kata kunci yang harus dicari:
Anda dapat mencapai apa yang Anda inginkan (dalam konteks lain) dengan nol baris kode, dengan menggeser tanggung jawab kode di sekitar, dan menggunakan kerangka kerja modern (yang mungkin ada atau tidak ada untuk lingkungan / bahasa pemrograman Anda).
Dari uraian Anda ("300 baris kode dalam fungsi 'utama'"), bahkan kata "fungsi" (alih-alih metode) membuat saya berasumsi bahwa tidak ada gunanya dalam apa yang Anda coba capai. Dalam lingkungan pemrograman jadul (yaitu, pemrograman imperatif dasar dengan struktur kecil, tentu saja tidak ada kelas yang bermakna, tidak ada pola kerangka kerja kelas seperti MVC atau semacamnya), benar-benar tidak ada gunanya melakukan sesuatu . Anda tidak akan pernah keluar dari bah tanpa perubahan mendasar. Setidaknya bos Anda tampaknya memungkinkan Anda membuat fungsi untuk menghindari duplikasi kode, itu adalah langkah pertama yang baik!
Saya tahu baik jenis kode maupun jenis programmer yang Anda uraikan dengan baik. Terus terang, jika itu adalah rekan kerja, saran saya akan berbeda. Tetapi karena itu adalah bos Anda, tidak ada gunanya bagi Anda untuk bertengkar tentang hal ini. Bukan hanya bos Anda yang dapat menolak Anda, tetapi penambahan kode Anda memang akan menyebabkan kode yang lebih buruk jika hanya Anda yang melakukan "pekerjaan Anda" secara parsial, dan bos Anda (dan mungkin orang lain) tetap seperti sebelumnya. Mungkin lebih baik untuk hasil akhirnya jika Anda beradaptasi dengan gaya pemrograman mereka (tentu saja saat mengerjakan basis kode khusus ini), dan mencoba, dalam konteks ini, untuk memanfaatkan yang terbaik dari itu.
sumber
"Bersih" adalah satu tujuan dalam menulis kode. Itu bukan satu-satunya tujuan. Tujuan lain yang layak adalah kolocalitas . Secara informal, kolokasi berarti bahwa orang yang mencoba memahami kode Anda tidak perlu melompati semua tempat untuk melihat apa yang Anda lakukan. Menggunakan fungsi yang dinamai bukan ekspresi ternary mungkin tampak seperti hal yang baik, tetapi tergantung pada berapa banyak fungsi yang Anda miliki dan di mana mereka berada, praktik ini dapat berubah menjadi gangguan. Saya tidak dapat memberi tahu Anda apakah Anda telah melewati batas itu, kecuali untuk mengatakan bahwa jika orang mengeluh, Anda harus mendengarkan, terutama jika orang-orang itu memiliki pendapat tentang status pekerjaan Anda.
sumber
Menggunakan fungsi-fungsi kecil, secara umum, merupakan praktik yang baik. Tapi idealnya saya percaya bahwa pengenalan suatu fungsi harus memisahkan potongan logis besar atau mengurangi ukuran keseluruhan kode dengan mengeringkannya. Contoh yang Anda berikan membuat kode lebih panjang dan membutuhkan lebih banyak waktu bagi pengembang untuk membaca, sementara alternatif singkat tidak menjelaskan bahwa
"resourceId"
nilainya hanya ada dalam produksi. Sesuatu yang sederhana seperti itu mudah dilupakan dan dibongkar ketika mencoba bekerja dengannya, terutama jika Anda masih baru dengan basis kode.Saya tidak akan mengatakan bahwa Anda harus benar-benar menggunakan ternary, beberapa orang yang telah bekerja sama dengan saya lebih lama
if () {...} else {...}
, ini sebagian besar merupakan pilihan pribadi. Saya cenderung lebih suka "satu baris melakukan pendekatan satu hal", tapi saya pada dasarnya akan tetap pada apa pun yang biasanya menggunakan basis kode.Ketika menggunakan ternary jika pemeriksaan logis membuat garis terlalu panjang atau rumit maka pertimbangkan untuk membuat variabel bernama / s untuk menyimpan nilai.
Saya juga ingin mengatakan bahwa jika basis kode membentang ke arah fungsi 300 baris, maka perlu subdivisi. Tapi saya menyarankan penggunaan stroke yang sedikit lebih luas.
sumber
Contoh kode yang Anda berikan, bos Anda BENAR. Dalam satu baris yang jelas lebih baik.
Secara umum, memecah logika kompleks menjadi potongan-potongan kecil lebih baik untuk keterbacaan, pemeliharaan kode dan kemungkinan bahwa subkelas akan memiliki perilaku yang berbeda (bahkan jika hanya sedikit).
Jangan abaikan kerugiannya: overhead fungsi, pengaburan (fungsi tidak melakukan apa yang dikomentari oleh komentar dan nama fungsi), logika spageti yang kompleks, potensi fungsi mati (pada satu waktu diciptakan untuk tujuan yang tidak lagi dipanggil).
sumber
Saya bisa memikirkan setidaknya dua argumen yang mendukung fungsi panjang:
Ini berarti Anda memiliki banyak konteks di sekitar setiap baris. Cara memformalkan ini: menggambar grafik aliran kontrol kode Anda. Pada titik (~ = garis) antara entri fungsi dan keluar fungsi, Anda tahu semua tepi yang masuk. Semakin lama fungsinya, semakin banyak simpul yang ada.
Banyak fungsi kecil berarti ada grafik panggilan yang lebih besar dan lebih kompleks. Pilih garis acak dalam fungsi acak, dan jawab pertanyaan "di konteks manakah baris ini dijalankan?" Ini menjadi lebih sulit dan lebih kompleks grafik panggilan, karena Anda harus melihat lebih banyak simpul dalam grafik itu.
Ada juga argumen yang menentang fungsi panjang — unit-testabilitas muncul dalam pikiran. Gunakan t experienceh̶e one ̶f̶o̶r̶c̶e̶ pengalaman Anda saat memilih antara satu dan yang lainnya.
Catatan: Saya tidak mengatakan bos Anda benar, hanya saja sudut pandangnya mungkin tidak sepenuhnya tanpa nilai.
Saya pikir pandangan saya adalah bahwa parameter optimasi yang baik tidak berfungsi. Saya pikir desiderata lebih berguna untuk berpikir dalam hal adalah sebagai berikut: semua yang lain sama, lebih disukai untuk dapat membaca kode deskripsi tingkat tinggi dari kedua logika bisnis dan implementasinya. (Detail implementasi level rendah selalu dapat dibaca jika Anda dapat menemukan sedikit kode yang relevan.)
Mengomentari jawaban David Arno :
Nama membuat jelas apa nilai kembali berarti , tetapi mengatakan apa-apa tentang efek mengeksekusi kode (= apa kode tidak ). Nama (hanya) menyampaikan informasi tentang maksud , kode menyampaikan informasi tentang perilaku (dari bagian mana maksud tersebut kadang-kadang dapat disimpulkan).
Terkadang Anda menginginkan satu, kadang-kadang yang lain, sehingga pengamatan ini tidak membuat aturan keputusan yang satu sisi secara universal valid.
Saya setuju bahwa Anda harus menjalankannya di kepala Anda. Jika Anda memiliki 500 baris fungsi dalam satu fungsi besar vs. dalam banyak fungsi kecil, tidak jelas bagi saya mengapa ini menjadi lebih mudah.
Misalkan kasus ekstrem 500 baris kode garis lurus sangat berpengaruh, dan Anda ingin tahu apakah efek A terjadi sebelum atau setelah efek B. Dalam kasus fungsi besar, gunakan Page Up / Down untuk menemukan dua baris dan kemudian membandingkan nomor baris. Dalam banyak-fungsi kecil kasus, Anda harus ingat di mana di pohon panggilan efek terjadi, dan jika Anda lupa Anda harus menghabiskan banyak waktu untuk menemukan kembali struktur pohon ini.
Saat melintasi pohon panggilan fungsi pendukung, Anda juga dihadapkan dengan tantangan untuk menentukan kapan Anda beralih dari logika bisnis ke detail implementasi. Saya mengklaim tanpa bukti * bahwa semakin sederhana grafik panggilan, semakin mudah untuk membuat perbedaan ini.
(*) Setidaknya saya jujur tentang hal itu ;-)
Sekali lagi, saya pikir kedua pendekatan memiliki kekuatan dan kelemahan.
Apakah Anda tertarik pada "bagaimana" atau "apa" adalah fungsi dari tujuan Anda membaca kode (misalnya mendapatkan ide umum vs melacak bug). Tujuan membaca kode tidak tersedia saat menulis program, dan Anda kemungkinan besar akan membaca kode untuk tujuan yang berbeda; keputusan yang berbeda akan dioptimalkan untuk tujuan yang berbeda.
Yang mengatakan, ini adalah bagian dari pandangan bos yang mungkin paling tidak saya setujui.
Compiler hanya membandingkan nama untuk kesetaraan, mereka tidak pernah memberi Anda MisleadingNameError. Juga, karena beberapa situs panggilan dapat memanggil fungsi yang diberikan berdasarkan nama, kadang-kadang lebih sulit dan rawan kesalahan untuk mengubah nama. Komentar tidak memiliki masalah ini. Namun, ini agak spekulatif; untuk benar-benar menyelesaikan ini, orang mungkin akan membutuhkan data tentang apakah programmer lebih mungkin memperbarui komentar yang menyesatkan vs nama yang menyesatkan, dan saya tidak memilikinya.
sumber
Menurut pendapat saya, kode yang benar untuk fungsi yang Anda butuhkan adalah:
Atau jika Anda ingin membaginya menjadi suatu fungsi, mungkin sesuatu seperti:
Tapi saya pikir Anda memiliki masalah yang lebih mendasar dengan konsep "dalam produksi". Masalah dengan fungsi Anda
isApplicationInProduction
adalah sepertinya aneh bahwa ini adalah satu-satunya tempat dalam sistem di mana berada dalam "produksi" penting, dan bahwa Anda selalu dapat mengandalkan ada atau tidaknya header resourceId untuk memberi tahu Anda. Harus adaisApplicationInProduction
metode umum ataugetEnvironment
metode yang memeriksa lingkungan secara langsung. Kode tersebut harus seperti:Maka Anda bisa mendapatkan nomor telepon dengan:
sumber
Hanya komentar pada dua poin
Banyak editor (mis. IntelliJ) akan membiarkan Anda beralih ke fungsi / kelas hanya dengan Ctrl-Mengklik penggunaan. Selain itu, Anda seringkali tidak perlu mengetahui detail implementasi suatu fungsi untuk membaca kode, sehingga membuat pembacaan kode lebih cepat.
Saya merekomendasikan Anda memberi tahu atasan Anda; dia akan menyukai advokasi Anda dan melihatnya sebagai kepemimpinan. Bersikap sopan saja.
sumber