操作中にオブジェクトの内部状態を検証するために使用している手法に興味があります。オブジェクト自体の観点からは、内部状態が悪いか不変の違反が原因でのみ失敗する可能性があります。
私の主な焦点はC++です。これは、C#では例外をスローすることが公式で一般的な方法であり、C ++ではこれを行う方法が1つだけではないためです(C#でも実際にはそうではありません)。
私は関数パラメーターの検証について話しているのではなく、クラス不変の整合性チェックについて話していることに注意してください。
たとえば、Printer
オブジェクトをQueue
印刷ジョブに非同期的に送信したいとします。のユーザーにとってPrinter
、非同期キューの結果は別の時間に到着するため、その操作は成功するだけです。したがって、発信者に伝える関連のエラーコードはありません。
しかし、Printer
オブジェクトにとって、内部状態が悪い場合、つまりクラス不変条件が壊れている場合、この操作は失敗する可能性があります。これは基本的にバグを意味します。Printer
この条件は、オブジェクトのユーザーにとって必ずしも重要ではありません。
個人的には、3つのスタイルの内部状態検証を組み合わせる傾向があり、どれが最良であるかを実際に判断することはできません。どれが絶対に最悪であるかだけです。これらについてのご意見をお聞かせください。また、この件に関するご自身の経験や考えを共有していただきたいと思います。
私が使用する最初のスタイル-破損したデータよりも制御可能な方法で失敗する方が良いです:
void Printer::Queue(const PrintJob& job)
{
// Validate the state in both release and debug builds.
// Never proceed with the queuing in a bad state.
if(!IsValidState())
{
throw InvalidOperationException();
}
// Continue with queuing, parameter checking, etc.
// Internal state is guaranteed to be good.
}
私が使用する2番目のスタイル-破損したデータよりも制御不能なクラッシュの方が優れています:
void Printer::Queue(const PrintJob& job)
{
// Validate the state in debug builds only.
// Break into the debugger in debug builds.
// Always proceed with the queuing, also in a bad state.
DebugAssert(IsValidState());
// Continue with queuing, parameter checking, etc.
// Generally, behavior is now undefined, because of bad internal state.
// But, specifically, this often means an access violation when
// a NULL pointer is dereferenced, or something similar, and that crash will
// generate a dump file that can be used to find the error cause during
// testing before shipping the product.
}
私が使用する3番目のスタイル-破損したデータよりも静かにそして防御的に救済する方が良い:
void Printer::Queue(const PrintJob& job)
{
// Validate the state in both release and debug builds.
// Break into the debugger in debug builds.
// Never proceed with the queuing in a bad state.
// This object will likely never again succeed in queuing anything.
if(!IsValidState())
{
DebugBreak();
return;
}
// Continue with defenestration.
// Internal state is guaranteed to be good.
}
スタイルへの私のコメント:
- アクセス違反が実際にクラッシュを引き起こすという条件で、失敗が隠されていない2番目のスタイルを好むと思います。
- 不変条件に関係するNULLポインターでない場合、私は最初のスタイルに傾く傾向があります。
- 3番目のスタイルは多くのバグを隠すので本当に嫌いですが、クラッシュしない堅牢なソフトウェアのような錯覚を引き起こすため、本番コードでそれを好む人は知っています(機能は機能を停止するだけです)。壊れた
Printer
オブジェクトのキューイング)。
これらのいずれかを好みますか、それともこれを達成する他の方法がありますか?