これは確かに主観的な問題ですが、議論にならないようにしたいと思います。人々が適切に扱えば、興味深い質問になると思います。
最近のいくつかのプロジェクトでは、長い委任チェーンが一般的であるアーキテクチャを実装していました。
二重委任チェーンは頻繁に発生します。
bool Exists = Env->FileSystem->FileExists( "foo.txt" );
そして、三重委任は決して珍しいことではありません。
Env->Renderer->GetCanvas()->TextStr( ... );
より高次の委任チェーンは存在しますが、実際には稀です。
上記の例では、使用されるオブジェクトは常に存在し、プログラムの機能に不可欠であり、実行開始時に明示的に構築されるため、NULL ランタイム チェックは実行されません。基本的に、次のような場合に委任チェーンを分割していました。
1)委任チェーンを通じて取得したオブジェクトを再利用します。
{ // make C invisible to the parent scope
clCanvas* C = Env->Renderer->GetCanvas();
C->TextStr( ... );
C->TextStr( ... );
C->TextStr( ... );
}
2)委任チェーンの途中にある中間オブジェクトは、使用前に NULL かどうかチェックする必要があります。例:
clCanvas* C = Env->Renderer->GetCanvas();
if ( C ) C->TextStr( ... );
私は、結果につながる非 NULL オブジェクトでメソッドを呼び出すことができるようにプロキシ オブジェクトを提供することで、ケース (2) に対処していましたempty
。
私の質問は次のとおりです:
- (1) または (2) のどちらの場合もパターンですか、それともアンチパターンですか?
- C++ で長い委任チェーンを処理するより良い方法はありますか?
私が選択する際に考慮した長所と短所は次のとおりです。
長所:
- 非常に説明的である。1行のコードから、オブジェクトがどこから来たのかが明らかである。
- 長い委任チェーンは見栄えが良い
短所:
- 委任チェーン内の複数の一時オブジェクトを検査することが難しいため、対話型デバッグは困難です。
長い委任チェーンのその他の長所と短所を知りたいです。意見にどれだけ同意するかではなく、意見がどれだけ説得力があるかに基づいて、理由を示して投票してください。
ベストアンサー1
どちらもアンチパターンと呼ぶほどではありません。ただし、最初の方法には、変数がC
論理的に関連した後でも表示されるという欠点があります (スコープが不必要すぎる)。
次の構文を使用するとこれを回避できます:
if (clCanvas* C = Env->Renderer->GetCanvas()) {
C->TextStr( ... );
/* some more things with C */
}
これは C++ では許可されていますが (C では許可されていません)、適切なスコープ (条件ブロック内にあるかのようにスコープが設定されます) を維持しC
、NULL をチェックすることができます。
何かが NULL ではないことをアサートすることは、SegFault によって強制終了されるよりは絶対に良いことです。したがって、そのポインタが絶対に NULL にならないことを 100% 確信している場合を除き、これらのチェックを単にスキップすることはお勧めしません。
さらに、特に気合が入っている場合は、チェックを追加の無料関数にカプセル化することもできます。
template <typename T>
T notNULL(T value) {
assert(value);
return value;
}
// e.g.
notNULL(notNULL(Env)->Renderer->GetCanvas())->TextStr();