The Go
pencipta bahasa tulis :
Go tidak memberikan pernyataan. Mereka tidak diragukan lagi nyaman, tetapi pengalaman kami bahwa pemrogram menggunakannya sebagai penopang untuk menghindari berpikir tentang penanganan dan pelaporan kesalahan yang tepat. Penanganan kesalahan yang tepat berarti bahwa server melanjutkan operasi setelah kesalahan non-fatal alih-alih mogok. Pelaporan kesalahan yang tepat berarti bahwa kesalahan itu langsung dan to the point, menyelamatkan programmer dari menafsirkan jejak kecelakaan besar. Kesalahan yang tepat sangat penting ketika programmer melihat kesalahan tidak terbiasa dengan kode.
Apa pendapat Anda tentang ini?
reflect.DeepEqual
, Anda tentu tidak membutuhkannya . Memang nyaman, tetapi dengan mengorbankan kinerja (unit test adalah kasus penggunaan yang baik). Jika tidak, Anda dapat menerapkan pemeriksaan kesetaraan apa pun yang sesuai untuk "koleksi" Anda tanpa terlalu banyak kesulitan.for
loop in Go (seperti C). Ini akan benar-benar menyenangkan untuk memiliki operasi slice generik, meskipun perbandingan jadi rumit ketika pointer dan struct yang terlibat.Jawaban:
Tidak, tidak ada yang salah
assert
selama Anda menggunakannya sebagaimana dimaksud.Artinya, itu seharusnya untuk menangkap kasus yang "tidak dapat terjadi", selama debugging, sebagai lawan dari penanganan kesalahan normal.
sumber
Tidak, tidak
goto
jugaassert
tidak jahat. Namun keduanya bisa disalahgunakan.Menegaskan adalah untuk pemeriksaan kewarasan. Hal-hal yang seharusnya mematikan program jika tidak benar. Bukan untuk validasi atau sebagai pengganti untuk penanganan kesalahan.
sumber
goto
dengan bijak?goto
karena alasan agama semata, kemudian gunakan sajagoto
daripada mengaburkan apa yang Anda lakukan. Dengan kata lain: jika Anda dapat membuktikan bahwa Anda benar-benar membutuhkangoto
, dan satu-satunya alternatif adalah memberlakukan banyak perancah tidak berguna yang pada akhirnya melakukan hal yang sama tetapi tanpa mengubah Polisi Goto ... maka gunakan sajagoto
. Tentu saja, prasyarat untuk hal ini adalah "jika Anda dapat membuktikan bahwa Anda benar-benar membutuhkangoto
". Seringkali, orang tidak. Itu masih tidak berarti itu pada dasarnya Hal Buruk.goto
digunakan di kernel linux untuk pembersihan kodeDengan logika itu, breakpoint juga jahat.
Pemberitahuan harus digunakan sebagai bantuan debugging, dan tidak ada yang lain. "Evil" adalah ketika Anda mencoba menggunakannya alih - alih penanganan kesalahan.
Asserts ada untuk membantu Anda, programmer, mendeteksi dan memperbaiki masalah yang tidak boleh ada dan memverifikasi bahwa asumsi Anda tetap benar.
Mereka tidak ada hubungannya dengan penanganan kesalahan, tetapi sayangnya, beberapa programmer menyalahgunakannya, dan kemudian menyatakan mereka "jahat".
sumber
Saya suka menggunakan banyak menegaskan. Saya merasa sangat berguna ketika saya membangun aplikasi untuk pertama kalinya (mungkin untuk domain baru). Alih-alih melakukan pengecekan error yang sangat mewah (bahwa saya akan mempertimbangkan optimasi prematur) saya kode cepat dan saya menambahkan banyak menegaskan. Setelah saya tahu lebih banyak tentang cara kerja saya menulis ulang dan menghapus beberapa dari konfirmasi dan mengubahnya untuk penanganan kesalahan yang lebih baik.
Karena menegaskan saya menghabiskan banyak waktu lebih sedikit program coding / debugging.
Saya juga memperhatikan bahwa pernyataan tersebut membantu saya memikirkan banyak hal yang dapat merusak program saya.
sumber
Sebagai informasi tambahan, go menyediakan fungsi bawaan
panic
. Ini dapat digunakan sebagai penggantiassert
. Misalnyapanic
akan mencetak jejak tumpukan, jadi dalam beberapa cara ia memiliki tujuanassert
.sumber
Mereka harus digunakan untuk mendeteksi bug dalam program. Input pengguna tidak buruk.
Jika digunakan dengan benar, mereka tidak jahat.
sumber
Ini banyak muncul, dan saya pikir satu masalah yang membuat pembelaan terhadap pernyataan membingungkan adalah bahwa mereka sering didasarkan pada pengecekan argumen. Jadi pertimbangkan contoh berbeda ketika Anda mungkin menggunakan pernyataan:
Anda menggunakan pengecualian untuk input karena Anda berharap terkadang Anda akan mendapatkan input yang buruk. Anda menegaskan bahwa daftar diurutkan untuk membantu Anda menemukan bug dalam algoritme Anda, yang menurut definisi tidak Anda harapkan. Pernyataan ini hanya ada dalam versi debug, jadi meskipun biayanya mahal, Anda tidak keberatan melakukannya di setiap permintaan rutin.
Anda masih harus menguji unit kode produksi Anda, tetapi itu cara yang berbeda dan saling melengkapi untuk memastikan kode Anda benar. Tes unit memastikan rutinitas Anda sesuai dengan antarmuka, sementara pernyataan adalah cara yang lebih halus untuk memastikan implementasi Anda melakukan apa yang Anda harapkan.
sumber
Penegasan tidak jahat tetapi mereka dapat dengan mudah disalahgunakan. Saya setuju dengan pernyataan bahwa "pernyataan sering digunakan sebagai penopang untuk menghindari berpikir tentang penanganan dan pelaporan kesalahan yang tepat". Saya sudah sering melihat ini.
Secara pribadi, saya suka menggunakan pernyataan karena mereka mendokumentasikan asumsi yang mungkin saya buat ketika menulis kode saya. Jika asumsi ini rusak saat mempertahankan kode, masalahnya dapat dideteksi selama pengujian. Namun, saya membuat titik untuk menghapus setiap pernyataan dari kode saya ketika melakukan membangun produksi (yaitu, menggunakan #ifdefs). Dengan menghapus pernyataan dalam produksi, saya menghilangkan risiko orang menyalahgunakannya sebagai penopang.
Ada juga masalah lain dengan pernyataan. Pernyataan hanya diperiksa pada saat run-time. Namun seringkali pemeriksaan yang ingin Anda lakukan bisa dilakukan pada waktu kompilasi. Lebih baik mendeteksi masalah pada waktu kompilasi. Untuk programmer C ++, boost menyediakan BOOST_STATIC_ASSERT yang memungkinkan Anda melakukan ini. Untuk programmer C, artikel ini ( teks tautan ) menjelaskan teknik yang dapat digunakan untuk melakukan pernyataan pada waktu kompilasi.
Singkatnya, aturan praktis yang saya ikuti adalah: Jangan menggunakan pernyataan dalam membangun produksi dan, jika mungkin, hanya menggunakan pernyataan untuk hal-hal yang tidak dapat diverifikasi pada waktu kompilasi (yaitu, harus diperiksa pada saat run-time).
sumber
Saya akui telah menggunakan konfirmasi tanpa mempertimbangkan pelaporan kesalahan yang tepat. Namun, itu tidak menghilangkan bahwa mereka sangat membantu ketika digunakan dengan benar.
Mereka sangat berguna jika Anda ingin mengikuti prinsip "Kecelakaan Dini". Misalnya, Anda menerapkan mekanisme penghitungan referensi. Di lokasi tertentu dalam kode Anda, Anda tahu bahwa refcount harus nol atau satu. Dan juga anggaplah bahwa jika refcount salah, program tidak akan crash segera tetapi selama loop pesan berikutnya pada titik mana akan sulit untuk mengetahui mengapa ada yang salah. Penegasan akan sangat membantu dalam mendeteksi kesalahan lebih dekat ke asalnya.
sumber
Saya lebih suka menghindari kode yang melakukan hal berbeda dalam debug dan rilis.
Membobol debugger pada kondisi dan memiliki semua info file / baris berguna, juga ekspresi yang tepat dan nilai yang tepat.
Memiliki pernyataan yang akan "mengevaluasi kondisi hanya dalam debug" mungkin merupakan pengoptimalan kinerja, dan karenanya, hanya berguna dalam 0,0001% program - di mana orang tahu apa yang mereka lakukan. Dalam semua kasus lain, ini berbahaya, karena ekspresi sebenarnya dapat mengubah status program:
assert(2 == ShroedingersCat.GetNumEars());
akan membuat program melakukan berbagai hal dalam debug dan rilis.Kami telah mengembangkan satu set makro pernyataan yang akan mengeluarkan pengecualian, dan melakukannya dalam versi debug dan rilis. Misalnya,
THROW_UNLESS_EQ(a, 20);
akan melempar pengecualian dengan pesan apa () yang memiliki kedua file, baris, dan nilai aktual a, dan seterusnya. Hanya makro yang memiliki kekuatan untuk ini. Pengawak mungkin dikonfigurasikan untuk memecahkan pada 'throw' dari tipe pengecualian spesifik.sumber
Saya sangat tidak suka menegaskan. Namun saya tidak akan mengatakan bahwa mereka jahat.
Pada dasarnya pernyataan akan melakukan hal yang sama dengan pengecualian yang tidak dicentang, satu-satunya pengecualian adalah bahwa pernyataan (biasanya) tidak boleh disimpan untuk produk akhir.
Jika Anda membangun jaring pengaman untuk diri Anda sendiri saat debugging dan membangun sistem mengapa Anda menolak jaring pengaman ini untuk pelanggan Anda, atau meja bantuan dukungan Anda, atau siapa saja yang akan menggunakan perangkat lunak yang sedang Anda buat. Gunakan pengecualian secara eksklusif untuk situasi yang menegaskan dan luar biasa. Dengan membuat hierarki pengecualian yang sesuai, Anda akan dapat membedakan satu dari yang lainnya dengan sangat cepat. Kecuali saat ini pernyataan tetap ada dan dapat memberikan informasi berharga jika terjadi kegagalan yang seharusnya hilang.
Jadi saya sepenuhnya memahami pencipta Go dengan menghapus sama sekali dan memaksa programmer untuk menggunakan pengecualian untuk menangani situasi. Ada penjelasan sederhana untuk ini, pengecualian hanyalah mekanisme yang lebih baik untuk pekerjaan itu, mengapa tetap dengan ingatan kuno?
sumber
Jawaban singkat: Tidak, saya yakin pernyataan bisa berguna
sumber
Saya baru-baru ini mulai menambahkan beberapa pernyataan ke kode saya, dan ini adalah bagaimana saya telah melakukannya:
Saya secara mental membagi kode saya menjadi kode batas dan kode internal. Kode batas adalah kode yang menangani input pengguna, membaca file, dan mendapatkan data dari jaringan. Dalam kode ini, saya meminta input dalam satu loop yang hanya keluar ketika input valid (dalam hal input pengguna interaktif), atau melemparkan pengecualian dalam kasus file / data rusak jaringan yang tidak dapat dipulihkan.
Kode internal adalah segalanya. Misalnya, fungsi yang menetapkan variabel di kelas saya mungkin didefinisikan sebagai
dan fungsi yang mendapat input dari jaringan mungkin terbaca seperti itu:
Ini memberi saya dua lapis cek. Apa pun di mana data ditentukan pada saat run-time selalu mendapatkan pengecualian atau penanganan kesalahan langsung. Namun, pemeriksaan tambahan
Class::f
denganassert
pernyataan itu berarti bahwa jika beberapa kode internal pernah meneleponClass::f
, saya masih memiliki pemeriksaan kewarasan. Kode internal saya mungkin tidak memberikan argumen yang valid (karena saya mungkin telah menghitungvalue
dari beberapa rangkaian fungsi yang kompleks), jadi saya suka memiliki pernyataan dalam fungsi pengaturan untuk mendokumentasikan bahwa terlepas dari siapa yang memanggil fungsi,value
tidak boleh lebih besar dari atau sama denganend
.Ini sepertinya cocok dengan apa yang saya baca di beberapa tempat, bahwa pernyataan tidak mungkin dilanggar dalam program yang berfungsi dengan baik, sementara pengecualian harus untuk kasus luar biasa dan kesalahan yang masih mungkin. Karena secara teori saya memvalidasi semua input, seharusnya tidak mungkin pernyataan saya dipicu. Jika ya, program saya salah.
sumber
Jika pernyataan yang Anda bicarakan berarti bahwa program muntah dan kemudian ada, pernyataan bisa sangat buruk. Ini bukan untuk mengatakan bahwa mereka selalu hal yang salah untuk digunakan, mereka adalah konstruksi yang sangat mudah disalahgunakan. Mereka juga memiliki banyak alternatif yang lebih baik. Hal-hal seperti itu adalah kandidat yang baik untuk disebut jahat.
Sebagai contoh, modul pihak ke-3 (atau modul apa saja) seharusnya hampir tidak pernah keluar dari program panggilan. Ini tidak memberi pemrogram panggilan kontrol atas risiko apa yang harus diambil oleh program pada saat itu. Dalam banyak kasus, data sangat penting sehingga bahkan menyimpan data yang rusak lebih baik daripada kehilangan data itu. Pernyataan dapat memaksa Anda kehilangan data.
Beberapa alternatif untuk menegaskan:
Beberapa referensi:
Bahkan orang-orang yang menganjurkan untuk menegaskan berpikir mereka hanya boleh digunakan dalam pembangunan dan bukan dalam produksi:
Orang ini mengatakan bahwa pernyataan harus digunakan ketika modul berpotensi merusak data yang tetap ada setelah pengecualian dilemparkan: http://www.advogato.org/article/949.html . Ini tentu saja merupakan poin yang masuk akal, namun, modul eksternal tidak boleh menentukan seberapa penting data yang rusak untuk program panggilan (dengan keluar "untuk" mereka). Cara yang tepat untuk menangani ini adalah dengan melemparkan pengecualian yang membuatnya jelas bahwa program sekarang mungkin dalam keadaan tidak konsisten. Dan karena program yang baik sebagian besar terdiri dari modul (dengan sedikit kode lem di executable utama), menegaskan hampir selalu hal yang salah untuk dilakukan.
sumber
assert
sangat berguna dan dapat menyelamatkan Anda dari banyak kemunduran saat kesalahan tak terduga terjadi dengan menghentikan program pada tanda-tanda awal masalah.Di sisi lain, sangat mudah disalahgunakan
assert
.Versi yang tepat dan benar akan seperti:
Jadi ... dalam jangka panjang ... dalam gambaran besar ... Saya harus setuju bahwa
assert
dapat disalahgunakan. Saya selalu melakukannya.sumber
assert
sedang disalahgunakan untuk penanganan kesalahan karena kurang mengetik.Jadi sebagai perancang bahasa, mereka seharusnya melihat bahwa penanganan kesalahan yang tepat dapat dilakukan dengan pengetikan yang lebih rendah. Tidak termasuk menegaskan karena mekanisme pengecualian Anda bertele-tele bukanlah solusi. Oh, tunggu, Go juga tidak memiliki pengecualian. Sangat buruk :)
sumber
Saya merasa seperti menendang kepala penulis ketika saya melihat itu.
Saya menggunakan menegaskan sepanjang waktu dalam kode dan akhirnya menggantikannya semua ketika saya menulis lebih banyak kode. Saya menggunakannya ketika saya belum menulis logika yang diperlukan dan ingin diberitahu ketika saya mengalami kode bukannya menulis pengecualian yang akan dihapus karena proyek semakin dekat dengan penyelesaian.
Pengecualian juga berbaur dengan kode produksi lebih mudah yang saya sukai. Pernyataan lebih mudah diperhatikan daripada
throw new Exception("Some generic msg or 'pretend i am an assert'");
sumber
Masalah saya dengan jawaban-jawaban ini adalah menegaskan tidak ada yang secara jelas menentukan apa yang membuatnya berbeda dari kesalahan fatal yang biasa , dan mengapa sebuah pernyataan tidak dapat menjadi bagian dari pengecualian . Sekarang, dengan ini dikatakan, bagaimana jika pengecualian tidak pernah ditangkap? Apakah itu membuatnya menjadi pernyataan nomenklatur? Dan, mengapa Anda ingin memaksakan pembatasan dalam bahasa yang dapat dikemukakan pengecualian / tidak ada / dapat menangani?
sumber
func()
dengan nomor negatif. Sekarang, tiba-tiba dengan pernyataan Anda, Anda telah menarik karpet dari bawah saya dan tidak memberi saya kesempatan untuk pulih, daripada dengan sopan memberi tahu saya apa yang saya minta tidak bisa dilakukan. Tidak ada yang salah dengan menuduh program itu berperilaku tidak pantas dan mengeluarkannya kutipan: masalahnya adalah Anda mengaburkan tindakan menegakkan hukum, dan menghukum penjahat.Ya, menegaskan itu jahat.
Seringkali mereka digunakan di tempat-tempat di mana penanganan kesalahan yang tepat harus digunakan. Biasakan menulis penanganan kesalahan kualitas produksi yang tepat sejak awal!
Biasanya mereka menghalangi penulisan unit test (kecuali jika Anda menulis pernyataan kustom yang berinteraksi dengan harness tes Anda). Ini sering karena mereka digunakan di mana penanganan kesalahan yang tepat harus digunakan.
Sebagian besar mereka dikompilasi dari rilis build yang berarti bahwa tidak ada "pengujian" mereka yang tersedia ketika Anda menjalankan kode yang sebenarnya Anda rilis; mengingat bahwa dalam situasi multi-utas masalah terburuk seringkali hanya muncul dalam kode rilis ini bisa buruk.
Terkadang mereka adalah penopang untuk desain yang rusak; yaitu desain kode memungkinkan pengguna untuk memanggilnya dengan cara yang seharusnya tidak dipanggil dan menyatakan "mencegah" ini. Perbaiki desain!
Saya menulis tentang ini lebih lanjut di blog saya pada tahun 2005 di sini: http://www.lenholgate.com/blog/2005/09/assert-is-evil.html
sumber
Tidak seburuk yang umumnya kontraproduktif. Ada pemisahan antara pemeriksaan kesalahan permanen dan debugging. Menegaskan membuat orang berpikir bahwa semua debugging harus permanen dan menyebabkan masalah keterbacaan yang besar ketika banyak digunakan. Penanganan kesalahan permanen harus lebih baik daripada yang diperlukan, dan karena menegaskan menyebabkan kesalahan sendiri, itu adalah praktik yang cukup dipertanyakan.
sumber
saya tidak pernah menggunakan assert (), contoh biasanya menunjukkan sesuatu seperti ini:
Ini buruk, saya tidak pernah melakukan ini, bagaimana jika permainan saya mengalokasikan sekelompok monster? mengapa saya harus menghentikan permainan, alih-alih Anda harus menangani kesalahan dengan anggun, jadi lakukan sesuatu seperti:
sumber
new
tidak pernah kembalinullptr
, ia melempar.