Bei einem neuen Job wurde ich in Code-Reviews für Code wie diesen markiert:
PowerManager::PowerManager(IMsgSender* msgSender)
: msgSender_(msgSender) { }
void PowerManager::SignalShutdown()
{
msgSender_->sendMsg("shutdown()");
}
Mir wurde gesagt, dass die letzte Methode lauten sollte:
void PowerManager::SignalShutdown()
{
if (msgSender_) {
msgSender_->sendMsg("shutdown()");
}
}
dh ich muss einen setzen NULL
Wache rund um die msgSender_
Variable, auch wenn es ein privates Daten Mitglied ist. Es fällt mir schwer, mich davon abzuhalten, mit Sprengsätzen zu beschreiben, wie ich über dieses Stück „Weisheit“ stehe. Wenn ich nach einer Erklärung frage, bekomme ich eine ganze Reihe von Horrorgeschichten darüber, wie ein Junior-Programmierer eines Jahres verwirrt darüber wurde, wie eine Klasse funktionieren sollte, und löschte versehentlich ein Mitglied, das er nicht haben sollte (und setzte es NULL
danach auf (anscheinend) und die Dinge explodierten gleich nach einer Produktveröffentlichung, und wir haben "auf die harte Tour gelernt, vertraue uns", dass es besser ist, einfach alles zu NULL
überprüfen .
Für mich fühlt sich das schlicht und einfach nach Frachtkult-Programmierung an . Ein paar wohlmeinende Kollegen versuchen ernsthaft, mir zu helfen, es zu verstehen und zu sehen, wie mir das helfen wird, robusteren Code zu schreiben, aber ... ich kann nicht anders, als mich zu fühlen, als wären sie diejenigen, die es nicht verstehen .
Ist es für einen Codierungsstandard sinnvoll, zu verlangen, dass jeder einzelne Zeiger, der in einer Funktion dereferenziert wird, NULL
zuerst auf private Datenelemente überprüft wird ? (Hinweis: Um einen gewissen Zusammenhang zu schaffen, stellen wir ein Unterhaltungselektronikgerät her, kein Flugsicherungssystem oder ein anderes Produkt, das dem Menschen gleichkommt.)
BEARBEITEN : Im obigen Beispiel ist der msgSender_
Mitbearbeiter nicht optional. Wenn es jemals ist NULL
, zeigt es einen Fehler an. Der einzige Grund, warum es an den Konstruktor übergeben wird, besteht darin, dass PowerManager
es mit einer Scheinunterklasse getestet werden kann IMsgSender
.
ZUSAMMENFASSUNG : Es gab einige wirklich gute Antworten auf diese Frage, danke an alle. Ich habe den von @aaronps hauptsächlich wegen seiner Kürze angenommen. Es scheint eine ziemlich breite allgemeine Übereinstimmung zu geben, dass:
- Mandatierung
NULL
Schutz für jeden einzelnen dereferenzierten Zeiger ist übertrieben, aber - Sie können die gesamte Debatte durch Verwenden einer Referenz (falls möglich) oder eines
const
Zeigers auslassen assert
Anweisungen sind eine aufschlussreichere Alternative zuNULL
Guards, um zu überprüfen, ob die Voraussetzungen für eine Funktion erfüllt sind.
null
und Nichtstun ist nur eine Möglichkeit, den Fehler während der Ausführung zu beheben, was es weitaus schwieriger macht, die Quelle zu finden.