Dari Kode Lengkap buku ini muncul kutipan berikut:
"Letakkan case normal setelah
if
daripada daripadaelse
"
Yang berarti bahwa pengecualian / penyimpangan dari jalur standar harus dimasukkan ke dalam else
case.
Tetapi The Pragmatic Programmer mengajarkan kita untuk "crash early" (hlm. 120).
Aturan mana yang harus saya ikuti?
if
cabang Anda kembali, gunakan dulu. Dan hindarielse
untuk sisa kode, Anda sudah kembali jika pra-kondisi gagal. Kode lebih mudah dibaca, lebih sedikit indentasi ...Jawaban:
"Crash early" bukan tentang baris kode mana yang datang lebih awal secara tekstual. Ini memberitahu Anda untuk mendeteksi kesalahan pada langkah paling awal yang mungkin dari pemrosesan , sehingga Anda tidak secara tidak sengaja membuat keputusan dan perhitungan berdasarkan keadaan yang sudah salah.
Dalam
if
/else
konstruksi, hanya satu dari blok yang dieksekusi, jadi tidak ada yang bisa dikatakan merupakan langkah "awal" atau "nanti". Oleh karena itu cara memesannya adalah masalah keterbacaan, dan "gagal lebih awal" tidak masuk ke dalam keputusan.sumber
if/else
konstruksi kecil mungkin tidak masalah. Tetapi yang dipanggil dalam satu lingkaran atau dengan banyak pernyataan di setiap blok bisa berjalan lebih cepat dengan kondisi paling umum terlebih dahulu.Jika
else
pernyataan Anda hanya berisi kode kegagalan, maka kemungkinan besar tidak seharusnya ada di sana.Alih-alih melakukan ini:
melakukan hal ini
Anda tidak ingin membuat sarang kode Anda secara mendalam hanya untuk memasukkan pengecekan kesalahan.
Dan, seperti yang telah dinyatakan semua orang, kedua nasihat itu tidak saling bertentangan. Salah satunya adalah tentang urutan eksekusi , yang lain adalah tentang urutan kode .
sumber
if
dan aliran luar biasa di blok setelahelse
tidak berlaku jika Anda tidak memilikielse
! Pernyataan penjaga seperti ini adalah bentuk yang disukai untuk menangani kondisi kesalahan di sebagian besar gaya pengkodean.Anda harus mengikuti keduanya.
"Crash early" / fail advice awal berarti Anda harus menguji input Anda untuk kemungkinan kesalahan sesegera mungkin.
Misalnya, jika metode Anda menerima ukuran atau jumlah yang seharusnya positif (> 0), maka saran awal gagal berarti Anda menguji kondisi itu tepat di awal metode Anda daripada menunggu algoritma menghasilkan omong kosong hasil.
Saran untuk menempatkan kasus normal terlebih dahulu berarti bahwa jika Anda menguji suatu kondisi, maka jalan yang paling mungkin harus didahulukan. Ini membantu dalam kinerja (karena prediksi cabang prosesor akan benar lebih sering) dan mudah dibaca, karena Anda tidak harus melewati blok kode ketika mencoba mencari tahu apa fungsi yang dilakukan dalam kasus normal.
Saran ini tidak benar-benar berlaku ketika Anda menguji prasyarat dan segera menebus (dengan menggunakan menegaskan atau
if (!precondition) throw
membangun), karena tidak ada kesalahan penanganan untuk melewati saat membaca kode.sumber
if(cond){/*more likely code*/}else{/*less likely code*/}
berjalan lebih cepat daripadaif(!cond){/*less likely code*/}else{/*more likely code*/}
karena prediksi cabang. Saya akan berpikir bahwa prediksi cabang tidak bias terhadap pernyataanif
atauelse
pernyataan dan hanya memperhitungkan sejarah. Jadi, jikaelse
lebih mungkin terjadi itu harus dapat memprediksi itu sama baiknya. Apakah asumsi ini salah?Saya pikir @JackAidley sudah mengatakan intinya , tetapi izinkan saya merumuskannya seperti ini:
tanpa Pengecualian (mis. C)
Dalam aliran kode biasa, Anda memiliki:
Dalam kasus "kesalahan awal", kode Anda tiba-tiba berbunyi:
Jika Anda menemukan pola ini - a
return
di dalamelse
(atau bahkanif
) blok, segera ulang sehingga kode tersebut tidak memilikielse
blok:Di dunia nyata ...
Ini menghindari bersarang terlalu dalam dan memenuhi kasus "keluar awal" (membantu menjaga pikiran - dan aliran kode - bersih) dan tidak melanggar "memasukkan hal yang lebih mungkin ke dalam
if
bagian" karena tidak adaelse
bagian .C
dan pembersihanTerinspirasi oleh jawaban pada pertanyaan serupa (yang salah), inilah cara Anda melakukan pembersihan dengan C. Anda dapat menggunakan satu atau dua titik keluar di sana, di sini satu untuk dua titik keluar:
Anda dapat menutupnya menjadi satu titik keluar jika ada sedikit pembersihan yang harus dilakukan:
Penggunaan
goto
ini sangat baik, jika Anda bisa mengatasinya; saran untuk menghindari penggunaangoto
diarahkan pada orang yang belum bisa memutuskan sendiri apakah suatu penggunaan itu baik, dapat diterima, buruk, kode spageti, atau sesuatu yang lain.Pengecualian
Pembicaraan di atas tentang bahasa tanpa pengecualian, yang saya sendiri lebih suka (saya bisa menggunakan penanganan kesalahan secara eksplisit jauh lebih baik, dan dengan lebih sedikit kejutan). Mengutip igli:
Tapi di sini adalah saran bagaimana Anda melakukannya dengan baik dalam bahasa dengan pengecualian, dan kapan Anda ingin menggunakannya dengan baik:
kesalahan kembali saat berhadapan dengan pengecualian
Anda dapat mengganti sebagian besar awal
return
dengan melemparkan pengecualian. Namun , aliran program normal Anda , yaitu setiap aliran kode di mana program tidak menemui, baik, pengecualian ... kondisi kesalahan atau semacamnya, tidak akan menimbulkan pengecualian.Ini berarti bahwa ...
... tidak apa-apa, tapi ...
… tidak. Pada dasarnya, pengecualian bukanlah elemen aliran kontrol . Ini juga membuat Operasi terlihat aneh bagi Anda ("programmer Java ™ itu selalu memberi tahu kami bahwa pengecualian ini normal") dan dapat menghambat debugging (mis. Beri tahu IDE untuk tidak melakukan pengecualian apa pun). Pengecualian sering membutuhkan lingkungan run-time untuk melepas tumpukan untuk menghasilkan traceback, dll. Mungkin ada lebih banyak alasan untuk tidak melakukannya.
Ini bermuara pada: dalam bahasa yang mendukung pengecualian, gunakan apa pun yang cocok dengan logika dan gaya yang ada dan terasa alami. Jika menulis sesuatu dari awal, dapatkan ini disepakati sejak dini. Jika menulis perpustakaan dari awal, pikirkan konsumen Anda. (Jangan, pernah, gunakan
abort()
di perpustakaan juga ...) Tapi apa pun yang Anda lakukan, jangan, sebagai aturan praktis, memiliki pengecualian yang dilemparkan jika operasi berlanjut (kurang lebih) secara normal setelahnya.saran umum wrt. Pengecualian
Cobalah untuk mendapatkan semua Pengecualian dalam program yang disetujui oleh seluruh tim pengembang terlebih dahulu. Pada dasarnya, rencanakan mereka. Jangan menggunakannya terlalu banyak. Terkadang, bahkan dalam C ++, Java ™, Python, pengembalian kesalahan lebih baik. Terkadang tidak; gunakan dengan pikiran.
sumber
goto fail;
identitas lain disembunyikan.Menurut saya 'Kondisi Penjaga' adalah salah satu cara terbaik dan termudah untuk membuat kode dapat dibaca. Saya sangat benci ketika saya melihat
if
di awal metode dan tidak melihatelse
kode karena tidak ada layar. Saya harus gulir ke bawah hanya untuk melihatthrow new Exception
.Letakkan cek di awal sehingga orang yang membaca kode tidak harus melompati seluruh metode untuk membacanya tetapi selalu memindai dari atas ke bawah.
sumber
(@mirabilos' jawabannya sangat baik, tapi inilah cara saya berpikir tentang pertanyaan untuk mencapai kesimpulan yang sama :)
Saya berpikir tentang diri saya (atau orang lain) membaca kode fungsi saya nanti. Ketika saya membaca baris pertama, saya tidak dapat membuat asumsi tentang input saya (kecuali yang saya tidak akan memeriksa lagi). Jadi pikiran saya adalah "Oke, saya tahu saya akan melakukan sesuatu dengan argumen saya. Tetapi pertama-tama mari kita bersihkan" - yaitu membunuh jalur kontrol di mana mereka tidak sesuai dengan keinginan saya. "Tetapi pada saat yang sama , Saya tidak melihat kasus normal sebagai sesuatu yang dikondisikan, saya ingin menekankan hal itu normal.
sumber
Jenis pemesanan kondisi ini tergantung pada kritik bagian kode yang dipertanyakan dan apakah ada standar yang dapat digunakan.
Dengan kata lain:
A. bagian kritis dan tidak ada default => Gagal Dini
B. bagian yang tidak penting dan default => Gunakan default di bagian lain
C. di antara kasus => memutuskan per kasus sesuai kebutuhan
sumber