Saya tahu ini bisa sangat spesifik kasus penggunaan, tetapi saya mendapati diri saya bertanya-tanya terlalu sering. Apakah ada sintaks yang umumnya disukai.
Saya tidak bertanya apa pendekatan terbaik ketika dalam suatu fungsi, saya bertanya apakah saya harus keluar lebih awal atau saya tidak memanggil fungsi itu.
Bungkus jika sekitar panggilan fungsi
if (shouldThisRun) {
runFunction();
}
Memiliki if ( guard ) in function
runFunction() {
if (!shouldThisRun) return;
}
Opsi terakhir jelas memiliki potensi untuk mengurangi duplikasi kode jika fungsi ini disebut beberapa kali, tetapi kadang-kadang rasanya salah untuk menambahkannya di sini karena Anda mungkin kehilangan satu-satunya tanggung jawab fungsi.
Inilah contohnya
Jika saya memiliki fungsi updateStatus () yang hanya memperbarui status sesuatu. Saya hanya ingin status diperbarui jika status telah berubah. Saya tahu tempat-tempat dalam kode saya di mana statusnya berpotensi untuk berubah, dan saya tahu tempat-tempat lain di mana ia telah berubah.
Saya tidak yakin apakah ini hanya saya tetapi rasanya agak kotor untuk memeriksa fungsi dalam ini karena saya ingin menjaga fungsi ini semurni mungkin - jika saya menyebutnya saya berharap statusnya akan diperbarui. Tapi saya tidak tahu apakah lebih baik membungkus telepon dengan memeriksa beberapa tempat yang saya tahu berpotensi untuk tidak berubah.
sumber
Jawaban:
Membungkus if di sekitar panggilan fungsi:
Ini untuk memutuskan apakah fungsi tersebut harus dipanggil sama sekali, dan merupakan bagian dari proses pengambilan keputusan program Anda.
Fungsi klausa penjaga (pengembalian awal):
Ini untuk melindungi agar tidak dipanggil dengan parameter yang tidak valid
Klausa penjaga yang digunakan dengan cara ini menjaga fungsi "murni" (istilah Anda). Itu ada hanya untuk memastikan bahwa fungsi tidak putus dengan data input yang salah.
Logika tentang apakah memanggil fungsi sama sekali adalah pada tingkat abstraksi yang lebih tinggi, bahkan jika hanya saja. Seharusnya ada di luar fungsi itu sendiri. Seperti yang dikatakan DocBrown, Anda dapat memiliki fungsi perantara yang melakukan pemeriksaan ini, untuk menyederhanakan kode.
Ini adalah pertanyaan yang bagus untuk diajukan, dan termasuk dalam rangkaian pertanyaan yang mengarah pada pengenalan tingkat abstraksi. Setiap fungsi harus beroperasi pada satu level abstraksi, dan memiliki logika program dan logika fungsi dalam fungsi terasa salah bagi Anda - ini karena mereka berada pada level abstraksi yang berbeda. Fungsi itu sendiri adalah level yang lebih rendah.
Dengan memisahkan ini, Anda memastikan bahwa kode Anda akan lebih mudah untuk ditulis, dibaca, dan dipelihara.
sumber
Anda dapat memiliki keduanya - fungsi yang tidak memeriksa parameter, dan yang lainnya, seperti ini (mungkin mengembalikan beberapa informasi tentang jika panggilan dilakukan):
Dengan begitu, Anda dapat menghindari logika duplikat dengan memberikan fungsi yang dapat digunakan kembali
tryRunFunction
dan masih memiliki fungsi asli Anda (mungkin murni) yang tidak membuat pemeriksaan di dalam.Perhatikan bahwa terkadang Anda memerlukan fungsi seperti
tryRunFunction
dengan cek terintegrasi secara eksklusif, sehingga Anda dapat mengintegrasikan cek tersebut ke dalamrunFunction
. Atau Anda tidak perlu menggunakan kembali cek di mana saja di program Anda lagi, dalam hal ini Anda dapat membiarkannya tetap dalam fungsi panggilan.Namun, cobalah untuk membuatnya transparan kepada penelepon apa yang terjadi dengan memberikan nama yang tepat fungsi Anda. Jadi penelepon tidak perlu menebak atau melihat ke dalam implementasi jika mereka harus melakukan pemeriksaan sendiri, atau jika fungsi yang dipanggil sudah melakukannya untuk mereka. Awalan sederhana seperti
try
sering dapat mencukupi untuk ini.sumber
runFunction
. Fungsi sepertiupdateStatus()
dapat disertai dengan fungsi lain sepertiupdateIfStatusHasChanged()
. Tapi ini 100% case dependend, tidak ada solusi "satu ukuran untuk semua", jadi ya, saya setuju, idiom "coba" tidak selalu merupakan pilihan yang baik.Adapun siapa yang memutuskan apakah akan menjalankan, jawabannya adalah, dari GRASP , siapa "ahli informasi" yang tahu.
Setelah Anda memutuskan itu, pertimbangkan untuk mengganti nama fungsi agar lebih jelas.
Sesuatu seperti ini, jika fungsinya memutuskan:
Atau, jika penelepon seharusnya memutuskan:
sumber
Saya ingin memperluas jawaban @ Baldrickk.
Tidak ada jawaban umum untuk pertanyaan Anda. Itu tergantung pada makna (kontrak) dari fungsi yang akan dipanggil dan sifat dari kondisi tersebut.
Jadi mari kita bahas dalam konteks contoh panggilan Anda
updateStatus()
. Kontraknya mungkin adalah memperbarui beberapa status karena sesuatu dengan pengaruh pada status telah terjadi. Saya berharap panggilan ke metode itu diizinkan bahkan jika tidak ada perubahan status nyata, dan diperlukan jika ada perubahan nyata.Jadi, situs panggilan dapat melewati panggilan
updateStatus()
jika ia tahu bahwa (di dalam cakrawala domainnya) tidak ada yang relevan berubah. Itulah situasi di mana panggilan harus dikelilingi olehif
konstruk yang sesuai .Di dalam
updateStatus()
fungsi, mungkin ada situasi di mana fungsi ini mendeteksi (dari data di dalam cakrawala domainnya) bahwa tidak ada yang harus dilakukan, dan di situlah ia harus kembali lebih awal.Jadi, pertanyaannya adalah:
Dengan sebuah
updateStatus()
fungsi, saya berharap melihat keduanya, memanggil situs yang tahu tidak ada yang berubah, melewatkan panggilan, dan implementasi yang memeriksa situasi "tidak ada yang berubah" lebih awal, bahkan jika dengan cara ini kondisi yang sama kadang-kadang diperiksa dua kali, keduanya di dalam dan di luar.sumber
Ada banyak penjelasan bagus. Tapi saya ingin terlihat dengan cara yang tidak biasa: Anggap Anda menggunakan cara ini:
Dan Anda perlu memanggil fungsi lain dalam
runFunction
metode seperti ini:Apa yang akan kamu lakukan? Apakah Anda menyalin semua validasi dari atas ke bawah?
Saya kira tidak. Jadi, saya biasanya melakukan pendekatan yang sama: Validasi input dan periksa kondisi dalam
public
metode. Metode publik harus melakukan validasinya sendiri dan memeriksa kondisi yang diperlukan bahkan penelepon melakukannya. Tetapi biarkan metode pribadi lakukan saja bisnisnya sendiri . Beberapa fungsi lain dapat memanggilrunFunction
tanpa melakukan validasi atau memeriksa kondisi apa pun.sumber