4

さて、状況は次のとおりです。

ConnectionStateとConnectionSollStateの2つの設定を持つ1つのクライアントがあり、どちらも同じ列挙可能(TypeConnectionState)であり、クライアント接続の実際の状態と接続の状態を格納します。toのすべての組み合わせで、ConnectionStateが「Connected」であるがConnectionSollStateが「Closed」である場合など、何か異なることが発生するはずです->クライアントをティアダウンします。だから私は私がチェックしなければならない4つの可能性が好きです。これで、すべてのクライアントが無限の数のセッションを処理でき、すべてのセッションに状態(StreamStateおよびStreamSollState)もあり、これらの状態には列挙可能な6つのオプションがあります。

これから、私は20のスイッチ条件を作成していますが、コードは非常に乱雑に見えます。コーディング中は5分ごとに何か間違ったことをしています。このような状況を処理する簡単な方法はありますか?(if / else)事態を悪化させるでしょう。

例:

private void RTSPWorker() {
    try {
        byte[] buffer = new byte[2048];
        while (!mb_RTSPWorkerAbbort) {
        // Call TransportWD
            Thread.Sleep(100 * mi_ConnectionTimeOut);

            // Check ConnectionSollState
            switch(ConnectionSollState) {
                case TypeConnectionState.Connected:
                    // ConnectionSollState = Connected, check ConnectionState
                    switch(ConnectionState) {
                        case TypeConnectionState.Connected:
                            // ConnectionState is connected, keep-alive!
                            if(GET_PARAMETER() == null) {
                                DESCRIBE();
                            }
                            // Check streams too
                            foreach (cRTSPStream oStream in mo_StreamDict.Values) {
                                // Check StreamSollState
                                switch(oStream.RTSPStreamSollState) {
                                    case cRTSPStream.TypeRTSPStreamState.Play:
                                        // SollState is PLAY, check State
                                        switch(oStream.RTSPStreamState) {
                                            case cRTSPStream.TypeRTSPStreamState.Play:
                                                //Stream is alive, keep-alive!
                                                if (oStream.PLAY() == null) { oStream.DESCRIBE(); } break;
                                            case cRTSPStream.TypeRTSPStreamState.Closed:
                                                // Reinitialise.
                                                if (oStream.SETUP() != null) { oStream.PLAY(); } break;
                                            default:
                                                // Default, send play.
                                                oStream.PLAY(); break;
                                        }
                                    break;
                                case cRTSPStream.TypeRTSPStreamState.Pause:
                                    // SollState is on pause, check State
                                    switch(oStream.RTSPStreamState) {
                                        case cRTSPStream.TypeRTSPStreamState.Closed:
                                            // Reinitialise.
                                            if (oStream.SETUP() != null) { oStream.PLAY(); } break;
                                        default:
                                            oStream.PAUSE();
                                            break;
                                    }
                                break;
                                case cRTSPStream.TypeRTSPStreamState.Closed:
                                    // SollState is closed, check State
                                    switch(oStream.RTSPStreamState) {
                                        case cRTSPStream.TypeRTSPStreamState.Closed:
                                            // Is closed, do nothing
                                            break;
                                        default:
                                            // Default teardown, remove session
                                            oStream.TEARDOWN();
                                            this.RemoveRTSPSession(oStream);
                                            break;
                                        }
                                default:
                                    // Default, what do?
                                    break;
                                }
                            }
                            break;
                        case TypeConnectionState.Closed:
                            // ConnectionState should be connected, re-connect!
                                while(Connect() != true) {
                                    // Sleep for 200ms, try again
                                    Thread.Sleep(200);
                                }
                            break;
                        default:
                            // TODO anything else
                            break;
                    }
                    break;
                case TypeConnectionState.Closed:
                    // Check ConnectionState
                    switch(ConnectionState) {
                        case TypeConnectionState.Connected:
                            // Is connected, should be closed. Close connection & clean up!
                            Close(null);
                            break;
                        default:
                            // Anything other than Connected, do nothing.
                            break;
                    }
                    break;

                default:
                    break;
            }
        }
    } catch {

    }
}
4

3 に答える 3

9

聖なる煙、バットマン、それはあなたがそこに持っているいくつかの理解できないコードです。ここにあなたの状況を改善するかもしれないいくつかの秘訣があります。これらのヒントは、個人的なコーディングスタイルを好むため、多少偏っていることを付け加えなければなりません。

  1. switchステートメントをIFステートメントに書き直します。同じ結果を得るにはもう少しコードを記述する必要がありますが、ネストされたIFステートメントはネストされたswitchステートメントよりもはるかに読みやすくなっています。
  2. メソッドをいくつかのサブメソッドに分割します。あなたの方法は、おそらく同時に多くのことを行おうとしています。->関心の分離と単一責任の原則
  3. 改善された真理値表を使用します。変数の組み合わせに基づいて何らかの結果を生成するロジックがある状況では、真理値表の構成を使用することをお勧めします。たとえば、List<Tuple<T1,T2,T etc..>>構造を使用します。

元:

var truthTable = List<Tuple<NavigationTab, Role, Action>>
{
    new Tuple<NavigationTab, Role, Action>(NavigationTab.Users, Role.UsersAdministration, MVC.Administration.Users.Index()),
    new Tuple<NavigationTab, Role, Action>(NavigationTab.Users, Role.RolesAdministration, MVC.Administration.Roles.Index()),
    new Tuple<NavigationTab, Role, Action>(NavigationTab.Products, Role.ProductsAdministration, MVC.Administration.Products.Index()),
}
于 2012-09-04T13:16:51.380 に答える
1

一般に、オブジェクト指向の改善は、switchステートメントの最良の代替手段と見なされています。たとえば、switchステートメントの代わりにポリモーフィズムを使用して次のようにすることができます。

try {
    byte[] buffer = new byte[2048];
    while (!mb_RTSPWorkerAbbort) {
        Thread.Sleep(100 * mi_ConnectionTimeOut);
        worker.DoWork();
    }
 } catch (Exception ex) {
     Trace.WriteLine(ex);
 }

状態が変化すると、実装が異なるさまざまなタイプのワーカークラスをインスタンス化できますDoWork。1つは次のようになります。

while(Connect() != true) {
    // Sleep for 200ms, try again
    Thread.Sleep(200);
}

もちろん、私は必ずしもあなたがそれを正確にそのようにすべきだとは思いません。私が従わなければならないのは、あなたが投稿したコードだけです。したがって、さまざまな動作を実装するためのはるかに優れた方法がある可能性があります。

これは、仕様パターンと非常によく似ています。

于 2012-09-04T13:18:38.767 に答える
0

コードをより小さく、より管理しやすい部分に分割します。

caseステートメントでロジックを抽出すると、次のように、スイッチなしでメインループを書き換えることができます。

while (!mb_RTSPWorkerAbbort)
{
    // Call TransportWD
    Thread.Sleep(100*mi_ConnectionTimeOut);

    if (ConnectionSollState == TypeConnectionState.Closed)
    {
        CloseIfConnected();
    }

    if (ConnectionSollState == TypeConnectionState.Connected)
    {
        if (ConnectionState == TypeConnectionState.Connected)
        {
            KeepAlive();
            ProcessStreams(); // <--bad example name - rename to what it's actually doing.
        }
        else
        {
            Reconnect();
        }
    }
}

今から1か月後にこれを見ると(またはこのような場合はレビューが必要な場合)、何が起こっているのかを確認するのがはるかに簡単になります。

于 2012-09-04T14:03:07.393 に答える