Demi keterbacaan, saya sering menemukan diri saya mendefinisikan variabel sementara saat memanggil fungsi, seperti kode berikut
var preventUndo = true;
doSomething(preventUndo);
Versi yang lebih pendek dari ini adalah:
doSomething(true);
Tetapi ketika saya kembali ke kode saya sering bertanya-tanya apa yang true
dimaksud. Apakah ada konvensi untuk teka-teki seperti ini?
coding-style
Duopixel
sumber
sumber
doSomething( Undo.PREVENT )
Undo = { PREVENT = true, DONT_PREVENT = false }
. Tetapi dalam JavaScript, konvensi adalah melakukannya seperti itu:function myFunction( mandatoryArg1, mandatoryArg2, otherArgs ) { /*...*/ }
lalumyFunction( 1, 2, { option1: true, option2: false } )
.doSomething(preventUndo=True)
Jawaban:
Menjelaskan Variabel
Kasing Anda adalah contoh dari pengantar menjelaskan variabel refactoring. Singkatnya, variabel yang menjelaskan adalah variabel yang tidak sepenuhnya diperlukan, tetapi memungkinkan Anda untuk memberikan nama yang jelas untuk sesuatu, dengan tujuan meningkatkan keterbacaan.
Kode berkualitas baik mengkomunikasikan maksud kepada pembaca; dan sebagai keterbacaan pengembang profesional dan rawatan adalah tujuan # 1 Anda.
Dengan demikian, aturan praktis yang saya sarankan adalah ini: jika tujuan parameter Anda tidak segera jelas, jangan ragu untuk menggunakan variabel untuk memberikannya nama baik. Saya pikir ini adalah praktik yang baik secara umum (kecuali disalahgunakan). Berikut adalah contoh cepat dan dibuat-buat - pertimbangkan:
versus yang sedikit lebih panjang, tetapi bisa dibilang lebih jelas:
Parameter Boolean
Contoh Anda sebenarnya menyoroti mengapa boolean di API sering merupakan ide yang buruk - di sisi panggilan, mereka tidak melakukan apa pun untuk menjelaskan apa yang terjadi. Mempertimbangkan:
Anda harus mencari tahu apa arti parameter tersebut; jika mereka enum, itu akan jauh lebih jelas:
Sunting:
Ditambahkan judul dan bertukar urutan dua paragraf utama, karena terlalu banyak orang yang berfokus pada bagian parameter boolean (untuk menjadi adil, itu adalah paragraf pertama awalnya). Juga menambahkan contoh ke bagian pertama.
sumber
doSomething(preventUndo: true);
ini cukup jelas. Juga, membuat enum untuk setiap boolean di API Anda? Serius?Jangan menulis kode yang tidak Anda butuhkan.
Jika Anda merasa
doSomething(true)
sulit untuk dipahami, Anda harus menambahkan komentar:atau, jika bahasa mendukungnya, tambahkan nama parameter:
Jika tidak, andalkan IDE Anda untuk memberi Anda tanda tangan dari metode yang dipanggil:
Kasus di mana itu berguna
Menempatkan variabel tambahan dapat bermanfaat:
Untuk keperluan debugging:
Kode yang sama dapat ditulis dalam satu baris, tetapi jika Anda ingin meletakkan breakpoint sebelum menambahkan produk ke troli untuk melihat apakah id produk benar, menulis dua baris bukan satu adalah ide yang baik.
Jika Anda memiliki metode dengan banyak parameter dan setiap parameter berasal dari evaluasi. Dalam satu baris, ini mungkin menjadi sama sekali tidak dapat dibaca.
Jika evaluasi suatu parameter terlalu rumit. Contoh kode yang pernah saya lihat:
Kenapa tidak dalam kasus lain?
Mengapa Anda tidak membuat variabel tambahan dalam kasus sederhana?
Bukan karena dampak kinerja. Ini akan menjadi asumsi yang sangat salah dari pengembang pemula yang mengoptimalkan aplikasi secara mikro . Tidak ada dampak kinerja di sebagian besar bahasa, karena kompiler akan menyejajarkan variabel. Dalam bahasa-bahasa di mana kompiler tidak melakukan itu, Anda mungkin mendapatkan beberapa mikrodetik dengan menggariskannya dengan tangan, yang tidak sepadan. Jangan lakukan itu.
Tetapi karena risiko memisahkan nama yang Anda berikan ke variabel dengan nama parameter.
Contoh:
Katakanlah kode aslinya adalah:
Kemudian, pengembang yang mengerjakan
doSomething
pemberitahuan bahwa baru-baru ini, undo history memperkenalkan dua metode baru:Sekarang,
preventUndo
sepertinya tidak terlalu jelas. Apakah itu berarti bahwa hanya tindakan terakhir yang akan dicegah? Atau mungkin itu berarti bahwa pengguna tidak akan dapat menggunakan fitur undo lagi? Atau sejarah undo akan dihapus? Nama yang lebih jelas adalah:Jadi sekarang Anda memiliki:
Bagaimana dengan enum?
Beberapa orang lain menyarankan menggunakan enum. Sementara itu memecahkan masalah langsung, itu menciptakan masalah yang lebih besar. Mari lihat:
Masalah dengan itu:
Terlalu banyak kode.
if (preventUndo == undoPrevention.prevent)
? Serius ?! Saya tidak ingin menulis sepertiif
itu setiap waktu.Menambahkan elemen ke enum sangat menggoda nanti, jika saya menggunakan enum yang sama di tempat lain. Bagaimana jika saya memodifikasinya seperti ini:
Apa yang akan terjadi sekarang? Akankah
doSomething
metode bekerja seperti yang diharapkan? Untuk mencegahnya, Anda harus menulis metode ini dengan cara ini dari awal:Varian yang menggunakan boolean mulai terlihat sangat bagus!
sumber
preventUndo
keallowUndo
dalam tanda tangan ...Anda juga tidak boleh menulis metode dengan bendera boolean.
Mengutip Robert C. Martin dalam bukunya Clean Code (ISBN-13 978-0-13-235088-4), "Melewati boolean menjadi fungsi adalah praktik yang benar-benar mengerikan."
Mengutipnya, alasannya adalah fakta bahwa Anda memiliki benar / salah beralih berarti bahwa metode Anda kemungkinan besar melakukan dua hal yang berbeda (yaitu "Melakukan sesuatu dengan membatalkan" dan "Melakukan sesuatu tanpa membatalkan"), dan karena itu harus dibagi menjadi dua metode yang berbeda (yang secara internal dapat menyebut hal yang sama).
sumber
doSomethingUndoable()
dapat menangkap perubahan dan kemudian memanggildoSomething()
Ketika Anda melihat dua kelas untuk melihat bagaimana mereka digabungkan, salah satu kategorinya adalah penggabungan data , yang merujuk pada kode dalam satu metode panggilan kelas dari kelas lain dan hanya meneruskan data, seperti bulan apa Anda ingin laporan, dan yang lain kategori adalah kopling kontrol , metode panggilan dan mengirimkan sesuatu yang mengontrol perilaku metode. Contoh yang saya gunakan di kelas adalah
verbose
bendera ataureportType
bendera, tetapipreventUndo
juga merupakan contoh yang bagus. Seperti yang baru saja Anda tunjukkan, kontrol kopling membuatnya sulit untuk membaca kode panggilan dan memahami apa yang terjadi. Ini juga membuat kode panggilan rentan terhadap perubahandoSomething()
yang menggunakan bendera yang sama untuk mengontrol undo dan arsip, atau menambahkan parameter lain kedoSomething()
untuk mengontrol pengarsipan, sehingga melanggar kode Anda, dan sebagainya.Masalahnya adalah bahwa kodenya terlalu erat. Melewati bool untuk mengendalikan perilaku, menurut pendapat saya, merupakan pertanda API yang buruk. Jika Anda memiliki API, ubahlah. Dua metode,
doSomething()
dandoSomethingWithUndo()
, akan lebih baik. jika Anda tidak memilikinya, tulis sendiri dua metode pembungkus dalam kode yang Anda miliki, dan mintalah salah satu dari mereka memanggildoSomething(true)
dan panggilan lainnyadoSomething(false)
.sumber
Bukan peran penelepon untuk menentukan peran argumen. Saya selalu mencari versi inline, dan memeriksa tanda tangan dari fungsi yang dipanggil jika saya ragu.
Variabel harus dinamai sesuai perannya dalam lingkup saat ini. Bukan Ruang lingkup di mana mereka dikirim.
sumber
Apa yang akan saya lakukan dalam JavaScript adalah memiliki fungsi mengambil objek sebagai satu-satunya parameter seperti ini:
Kemudian sebut dengan:
sumber
doSomething(x)
metode! lol ... Saya bahkan tidak melihat posting Anda sampai sekarang.Saya suka memanfaatkan fitur bahasa untuk membantu kejelasan diri saya. Misalnya dalam C # Anda dapat menentukan parameter dengan nama:
Dalam JavaScript, saya biasanya lebih suka menggunakan objek opsi sebagai argumen karena alasan ini:
Itu hanya preferensi saya. Saya kira itu akan sangat tergantung pada metode yang dipanggil, dan bagaimana IDE membantu pengembang memahami tanda tangan.
sumber
$.ajax({url:'', data:''})
etc etc.Saya menemukan ini adalah yang paling sederhana dan paling mudah dibaca:
MainMa tidak suka itu. Kita mungkin harus setuju untuk tidak setuju, atau kita dapat menggunakan solusi yang diusulkan Joshua Bloch:
Sekarang jika Anda pernah menambahkan Undo.LIMITED_UNDO, kode Anda tidak akan dikompilasi kecuali jika Anda menerapkan metode createUndoBuffer (). Dan di doSomething () tidak ada jika (Undo.ALLOW == u). Saya telah melakukan keduanya dan metode kedua cukup berat dan sedikit sulit untuk dipahami ketika Undo enum meluas ke halaman dan halaman kode, tetapi itu membuat Anda berpikir. Saya biasanya tetap dengan metode yang lebih sederhana untuk mengganti boolean sederhana dengan enum 2-nilai sampai saya punya alasan untuk berubah. Ketika saya menambahkan nilai ketiga, saya menggunakan IDE saya untuk "Temukan penggunaan" dan perbaiki semuanya.
sumber
Saya pikir solusi Anda membuat kode Anda sedikit lebih mudah dibaca tetapi saya akan menghindari mendefinisikan variabel tambahan hanya untuk membuat panggilan fungsi Anda lebih jelas. Juga, jika Anda ingin menggunakan variabel tambahan, saya akan menandainya sebagai konstan jika bahasa pemrograman Anda mendukungnya.
Saya dapat memikirkan dua alternatif yang tidak melibatkan variabel tambahan:
1. Gunakan komentar ekstra
2. Gunakan enum dua nilai, bukan boolean
Anda dapat menggunakan alternatif 2 jika bahasa Anda mendukung enum.
SUNTING
Tentu saja, menggunakan argumen bernama juga merupakan opsi, jika bahasa Anda mendukungnya.
Mengenai pengkodean tambahan yang dibutuhkan oleh enums, sepertinya benar-benar diabaikan bagi saya. Dari pada
kamu punya
atau
Dan bahkan jika itu sedikit lebih banyak mengetik, ingatlah bahwa kode ditulis sekali dan dibaca berulang kali, sehingga dapat bermanfaat mengetik lebih sedikit sekarang untuk menemukan kode yang lebih mudah dibaca enam bulan kemudian.
sumber
Saya setuju dengan apa yang dikatakan @GlenPeterson:
tetapi juga insteresting akan menjadi berikut karena menurut saya hanya ada dua kemungkinan (benar atau salah)
sumber
doSomething
tetapi memungkinkan penelepon pilihan apakah akan memperbolehkan undo. Obat mungkin memiliki kelebihan yang mengambil opsi Boolean, tetapi juga memiliki versi pembungkus yang memanggil versi sebelumnya dengan parameter selalu benar atau selalu salah.Karena Anda bertanya tentang javascript terutama, dengan menggunakan coffeescript Anda dapat memiliki argumen bernama seperti sintaks, super mudah:
kompilasi ke
Bersenang-senanglah di http://js2coffee.org/ untuk mencoba berbagai kemungkinan
sumber
Hanya untuk solusi yang kurang konvensional dan karena OP menyebutkan Javascript, kemungkinan adalah menggunakan array asosiatif untuk memetakan nilai. Keuntungan lebih dari satu boolean adalah bahwa Anda dapat memiliki argumen sebanyak yang Anda suka dan tidak khawatir tentang urutannya.
Saya menyadari ini adalah refleks seseorang dari latar belakang yang sangat diketik dan mungkin tidak begitu praktis tetapi menganggap ini sebagai orisinalitas.
Kemungkinan lain adalah memiliki objek dan juga dimungkinkan dalam Javascript. Saya tidak 100% yakin ini benar secara sintaksis. Lihatlah pola-pola seperti Factory untuk inspirasi lebih lanjut.
sumber
doSomethingOptions.PREVENTUNDO
) daripada notasi akses array.Fokus pertanyaan Anda dan jawaban lainnya adalah meningkatkan keterbacaan di mana fungsi dipanggil, yang merupakan fokus yang saya setujui. Setiap pedoman khusus, acara "tidak ada argumen boolean", harus selalu berfungsi sebagai sarana untuk tujuan ini dan tidak menjadi dan mengakhiri sendiri.
Saya pikir ini berguna untuk mencatat bahwa masalah ini sebagian besar dihindari ketika bahasa pemrograman mendukung argumen bernama / argumen kata kunci, seperti dalam C # 4 dan Python, atau di mana argumen metode disisipkan dalam nama metode, seperti dalam Smalltalk atau Objective-C.
Contoh:
sumber
Orang harus menghindari melewati variabel boolean sebagai argumen untuk fungsi. Karena fungsi harus melakukan satu hal pada satu waktu. Dengan melewati variabel boolean, fungsi tersebut memiliki dua perilaku. Ini juga menciptakan masalah keterbacaan untuk pada tahap selanjutnya atau untuk programmer lain yang cenderung melihat kode Anda. Ini juga menciptakan masalah dalam menguji fungsi. Mungkin dalam kasus ini Anda harus membuat dua test case. Bayangkan jika Anda memiliki fungsi yang sudah mendapat pernyataan sakelar dan mengubah perilakunya berdasarkan jenis sakelar, maka Anda harus memiliki begitu banyak kasus uji yang berbeda yang ditentukan untuknya.
Setiap kali seseorang menemukan argumen boolean untuk fungsi tersebut, mereka harus mengubah kode sehingga mereka tidak menulis argumen boolean sama sekali.
sumber
if(param) {...} else {...}
)?Kompiler yang bagus untuk bahasa tingkat rendah seperti C ++ akan mengoptimalkan kode mesin di atas 2 baris seperti di bawah ini:
jadi itu tidak masalah dalam kinerja tetapi akan meningkatkan keterbacaan.
Juga sangat membantu untuk menggunakan variabel dalam kasus itu akan menjadi variabel nanti dan dapat menerima nilai-nilai lain juga.
sumber