C++ の長い委任チェーン 質問する

C++ の長い委任チェーン 質問する

これは確かに主観的な問題ですが、議論にならないようにしたいと思います。人々が適切に扱えば、興味深い質問になると思います。

最近のいくつかのプロジェクトでは、長い委任チェーンが一般的であるアーキテクチャを実装していました。

二重委任チェーンは頻繁に発生します。

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. (1) または (2) のどちらの場合もパターンですか、それともアンチパターンですか?
  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();

おすすめ記事