新しい仕事で、次のようなコードのコードレビューでフラグを立てられました。
PowerManager::PowerManager(IMsgSender* msgSender)
: msgSender_(msgSender) { }
void PowerManager::SignalShutdown()
{
msgSender_->sendMsg("shutdown()");
}
最後のメソッドは次のように読むべきだと言われています:
void PowerManager::SignalShutdown()
{
if (msgSender_) {
msgSender_->sendMsg("shutdown()");
}
}
つまり、変数がプライベートデータメンバーであっても、変数をガードする必要があります。この「知恵」についてどのように感じているかを説明するためにexp辞を使うのを抑えるのは難しいです。説明を求めると、ある年のジュニアプログラマーがクラスがどのように機能するかについて混乱し、必要のないメンバーを誤って削除した(そしてその後に設定する)ことについてのホラーストーリーを大量に受け取ります、どうやら)、そして製品リリース直後に現場で物事が爆発しました。すべてをチェックする方が良いという「難しい方法を学び、信頼してください」。NULL
msgSender_
NULL
NULL
私にとって、これは貨物カルトのプログラミングのように感じます。いくつかの善意の同僚は、私が「それを得る」のを助け、これが私がより堅牢なコードを書くのにどのように役立つかを真剣に助けようとしていますが、...私は彼らがそれを手に入れていないように感じるのを助けることができません。
コーディング標準では、関数内で間接参照されているすべてのポインターをNULL
最初にチェックすることを要求するのは妥当ですか?プライベートデータメンバーであっても?(注:コンテキストを提供するために、航空交通管制システムやその他の「障害と同等の人々が死ぬ」製品ではなく、家電製品を製造しています。)
編集:上記の例では、msgSender_
共同編集者はオプションではありません。これまでNULL
に発生した場合は、バグを示しています。コンストラクターに渡される唯一の理由はPowerManager
、モックIMsgSender
サブクラスでテストできることです。
要約:この質問には本当に素晴らしい回答がいくつかありました。みなさんありがとう。私は主にその簡潔さのために@aaronpsからのものを受け入れました。以下のかなり一般的な合意があるようです。
- すべての間接参照されたポインタに
NULL
ガードを強制するのはやり過ぎですが、 - 代わりに参照(可能な場合)または
const
ポインターを使用して、議論全体を回避できます。 assert
ステートメントは、NULL
関数の前提条件が満たされていることを検証するための、ガードに対するより賢明な代替手段です。
null
て何もしないことは、バグを実行に移すだけの方法であり、ソースに戻るのをはるかに困難にします。