Di pekerjaan baru, saya telah ditandai dalam ulasan kode untuk kode seperti ini:
PowerManager::PowerManager(IMsgSender* msgSender)
: msgSender_(msgSender) { }
void PowerManager::SignalShutdown()
{
msgSender_->sendMsg("shutdown()");
}
Saya diberitahu bahwa metode terakhir harus membaca:
void PowerManager::SignalShutdown()
{
if (msgSender_) {
msgSender_->sendMsg("shutdown()");
}
}
yaitu, saya harus menempatkan NULLpenjaga di sekitar msgSender_variabel, meskipun anggota data yang pribadi. Sulit bagi saya untuk menahan diri dari menggunakan kata-kata kasar untuk menggambarkan bagaimana perasaan saya tentang 'kebijaksanaan' ini. Ketika saya meminta penjelasan, saya mendapatkan serangkaian cerita horor tentang bagaimana beberapa programmer junior, beberapa tahun, bingung tentang bagaimana kelas seharusnya bekerja dan secara tidak sengaja menghapus anggota yang tidak seharusnya (dan mengaturnya NULLsetelah itu , tampaknya), dan banyak hal meledak di lapangan tepat setelah rilis produk, dan kami telah "belajar dengan cara yang sulit, percayalah pada kami" bahwa lebih baik hanya NULLmemeriksa semuanya .
Bagi saya, ini terasa seperti pemrograman kultus kargo , sederhana dan sederhana. Beberapa kolega yang bermaksud baik sungguh-sungguh berusaha membantu saya 'mendapatkannya' dan melihat bagaimana ini akan membantu saya menulis kode yang lebih kuat, tetapi ... Saya tidak dapat menahan perasaan bahwa merekalah yang tidak mendapatkannya. .
Apakah masuk akal jika standar pengkodean mengharuskan setiap penunjuk tunggal yang direferensikan dalam suatu fungsi diperiksa NULLterlebih dahulu — bahkan anggota data pribadi? (Catatan: Untuk memberikan beberapa konteks, kami membuat perangkat elektronik konsumen, bukan sistem kontrol lalu lintas udara atau produk 'kegagalan-sama dengan orang-mati' lainnya.)
EDIT : Pada contoh di atas, msgSender_kolaborator bukan opsional. Jika pernah NULL, ini menunjukkan bug. Satu-satunya alasan ia dilewatkan ke konstruktor adalah agar PowerManagerdapat diuji dengan IMsgSendersubkelas tiruan .
RINGKASAN : Ada beberapa jawaban yang sangat bagus untuk pertanyaan ini, terima kasih semuanya. Saya menerima yang dari @ aaronps terutama karena singkatnya. Tampaknya ada kesepakatan umum yang cukup luas bahwa:
- Mandat
NULLpenjaga untuk setiap pointer dereferenced tunggal adalah berlebihan, tetapi - Anda dapat memihak keseluruhan debat dengan menggunakan referensi sebagai gantinya (jika mungkin) atau sebuah
constpointer, dan assertpernyataan adalah alternatif yang lebih tercerahkan bagiNULLpenjaga untuk memverifikasi bahwa prasyarat fungsi terpenuhi.
nulldan tidak melakukan apa-apa hanyalah cara untuk memindahkan bug ke bawah eksekusi, sehingga jauh lebih sulit untuk melacak kembali ke sumbernya.