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 NULL
penjaga 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 NULL
setelah 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 NULL
memeriksa 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 NULL
terlebih 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 PowerManager
dapat diuji dengan IMsgSender
subkelas 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
NULL
penjaga untuk setiap pointer dereferenced tunggal adalah berlebihan, tetapi - Anda dapat memihak keseluruhan debat dengan menggunakan referensi sebagai gantinya (jika mungkin) atau sebuah
const
pointer, dan assert
pernyataan adalah alternatif yang lebih tercerahkan bagiNULL
penjaga untuk memverifikasi bahwa prasyarat fungsi terpenuhi.
null
dan tidak melakukan apa-apa hanyalah cara untuk memindahkan bug ke bawah eksekusi, sehingga jauh lebih sulit untuk melacak kembali ke sumbernya.