0

私が参加した最近のいくつかのプロジェクトでは、次のコーディング パターンにはまっています: (これに適切な名前があるかどうかはわかりませんが、とにかく...)

あるオブジェクトが何らかの決定された状態にあり、この状態を外部から変更したくないとしましょう。これらの変更は、任意の動作を意味し、任意のアルゴリズムを呼び出す可能性がありますが、実際には、オブジェクトの状態(メンバー状態、データ状態など)の変更に焦点を当てています。

そして、これらのオブジェクトを変更する 1 つの個別の方法を a と呼びましょうMutatorMutatorsは一度(一般的に)適用され、のような内部メソッドがapply(Target& target, ...)あり、オブジェクトの状態の変更を即座に引き起こします(実際、それらはある種の機能オブジェクトです)。

また、チェーンに簡単に同化して、1 つずつ適用することもできます ( Mutator m1, m2, ...)。BasicMutatorまた、いくつかの基本的なwithvirtual void apply(...)メソッドから派生させることもできます。

アクセスの点で異なる と というクラスを紹介しました。まず、オブジェクトの内部状態を変更することもできInnerMutator、フレンド( )として宣言する必要があります。ExplicitMutatorfriend InnerMutator::access;


これらのプロジェクトでは、私のロジックは次のように機能するようになりました。

  1. 利用可能なミューテーターを準備し、適用するものを選択します
  2. を作成し、object特定の状態に設定します
  3. foreach (mutator) mutator.apply(object);

今質問です。

このスキームはうまく機能するようになり、 (私には)非標準だが有用な設計パターンのサンプルのように思えます。

私が不快に感じるのはそのようなInnerMutatorものです。状態を変更できるすべてのオブジェクトに対してミューテーターをフレンドとして宣言することは良い考えではないと思います。また、適切な代替手段を見つけたくありません。

この状況は解決できますか、Mutatorsそれとも同じ結果になる別のパターンをアドバイスしてもらえますか?

ありがとう。

4

2 に答える 2

5

これが攻撃的に受け止められないことを願っていますが、この設計はかなり単純な問題に対する過度に派手な解決策だと思わずにはいられません。

たとえば、ミューテーターを集約する必要があるのはなぜですか? 単に書くことができます:

template <class T>
void mutate(T& t)
{
    t.mutate1(...);
    t.mutate2(...);
    t.mutate3(...);
}

集計ミューテーターがありますが、それは、1 つのスーパーミューテーターを作成するミューテーターの組み合わせリストではなく、静的ポリモーフィズムに依存する単純な関数テンプレートです。

私はかつて、かなり似ているかもしれない何かをしました。次のようなコードを記述できるように、演算子 && によって両方のオペランドを (左から右の順序で) 適用するスーパー関数オブジェクトに結合できる関数オブジェクトを作成しました。

foreach(v.begin(), v.end(), attack && burn && drain);

当時の私にとっては非常に素晴らしく、非常に賢いように見えました。また、新しい関数オブジェクトをオンザフライで生成する (ランタイム メカニズムが関与していない) ため、非常に効率的でしたが、同僚がそれを見たとき、私は正気ではないと思われました。振り返ってみると、私はすべてを関数型プログラミングに詰め込もうとしていましたが、これには有用性がありますが、おそらく C++ に過度に依存するべきではありません。書くのは簡単だったでしょう:

BOOST_FOR_EACH(Something& something, v)
{
    attack(something);
    burn(something);
    drain(something);
}

コードの行数が増えることは確かですが、一元化されてデバッグが容易であるという利点があり、私のコードで作業している他の人にエイリアンの概念を導入しません。コード行を強制的に削減しようとするよりも、厳密なロジックに集中する方がはるかに有益であることがわかりました。

このことについて深く考え、このミューテーターベースの設計がいかに巧妙でタイトであっても、このミューテーターベースの設計を継続する価値があるかどうかを真剣に検討することをお勧めします。他の人がそれをすぐに理解できない場合、ブースト作成者の権限がない限り、人々にそれを気に入ってもらうのは難しいでしょう.

InnerMutator に関しては、疫病のように避けるべきだと思います。ここで可能な限り直接クラスの内部を変更できる外部ミューテーター クラスを持つことは、内部を持つことの多くの目的をまったく無効にします。

于 2010-06-28T18:01:44.340 に答える
3

Mutatorそれらが変更しているクラスのメソッドを単純に作成する方が良いのではないでしょうか? 複数のクラスに持たせたい共通の機能がある場合、それらを同じ基本クラスから継承させてみませんか? これを行うことで、私が想像するすべての内部ミューテーターの不快感に対処できます。

変更をキューに入れたい場合は、それらをクラス内のメソッドへの関数呼び出しのセットとして保存できます。

于 2010-06-28T17:53:25.763 に答える