Pertimbangkan fungsi tanpa parameter ( edit: tidak harus) yang melakukan satu baris kode, dan dipanggil hanya sekali dalam program (meskipun bukan tidak mungkin akan diperlukan lagi di masa mendatang).
Itu bisa melakukan kueri, memeriksa beberapa nilai, melakukan sesuatu yang melibatkan regex ... apa pun yang tidak jelas atau "diretas".
Alasan di balik ini adalah untuk menghindari evaluasi yang sulit dibaca:
if (getCondition()) {
// do stuff
}
di mana getCondition()
fungsi satu baris.
Pertanyaan saya sederhana: apakah ini praktik yang baik? Tampaknya baik-baik saja bagi saya tetapi saya tidak tahu tentang jangka panjang ...
getCondition
? Jika itu sekecil dan jarang digunakan seperti yang Anda katakan maka memberi nama tidak menyelesaikan apa pun.Jawaban:
Tergantung pada satu baris itu. Jika garis dapat dibaca dan ringkas dengan sendirinya, fungsi mungkin tidak diperlukan. Contoh sederhana:
OTOH, jika fungsinya memberikan nama yang bagus untuk satu baris kode yang berisi mis. Ekspresi yang rumit dan sulit dibaca, itu dibenarkan dengan sempurna (bagi saya). Contoh dibuat (dipecah menjadi beberapa baris untuk dibaca di sini):
sumber
taxPayer
global dalam skenario ini. Mungkin kelas ini adalahTaxReturn
, dantaxPayer
merupakan atribut.Ya, ini dapat digunakan untuk memuaskan praktik terbaik. Sebagai contoh, lebih baik untuk memiliki fungsi yang jelas-bernama melakukan beberapa pekerjaan, bahkan jika itu hanya satu baris panjang, daripada memiliki baris kode dalam fungsi yang lebih besar dan memerlukan komentar satu baris yang menjelaskan apa fungsinya. Selain itu, baris kode yang berdekatan harus melakukan tugas pada tingkat abstraksi yang sama. Contoh tandingan akan menjadi sesuatu seperti
Dalam hal ini jelas lebih baik untuk memindahkan garis tengah ke fungsi yang masuk akal.
sumber
petrolFlag |= 0x006A;
tanpa mengambil keputusan, akan lebih baik untuk mengatakanpetrolFlag |= A_B_C;
tanpa fungsi tambahan. Agaknya,engageChoke()
hanya boleh dipanggil jikapetrolFlag
memenuhi kriteria tertentu dan itu harus dengan jelas mengatakan 'Saya butuh fungsi di sini.' Hanya sedikit nit, jawaban ini pada dasarnya tepat jika tidak :)mixLeadedGasoline()
, Anda tidak perlu melakukannya!Saya pikir dalam banyak kasus fungsi seperti itu adalah gaya yang baik, tetapi Anda dapat mempertimbangkan variabel boolean lokal sebagai alternatif dalam kasus ketika Anda tidak perlu menggunakan kondisi ini di suatu tempat di tempat lain misalnya:
Ini akan memberi petunjuk kepada pembaca kode dan menyimpan dari memperkenalkan fungsi baru.
sumber
IsEngineReadyUnlessItIsOffOrBusyOrOutOfService
).Selain jawaban Peter , jika kondisi itu mungkin perlu diperbarui di beberapa titik di masa depan, dengan membuatnya merangkum dengan cara yang Anda sarankan Anda hanya akan memiliki satu titik edit.
Mengikuti contoh Peter, jika ini
menjadi ini
Anda membuat satu pengeditan dan diperbarui secara universal. Dari segi pemeliharaan, ini adalah nilai tambah.
Dari segi kinerja, sebagian besar kompiler yang mengoptimalkan akan menghapus pemanggilan fungsi dan tetap menjalankan blok kode kecil. Mengoptimalkan sesuatu seperti ini sebenarnya dapat mengecilkan ukuran blok (dengan menghapus instruksi yang diperlukan untuk panggilan fungsi, kembali, dll) sehingga biasanya aman untuk dilakukan bahkan dalam kondisi yang dapat mencegah inlining.
sumber
seemsGreen
akan dapat diandalkan dengan benda-benda ringan tidak akan relevan jika kode tidak pernah peduli apakah benda-benda ringan berwarna hijau. Namun, jika definisi "ringan" berubah, sehingga beberapa objek non-hijau yang mengembalikan true untukseemsGreen
tidak dilaporkan sebagai "ringan", maka perubahan tersebut ke definisi "ringan" dapat memecahkan kode yang menguji objek. menjadi "hijau". Dalam beberapa kasus, pengujian green-ness dan berat bersama dalam kode dapat membuat hubungan antara tes lebih jelas daripada jika mereka metode yang terpisah.Selain keterbacaan (atau sebagai pelengkap dari itu) ini memungkinkan untuk menulis fungsi pada tingkat abstraksi yang tepat.
sumber
Tergantung. Terkadang lebih baik untuk merangkum ekspresi dalam fungsi / metode, bahkan jika itu hanya satu baris. Jika sulit dibaca atau Anda membutuhkannya di banyak tempat, maka saya menganggapnya sebagai praktik yang baik. Dalam jangka panjang lebih mudah untuk mempertahankannya, karena Anda telah memperkenalkan satu titik perubahan dan keterbacaan yang lebih baik .
Namun, terkadang itu hanya sesuatu yang tidak Anda butuhkan. Ketika ungkapan itu mudah dibaca dan / atau hanya muncul di satu tempat, maka jangan membungkusnya.
sumber
Saya pikir jika Anda hanya memiliki beberapa dari mereka maka tidak apa-apa tetapi masalah muncul ketika ada banyak dari mereka dalam kode Anda. Dan ketika kompiler berjalan atau interpitor (tergantung pada bahasa yang Anda gunakan) Ini akan berfungsi di memori. Jadi katakanlah Anda memiliki 3 dari mereka, saya tidak berpikir komputer akan melihat tetapi jika Anda mulai memiliki 100 dari hal-hal kecil maka sistem harus mendaftarkan fungsi dalam memori yang hanya dipanggil sekali dan kemudian tidak dihancurkan.
sumber
Saya telah melakukan hal yang tepat ini baru-baru ini dalam aplikasi yang telah saya refactoring, untuk membuat eksplisit arti sebenarnya dari kode tanpa komentar:
sumber
if
? Pendekatan lokal (lambda) ini membuatPaymentButton_Click
fungsi (secara keseluruhan) lebih sulit untuk dibaca. DalamlblCreditCardError
contoh Anda tampaknya menjadi anggota, demikian jugaHaveError
predikat (pribadi) yang valid untuk objek. Saya cenderung downvote ini, tapi saya bukan programmer C #, jadi saya menolak.CheckInputs()
???Memindahkan satu baris ke metode yang dinamai membuat kode Anda lebih mudah dibaca. Banyak orang lain telah menyebutkan hal itu ("kode dokumentasi diri"). Keuntungan lain dari memindahkannya ke suatu metode adalah membuatnya lebih mudah untuk unit test. Ketika itu diisolasi ke dalam metode itu sendiri, dan unit diuji, Anda dapat yakin bahwa jika / ketika bug ditemukan, itu tidak akan ada dalam metode ini.
sumber
Sudah ada banyak jawaban bagus, tetapi ada kasus khusus yang layak disebut .
Jika pernyataan satu baris Anda memerlukan komentar , dan Anda dapat mengidentifikasi dengan jelas (yang berarti: nama) tujuannya, pertimbangkan mengekstraksi fungsi sambil meningkatkan komentar ke dalam API doc. Dengan cara ini Anda membuat panggilan fungsi lebih mudah dan cepat untuk dipahami.
Menariknya, hal yang sama dapat dilakukan jika saat ini tidak ada yang dilakukan, tetapi sebuah komentar yang mengingatkan ekspansi yang diperlukan (dalam waktu dekat 1) ), jadi ini,
bisa juga berubah menjadi ini
1) Anda harus benar-benar yakin tentang ini (lihat prinsip YAGNI )
sumber
Jika bahasa mendukungnya, saya biasanya menggunakan fungsi anonim berlabel untuk mencapai ini.
IMHO ini adalah kompromi yang baik karena memberi Anda manfaat keterbacaan karena tidak memiliki ekspresi rumit yang mengacaukan
if
kondisi sambil menghindari mengacaukan namespace global / paket dengan label kecil yang dibuang. Ini memiliki manfaat tambahan bahwa fungsi "definisi" tepat di mana yang digunakan membuatnya mudah untuk memodifikasi dan membaca definisi.Tidak harus hanya menjadi fungsi predikat. Saya suka membungkus boiler-plate berulang dalam fungsi-fungsi kecil seperti ini juga (Ini bekerja sangat baik untuk generasi daftar pythonic tanpa mengacaukan sintaks braket). Misalnya, contoh berikut yang disederhanakan ketika bekerja dengan PIL dengan python
sumber
[] == False
atau yang lain kesetaraan pythonic serupa yang tidak 'selalu' intuitif. Ini pada dasarnya cara untuk menandai bahwa someCondition sebenarnya merupakan predikat.[] != False
tetapi[]
False sebagai ketika dilemparkan ke boollen([complicated expression producing a list]) == 0
, daripada menggunakanTrue if [blah] else False
yang masih mengharuskan pembaca untuk mengetahui bahwa [] mengevaluasi ke False.