1

サーバーのチェーンに沿ったメッセージフローを表すモデルプログラムがあります。

public class MyModel
{
    static bool x_send_msg1 = false; // has X sent msg1?
    static bool y_recv_msg1 = false; // has Y received msg1?

    static bool y_send_msg1 = false; // has Y sent msg1?
    static bool z_send_msg1 = false; // has Z received msg1?

    // (etc for more servers and more messages)

    [Action]
    static void YSendMsg1()
    {
       // Y sends Msg1 to Z
       y_send_msg1 = true;
       z_recv_msg1 = true;
    }
    static bool YSendMsg1Enabled()
    {
       // in the simplest case, this can happen whenever Y has received the
       // message but not yet forwarded it
       return y_recv_msg1 && !y_send_msg1;
    }

}

もっとたくさんのメッセージがあります。各サーバーとメッセージタイプのEnabled()ロジックは少し異なりますが、状態は似ているので、次のように記述してカプセル化します。

class State
{
    public bool send_msg1 = false;
    public bool recv_msg1 = false;
}
public static State X = new State();
public static State Y = new State();

次に、カプセル化された状態をアクションで使用します。

[Action]
static void YSendMsg1()
{
  // instead of y_qqq above, now we can write Y.qqq:
   Y.send_msg1 = true;
   Z.recv_msg1 = true;
}
static bool YSendMsg1Enabled()
{
   return Y.recv_msg1 && !Y.send_msg1;
}

ただし、NModelでは、この方法でオブジェクトを使用して状態を保持することはできません。チェーン内のサーバーごとに1つずつ、ブール値の繰り返しグループを定義することを回避できる他の方法はありますか?

4

3 に答える 3

2

スタイルの質問はさておき、質問に示されているように状態をカプセル化することの主な利点は、記述および読み取りが必要なコードの量を減らすことです。(#servers * #messages)宣言を記述する代わりに、(#server + #messages)のみが必要です。

SetNModelの組み込みクラスを使用して各メッセージの状態を追跡することにより、同じコードの削減(対応する可読性の向上と手根管症候群の削減)を実現できます。と呼ばれるセットsend_msg1には、送信したすべてのサーバーの名前が含まれていますmsg1

public class MyModel
{
    static set<int> send_msg1 = set<int>.EmptySet; // has server #n sent msg #1?
    static set<int> recv_msg1 = set<int>.EmptySet; // has server #n received msg #1?
    // (etc for more messages)

    static int X = 1;
    static int Y = 2;
    // (etc for more server names)

    [Action]
    static void YSendMsg1()
    {
       // Y sends Msg1 to Z
       send_msg1 = send_msg1.Add(Y);
       recv_msg1 = recv_msg1.Add(Z);
    }
    static bool YSendMsg1Enabled()
    {
       // in the simplest case, this can happen whenever Y has received the
       // message but not yet forwarded it
       return recv_msg1.Contains(Y) && !send_msg1.Contains(Y);
    }

}

(たとえば、セットのマップを使用してすべてを単一の変数に保持することにより、コードイベントの量をさらに減らすことができます。ただし、状態を空間的に分離したままにすることの利点の1つは、モデルビューアーでより読みやすい状態の要約を生成することです。 。)

于 2009-12-18T19:38:33.250 に答える
1

上記の答えを書いて以来、私は当初探していたものに近い別の解決策を学びました。

LabeledInstanceインスタンス変数を持つオブジェクトを使用するには、以下に示すように派生することができます。インスタンスは静的Create()メソッドを使用して割り当てられ、フィールドはオーバーライドされたInitialize()メソッドで初期化される必要があります。

(アクションにインスタンスメソッドを使用することもできますが、そのためには、クラスにドメインを割り当てる必要があります。そのドメインの名前は、クラスの現在のすべてのインスタンスを含む静的セットに対応している必要があります。)

舞台裏では、NModelはこのクラスを、クラス内のインスタンス変数ごとに1つずつ、一連​​のマップに変換します。これらのマップへのキーは、クラス名のインデックス付きインスタンスになりますState(1)。これはMVCツール内で読むのがやや難しい場合があるため、オブジェクトの状態の読みやすい統合された要約を含む、ある種のインスタンス変数を保持することもできます。

class State : LabeledInstance<State>
{ 
    public override void Initialize()
    {
        send_msg1 = false;
        recv_msg1 = false;
    }
    public bool send_msg1;
    public bool recv_msg1;
} 

public static State X = State.Create();
public static State Y = State.Create();
于 2010-01-14T20:20:48.997 に答える
0

オブザーバーパターンがここで役立つと思います-http ://www.dofactory.com/Patterns/PatternObserver.aspx

于 2009-12-17T12:55:07.370 に答える