Ada diskusi yang terjadi di comp.lang.c ++. Dimoderasi tentang apakah atau tidak, yang dalam C ++ hanya ada di debug build secara default, harus disimpan dalam kode produksi atau tidak.
Jelas, setiap proyek adalah unik, jadi pertanyaan saya di sini adalah tidak begitu banyak apakah pernyataan harus disimpan, tetapi di mana kasus ini dianjurkan / bukan ide yang baik.
Maksud saya, maksud saya:
- Pemeriksaan run-time yang menguji suatu kondisi yang, ketika salah, mengungkapkan bug dalam perangkat lunak.
- Suatu mekanisme dimana program dihentikan (mungkin setelah pekerjaan pembersihan yang sangat minim).
Saya tidak perlu berbicara tentang C atau C ++.
Pendapat saya sendiri adalah bahwa jika Anda adalah programmer, tetapi tidak memiliki data (yang merupakan kasus dengan kebanyakan aplikasi desktop komersial), Anda harus tetap menggunakannya, karena pernyataan yang gagal menunjukkan bug, dan Anda tidak boleh pergi aktif dengan bug, dengan risiko merusak data pengguna. Ini memaksa Anda untuk menguji dengan kuat sebelum mengirim, dan membuat bug lebih terlihat, sehingga lebih mudah dikenali dan diperbaiki.
Apa pendapat / pengalaman Anda?
Bersulang,
Carl
Lihat pertanyaan terkait di sini
Tanggapan dan Pembaruan
Hei Graham,
Pernyataan adalah kesalahan, murni dan sederhana dan karenanya harus ditangani seperti itu. Karena kesalahan harus ditangani dalam mode rilis maka Anda tidak benar-benar membutuhkan pernyataan.
Itu sebabnya saya lebih suka kata "bug" ketika berbicara tentang pernyataan. Itu membuat segalanya lebih jelas. Bagi saya, kata "kesalahan" terlalu kabur. File yang hilang adalah kesalahan, bukan bug, dan program harus menghadapinya. Mencoba untuk menunjukkan referensi null pointer adalah bug, dan program harus mengakui bahwa ada sesuatu yang berbau keju buruk.
Oleh karena itu, Anda harus menguji pointer dengan penegasan, tetapi keberadaan file dengan kode penanganan kesalahan yang normal.
Sedikit di luar topik, tetapi poin penting dalam diskusi.
Sebagai kepala-up, jika pernyataan Anda masuk ke debugger ketika gagal, mengapa tidak. Tetapi ada banyak alasan file tidak bisa ada yang sepenuhnya di luar kendali kode Anda: hak baca / tulis, disk penuh, perangkat USB dicabut, dll. Karena Anda tidak memiliki kontrol atasnya, saya merasa pernyataan bukan cara yang tepat untuk menghadapinya.
Carl
Thomas,
Ya, saya memiliki Kode Lengkap, dan harus mengatakan saya sangat tidak setuju dengan saran khusus itu.
Katakan pengalokasi memori khusus Anda mengacaukan, dan nol sepotong memori yang masih digunakan oleh beberapa objek lain. Kebetulan saya nol pointer yang objek ini dereferensi secara teratur, dan salah satu invarian adalah bahwa pointer ini tidak pernah nol, dan Anda memiliki beberapa pernyataan untuk memastikan itu tetap seperti itu. Apa yang Anda lakukan jika pointer tiba-tiba nol. Anda hanya jika () di sekitarnya, berharap itu berfungsi?
Ingat, kita berbicara tentang kode produk di sini, jadi tidak ada pembobolan terhadap debugger dan memeriksa status lokal. Ini adalah bug nyata pada mesin pengguna.
Carl
Jawaban:
Pernyataan adalah komentar yang tidak menjadi ketinggalan zaman. Mereka mendokumentasikan keadaan teoritis mana yang dimaksudkan, dan negara mana yang seharusnya tidak terjadi. Jika kode diubah sehingga menyatakan perubahan diizinkan, pengembang segera diberitahu dan perlu memperbarui pernyataan.
sumber
Izinkan saya mengutip Kode Lengkap Steve McConnell. Bagian tentang Pernyataan adalah 8.2.
Namun, kemudian di bagian yang sama, saran ini diberikan:
Saya pikir selama kinerjanya tidak menjadi masalah, biarkan pernyataan itu muncul, tetapi alih-alih menampilkan pesan, minta ia menulis ke file log. Saya pikir saran itu juga ada dalam Kode Lengkap, tetapi saya tidak menemukannya sekarang.
sumber
Biarkan pernyataan diaktifkan dalam kode produksi, kecuali jika Anda telah mengukur bahwa program berjalan lebih cepat secara signifikan dengan mereka dimatikan.
http://c2.com/cgi/wiki?ShipWithAssertionsOn
sumber
assert ref != null;
berbeda dariif (ref == null) throw new IllegalArgumentException();
Anda tidak boleh menggunakan yang pertama untuk prasyarat yang bisa salah. Anda perlu menggunakanassert
untuk hal-hal yang tidak bisa salah. Contoh,int i = -1 * someNumber; i = i * i;
lalu untuk mengingatkan orang-orang yangi
positif,assert i > 0;
Jika Anda bahkan berpikir untuk membiarkan asersi dalam produksi, Anda mungkin menganggapnya salah. Inti dari pernyataan adalah bahwa Anda dapat mematikannya dalam produksi, karena mereka bukan bagian dari solusi Anda. Mereka adalah alat pengembangan, yang digunakan untuk memverifikasi bahwa asumsi Anda benar. Tetapi saat Anda mulai berproduksi, Anda harus sudah memiliki kepercayaan pada asumsi Anda.
Yang mengatakan, ada satu kasus di mana saya akan mengaktifkan pernyataan dalam produksi: Jika kita menemukan bug yang dapat direproduksi dalam produksi yang kita mengalami kesulitan mereproduksi dalam lingkungan pengujian, mungkin membantu untuk mereproduksi bug dengan pernyataan diaktifkan. dalam produksi, untuk melihat apakah mereka memberikan informasi yang bermanfaat.
Pertanyaan yang lebih menarik adalah ini: Dalam fase pengujian Anda, kapan Anda mematikan pernyataan?
sumber
Pernyataan tidak boleh berada dalam kode produksi. Jika pernyataan tertentu sepertinya bermanfaat dalam kode produksi, maka itu tidak boleh menjadi pernyataan; itu harus menjadi run time error cek, yaitu sesuatu kode seperti ini:
if( condition != expected ) throw exception
.Istilah 'pernyataan' berarti "pemeriksaan waktu pengembangan saja yang tidak akan dilakukan di lapangan."
Jika Anda mulai berpikir bahwa pernyataan mungkin akan sampai ke lapangan, maka Anda juga akan mulai membuat pikiran berbahaya lainnya, seperti bertanya-tanya apakah pernyataan yang diberikan benar-benar layak dibuat. Tidak ada pernyataan yang tidak layak dibuat. Anda seharusnya tidak pernah bertanya pada diri sendiri "haruskah saya menyatakan ini atau tidak?" Anda seharusnya hanya bertanya pada diri sendiri, "Adakah yang saya lupa nyatakan?"
sumber
Kecuali jika profiling menunjukkan bahwa pernyataan tersebut menyebabkan masalah kinerja, saya katakan mereka juga harus tetap dalam rilis produksi.
Namun, saya pikir ini juga mengharuskan Anda menangani kegagalan pernyataan dengan anggun. Sebagai contoh, mereka harus menghasilkan jenis dialog umum dengan opsi (secara otomatis) melaporkan masalah kepada pengembang, dan tidak hanya berhenti atau crash program. Selain itu, Anda harus berhati-hati untuk tidak menggunakan pernyataan untuk kondisi yang sebenarnya Anda izinkan, tetapi mungkin tidak suka atau menganggap tidak diinginkan. Ketentuan tersebut harus ditangani oleh bagian lain dari kode.
sumber
Dalam C ++ saya, saya mendefinisikan REQUIRE (x) yang seperti menegaskan (x) kecuali bahwa itu melempar pengecualian jika pernyataan gagal dalam membangun rilis.
Karena pernyataan yang gagal menunjukkan bug, itu harus diperlakukan dengan serius bahkan dalam rilis Rilis. Ketika masalah kinerja kode saya, saya akan sering menggunakan REQUIRE () untuk kode tingkat lebih tinggi dan menegaskan () untuk kode tingkat lebih rendah yang harus berjalan cepat. Saya juga menggunakan REQUIRE alih-alih menegaskan apakah kondisi kegagalan mungkin disebabkan oleh data yang dikirimkan dari kode yang ditulis oleh pihak ketiga, atau oleh file korupsi (secara optimal saya akan merancang kode secara khusus untuk berperilaku baik dalam kasus korupsi file, tetapi kami tidak selalu punya waktu untuk melakukan itu.)
Mereka mengatakan Anda tidak harus menunjukkan pesan tegas kepada pengguna akhir karena mereka tidak akan memahaminya. Begitu? Pengguna akhir dapat mengirimi Anda email dengan tangkapan layar atau teks pesan kesalahan, yang membantu Anda melakukan debug. Jika pengguna hanya mengatakan "macet", Anda kurang memiliki kemampuan untuk memperbaikinya. Akan lebih baik untuk mengirim pesan kegagalan pernyataan ke diri Anda secara otomatis melalui internet, tetapi itu hanya berfungsi jika pengguna memiliki akses internet dan Anda bisa mendapatkan izin mereka.
sumber
Jika Anda ingin menyimpannya ganti dengan penanganan kesalahan. Tidak ada yang lebih buruk dari sebuah program yang hilang begitu saja. Saya melihat tidak ada yang salah dengan memperlakukan kesalahan tertentu sebagai bug serius, tetapi mereka harus diarahkan ke bagian program Anda yang dilengkapi untuk menanganinya dengan mengumpulkan data, mencatatnya, dan memberi tahu pengguna bahwa aplikasi Anda memiliki beberapa kondisi yang tidak diinginkan dan keluar.
sumber
Asalkan mereka ditangani sama seperti kesalahan lainnya, saya tidak melihat masalah dengan itu. Ingatlah bahwa pernyataan gagal dalam C, seperti bahasa lain, hanya akan keluar dari program, dan ini biasanya tidak cukup untuk sistem produksi.
Ada beberapa pengecualian - PHP, misalnya, memungkinkan Anda membuat custom handler untuk kegagalan asersi sehingga Anda dapat menampilkan kesalahan khusus, melakukan pendataan terperinci, dll. Bukan hanya keluar.
sumber
Perangkat lunak server database kami berisi pernyataan produksi dan debug. Pernyataan debug hanya bahwa - mereka dihapus dalam kode produksi. Pernyataan produksi hanya terjadi jika (a) ada kondisi yang seharusnya tidak pernah ada dan (b) tidak mungkin untuk pulih dari kondisi ini secara andal. Pernyataan produksi menunjukkan bahwa bug dalam perangkat lunak telah ditemukan atau beberapa jenis korupsi data telah terjadi.
Karena ini adalah sistem basis data dan kami menyimpan data yang berpotensi penting perusahaan, kami melakukan apa pun yang kami bisa untuk menghindari data yang rusak. Jika ada kondisi yang dapat menyebabkan kami menyimpan data yang salah, kami segera menegaskan, mengembalikan semua transaksi, dan menghentikan server.
Karena itu, kami juga mencoba untuk menghindari pernyataan produksi dalam rutinitas kritis kinerja.
sumber
Saya melihat menegaskan sebagai tes unit in-line. Berguna untuk tes cepat saat berkembang, tetapi pada akhirnya pernyataan tersebut harus di refactored untuk diuji secara eksternal dalam unit test.
sumber
Saya menemukan yang terbaik untuk menangani semua kesalahan yang ada dalam ruang lingkup, dan menggunakan pernyataan untuk asumsi yang kami nyatakan BENAR.
yaitu, jika program Anda membuka / membaca / menutup file, maka tidak dapat membuka file dalam ruang lingkup - itu kemungkinan nyata, yang akan lalai untuk diabaikan, dengan kata lain. Jadi, kode kesalahan pengecekan harus dikaitkan dengannya.
Namun, misalkan fopen Anda () didokumentasikan sebagai selalu mengembalikan pegangan file yang valid dan terbuka. Anda membuka file, dan meneruskannya ke fungsi readfile () Anda.
Fungsi readfile itu, dalam konteks ini, dan mungkin sesuai dengan spesifikasi desainnya, dapat mengasumsikan itu akan mendapatkan ptr file yang valid. Jadi, akan sia-sia menambahkan kode penanganan kesalahan untuk kasus negatif, dalam program yang begitu sederhana. Namun, paling tidak harus mendokumentasikan asumsi tersebut, entah bagaimana - memastikan entah bagaimana --- bahwa inilah yang sebenarnya terjadi, sebelum melanjutkan eksekusi. Seharusnya tidak SEPENUHNYA berasumsi bahwa akan selalu valid, jika itu disebut salah, atau itu disalin / ditempelkan ke beberapa program lain, misalnya.
Jadi, readfile () {assert (fptr! = NULL); ..} sesuai dalam kasus ini, sementara penanganan kesalahan secara penuh tidak (mengabaikan fakta bahwa sebenarnya membaca file akan memerlukan beberapa sistem penanganan kesalahan).
Dan ya, pernyataan itu harus tetap dalam kode produksi, kecuali jika benar-benar diperlukan untuk menonaktifkannya. Meskipun begitu, Anda mungkin harus menonaktifkannya hanya di dalam bagian yang kritis-kinerja.
sumber
Misalkan sepotong kode dalam produksi, dan itu mengenai pernyataan yang biasanya dipicu. Penegasan telah menemukan bug! Kecuali belum, karena pernyataannya dimatikan.
Jadi apa yang terjadi sekarang? Entah program akan (1) macet dalam cara yang tidak informatif pada suatu titik lebih lanjut dihapus dari sumber masalah, atau (2) berjalan dengan riang sampai selesai, kemungkinan memberikan hasil yang salah.
Skenario tidak mengundang. Biarkan pernyataan aktif bahkan dalam produksi.
sumber
Saya jarang menggunakan pernyataan untuk hal lain yang menyusun pemeriksaan tipe waktu. Saya akan menggunakan pengecualian alih-alih penegasan hanya karena sebagian besar bahasa dibuat untuk menanganinya.
Saya menawarkan sebuah contoh
melawan
Bagaimana cara aplikasi menangani pernyataan? Saya lebih suka
try catch
metode lama dalam menangani kesalahan fatal.sumber
Sebagian besar waktu, ketika saya menggunakan pernyataan di java (kata kunci yang menegaskan) saya secara otomatis menambahkan beberapa kode produksi setelah. Menurut kasus ini, itu bisa berupa pesan logging, pengecualian ... atau tidak sama sekali.
Menurut saya, semua pernyataan Anda sangat penting dalam rilis dev, bukan pada relase produksi. Beberapa dari mereka harus disimpan, yang lain harus dibuang.
sumber
ASSERTIONS bukan kesalahan dan tidak boleh ditangani sebagai kesalahan. Ketika pernyataan dilemparkan, ini berarti ada bug dalam kode Anda atau sebagai alternatif dalam kode yang memanggil kode Anda.
Ada beberapa poin untuk menghindari mengaktifkan pernyataan dalam kode produksi: 1. Anda tidak ingin pengguna akhir Anda melihat pesan seperti "ASSERTION gagal MyPrivateClass.cpp baris 147. Pengguna akhir BUKAN Anda insinyur QA. 2. ASSERTION mungkin mempengaruhi kinerja
Namun, ada satu alasan kuat untuk meninggalkan pernyataan: ASSERTION dapat memengaruhi kinerja dan waktu, dan sayangnya hal ini terkadang penting (terutama di sistem embedded).
Saya cenderung memilih untuk meninggalkan pernyataan dalam kode produksi tetapi memastikan bahwa pernyataan ini dicetak tidak terkena pengguna akhir.
~ Yitzik
sumber
Pernyataan adalah kesalahan, murni dan sederhana dan karenanya harus ditangani seperti itu.
Karena kesalahan harus ditangani dalam mode rilis maka Anda tidak benar-benar membutuhkan pernyataan.
Manfaat utama yang saya lihat untuk pernyataan adalah istirahat bersyarat - mereka jauh lebih mudah untuk diatur daripada menelusuri melalui jendela VC untuk mengatur sesuatu yang membutuhkan 1 baris kode.
sumber