In un nuovo lavoro, sono stato segnalato nelle recensioni di codice per codice come questo:
PowerManager::PowerManager(IMsgSender* msgSender)
: msgSender_(msgSender) { }
void PowerManager::SignalShutdown()
{
msgSender_->sendMsg("shutdown()");
}
Mi è stato detto che l'ultimo metodo dovrebbe leggere:
void PowerManager::SignalShutdown()
{
if (msgSender_) {
msgSender_->sendMsg("shutdown()");
}
}
vale a dire, mi deve mettere una NULL
guardia attorno alla msgSender_
variabile, anche se è un membro di dati privati. È difficile per me trattenermi dall'usare le imprecazioni per descrivere cosa provo per questo pezzo di "saggezza". Quando chiedo una spiegazione, ricevo una litania di storie dell'orrore su come un programmatore junior, qualche anno, si è confuso su come avrebbe dovuto funzionare una classe e cancellato accidentalmente un membro che non avrebbe dovuto (e lo ha impostato in NULL
seguito , a quanto pare), e le cose sono esplose sul campo subito dopo il rilascio di un prodotto, e abbiamo "imparato nel modo più duro, fidati di noi" che è meglio NULL
controllare tutto .
Per me, sembra una programmazione di culto del carico , chiara e semplice. Alcuni colleghi ben intenzionati stanno seriamente cercando di aiutarmi a "ottenerlo" e vedere come questo mi aiuterà a scrivere codice più robusto, ma ... Non posso fare a meno di sentirli come quelli che non lo capiscono .
È ragionevole che uno standard di codifica richieda che ogni singolo puntatore con riferimento a una funzione sia controllato per NULL
primo, anche per i membri di dati privati? (Nota: per dare un po 'di contesto, realizziamo un dispositivo elettronico di consumo, non un sistema di controllo del traffico aereo o qualche altro prodotto "fail-egals-people-die".)
EDIT : nell'esempio sopra, il msgSender_
collaboratore non è facoltativo. Se mai NULL
, indica un bug. L'unico motivo per cui viene passato nel costruttore è quindi PowerManager
può essere testato con una IMsgSender
sottoclasse finta .
SINTESI : Ci sono state delle risposte davvero fantastiche a questa domanda, grazie a tutti. Ho accettato quello di @aaronps principalmente per la sua brevità. Sembra esserci un accordo generale abbastanza ampio sul fatto che:
- Il mandato di
NULL
guardia per ogni singolo puntatore senza riferimenti è eccessivo, ma - Puoi fare un passo laterale dell'intero dibattito usando invece un riferimento (se possibile) o un
const
puntatore e assert
le dichiarazioni sono un'alternativa più illuminata alleNULL
guardie per verificare che siano soddisfatte le condizioni preliminari di una funzione.
null
e non fare nulla è solo un modo per spostare il bug sull'esecuzione, rendendo molto più difficile rintracciare la fonte.