Saya telah membaca banyak artikel (dan beberapa pertanyaan serupa lainnya yang diposting di StackOverflow) tentang bagaimana dan kapan menggunakan pernyataan, dan saya memahaminya dengan baik. Tapi tetap saja, saya tidak mengerti motivasi seperti apa yang harus mendorong saya untuk menggunakan Debug.Assert
alih-alih memberikan pengecualian. Apa yang saya maksud adalah, di NET respon default untuk pernyataan yang gagal adalah untuk "menghentikan dunia" dan menampilkan kotak pesan kepada pengguna. Meskipun perilaku semacam ini dapat dimodifikasi, saya merasa sangat menjengkelkan dan mubazir untuk melakukan itu, sementara saya dapat, hanya memberikan pengecualian yang sesuai. Dengan cara ini, saya dapat dengan mudah menulis kesalahan ke log aplikasi tepat sebelum saya mengeluarkan pengecualian, dan plus, aplikasi saya tidak selalu macet.
Jadi, mengapa saya, jika ada, harus menggunakan Debug.Assert
sebagai pengganti pengecualian biasa? Menempatkan pernyataan di tempat yang tidak semestinya dapat menyebabkan semua jenis "perilaku yang tidak diinginkan", jadi dalam sudut pandang saya, saya benar-benar tidak mendapatkan apa-apa dengan menggunakan pernyataan alih-alih memberikan pengecualian. Apakah Anda setuju dengan saya, atau saya melewatkan sesuatu di sini?
Catatan: Saya memahami sepenuhnya apa perbedaannya "dalam teori" (Debug vs Rilis, pola penggunaan, dll.), Tetapi seperti yang saya lihat, saya akan lebih baik memberikan pengecualian daripada melakukan pernyataan. Karena jika bug ditemukan pada rilis produksi, saya masih ingin "pernyataan" gagal (lagipula, "overhead" sangat kecil), jadi lebih baik saya memberikan pengecualian saja.
Sunting: Cara saya melihatnya, jika pernyataan gagal, itu berarti bahwa aplikasi memasuki semacam keadaan tak terduga yang rusak. Jadi mengapa saya ingin melanjutkan eksekusi? Tidak masalah jika aplikasi berjalan pada versi debug atau rilis. Hal yang sama berlaku untuk keduanya
sumber
Jawaban:
Meskipun saya setuju bahwa alasan Anda masuk akal - yaitu, jika suatu pernyataan dilanggar secara tidak terduga, masuk akal untuk menghentikan eksekusi dengan melempar - Saya pribadi tidak akan menggunakan pengecualian sebagai pengganti pernyataan. Inilah alasannya:
Seperti yang dikatakan orang lain, pernyataan harus mendokumentasikan situasi yang tidak mungkin , sedemikian rupa sehingga jika situasi yang diduga tidak mungkin terjadi, pengembang diberi tahu. Pengecualian, sebaliknya, memberikan mekanisme aliran kontrol untuk situasi yang luar biasa, tidak mungkin, atau salah, tetapi bukan situasi yang tidak mungkin. Bagi saya, perbedaan utamanya adalah ini:
Seharusnya SELALU dimungkinkan untuk menghasilkan kasus uji yang melatih pernyataan lemparan yang diberikan. Jika tidak mungkin untuk menghasilkan kasus uji seperti itu maka Anda memiliki jalur kode dalam program Anda yang tidak pernah dijalankan, dan itu harus dihapus sebagai kode mati.
Seharusnya TIDAK PERNAH mungkin untuk menghasilkan kasus uji yang menyebabkan pernyataan diaktifkan. Jika sebuah pernyataan diaktifkan, kode salah atau pernyataan salah; bagaimanapun juga, sesuatu perlu diubah dalam kode.
Itulah mengapa saya tidak akan mengganti pernyataan dengan pengecualian. Jika pernyataan tidak dapat benar-benar diaktifkan, maka menggantinya dengan pengecualian berarti Anda memiliki jalur kode yang tidak dapat diuji dalam program Anda . Saya tidak suka jalur kode yang tidak dapat diuji.
sumber
Pernyataan digunakan untuk memeriksa pemahaman pemrogram tentang dunia. Sebuah pernyataan seharusnya gagal hanya jika pemrogram telah melakukan kesalahan. Misalnya, jangan pernah menggunakan pernyataan untuk memeriksa input pengguna.
Menegaskan pengujian untuk kondisi yang "tidak dapat terjadi". Pengecualian adalah untuk kondisi yang "seharusnya tidak terjadi, tetapi lakukan".
Pernyataan berguna karena pada waktu pembuatan (atau bahkan waktu proses) Anda dapat mengubah perilakunya. Misalnya, sering kali dalam build rilis, pernyataan bahkan tidak dicentang, karena menimbulkan overhead yang tidak diperlukan. Ini juga sesuatu yang harus diwaspadai: pengujian Anda bahkan mungkin tidak dijalankan.
Jika Anda menggunakan pengecualian alih-alih menegaskan, Anda kehilangan beberapa nilai:
Kode ini lebih bertele-tele, karena menguji dan melempar pengecualian setidaknya dua baris, sementara pernyataan hanya satu.
Kode pengujian dan lemparan Anda akan selalu berjalan, sementara pernyataan dapat dikompilasi.
Anda kehilangan beberapa komunikasi dengan pengembang lain, karena menegaskan memiliki arti yang berbeda dari kode produk yang memeriksa dan melempar. Jika Anda benar-benar menguji pernyataan pemrograman, gunakan pernyataan.
Selengkapnya di sini: http://nedbatchelder.com/text/assert.html
sumber
EDIT: Menanggapi edit / catatan yang Anda buat di posting Anda: Sepertinya menggunakan pengecualian adalah hal yang benar untuk digunakan selama menggunakan pernyataan untuk jenis hal yang Anda coba capai. Saya pikir hambatan mental yang Anda hadapi adalah bahwa Anda mempertimbangkan pengecualian dan pernyataan untuk memenuhi tujuan yang sama, jadi Anda mencoba mencari tahu mana yang 'benar' untuk digunakan. Meskipun mungkin ada beberapa tumpang tindih dalam cara penggunaan pernyataan dan pengecualian, jangan bingung bahwa bagi mereka solusi yang berbeda untuk masalah yang sama - sebenarnya tidak. Penegasan dan Pengecualian masing-masing memiliki tujuan, kekuatan, dan kelemahannya sendiri.
Saya akan mengetik jawaban dengan kata-kata saya sendiri tetapi ini memberikan konsep keadilan yang lebih baik daripada yang saya miliki:
C # Station: Pernyataan
Pada dasarnya, gunakan pengecualian untuk hal-hal yang perlu ditangkap / ditangani dalam aplikasi produksi, gunakan pernyataan untuk melakukan pemeriksaan logis yang akan berguna untuk pengembangan tetapi dinonaktifkan dalam produksi.
sumber
Saya pikir contoh praktis (dibuat-buat) dapat membantu menjelaskan perbedaannya:
(diadaptasi dari ekstensi Batch MoreLinq )
Jadi seperti yang dikatakan Eric Lippert dkk, Anda hanya menegaskan hal-hal yang Anda harapkan benar, kalau-kalau Anda (pengembang) secara tidak sengaja salah menggunakannya di tempat lain, sehingga Anda dapat memperbaiki kode Anda. Anda pada dasarnya melempar pengecualian ketika Anda tidak memiliki kendali atas atau tidak dapat mengantisipasi apa yang masuk, misalnya untuk input pengguna , sehingga apa pun yang memberikannya data yang buruk dapat merespons dengan tepat (misalnya pengguna).
sumber
Nugget lain dari Code Complete :
Dia melanjutkan dengan menambahkan beberapa pedoman tentang apa yang harus dan tidak boleh ditegaskan.
Di sisi lain, pengecualian:
Jika Anda tidak memiliki buku ini, Anda harus membelinya.
sumber
Debug.Assert secara default hanya akan bekerja dalam build debug, jadi jika Anda ingin menangkap segala jenis perilaku buruk yang tidak terduga dalam build rilis Anda, Anda perlu menggunakan pengecualian atau mengaktifkan konstanta debug di properti project Anda (yang umum bukan ide yang bagus).
sumber
Gunakan pernyataan untuk hal-hal yang ADALAH mungkin tetapi tidak boleh terjadi (jika tidak mungkin, mengapa Anda memberikan pernyataan?).
Bukankah itu terdengar seperti kasus untuk menggunakan
Exception
? Mengapa Anda menggunakan pernyataan, bukanException
?Karena harus ada kode yang dipanggil sebelum pernyataan Anda yang akan menghentikan parameter pernyataan menjadi salah.
Biasanya tidak ada kode sebelum Anda
Exception
yang menjamin bahwa itu tidak akan dibuang.Mengapa baik yang
Debug.Assert()
dikumpulkan dalam prod? Jika Anda ingin mengetahuinya di debug, tidakkah Anda ingin mengetahuinya di prod?Anda menginginkannya hanya selama pengembangan, karena begitu Anda menemukan
Debug.Assert(false)
situasi, Anda kemudian menulis kode untuk menjamin bahwaDebug.Assert(false)
itu tidak akan terjadi lagi. Setelah pengembangan selesai, dengan asumsi Anda telah menemukanDebug.Assert(false)
situasi dan memperbaikinya,Debug.Assert()
dapat dengan aman dikompilasi karena sekarang berlebihan.sumber
Misalkan Anda adalah anggota tim yang cukup besar dan ada beberapa orang yang semuanya bekerja pada basis kode umum yang sama, termasuk tumpang tindih pada kelas. Anda dapat membuat metode yang dipanggil oleh beberapa metode lain, dan untuk menghindari pertentangan kunci, Anda tidak menambahkan kunci terpisah padanya, melainkan "menganggap" itu sebelumnya dikunci oleh metode panggilan dengan kunci tertentu. Seperti, Debug.Assert (RepositoryLock.IsReadLockHeld || RepositoryLock.IsWriteLockHeld); Pengembang lain mungkin mengabaikan komentar yang mengatakan metode panggilan harus menggunakan kunci, tetapi mereka tidak dapat mengabaikan ini.
sumber