2

私は現在、.Net Framework 2.0 の C# で古い VB6 プログラムを書き直しています (私の選択ではなく、会社によって決定されました)。ほとんどの場合、物事はかなりうまくいっています。このプログラムは、精密研削盤から受信したデータを測定し、グラフとダイヤルを表示して精度を表示します。

元のプログラマーは機械エンジニアでしたが、ソフトウェア エンジニアではありませんでした。プログラムは動作しますが、あちこちにずさんなコードがあります。最も注目すべきは、いくつかの GoTo ステートメントに出くわしたことです。必要に応じてループに入れ、そこから同じ機能を取得するのは非常に簡単です。

ただし、元のコードで、GoTo がループをシミュレートする以上のことを行っているように見えるケースに遭遇しました。いくつかの異なる終了条件があります。これは次のようになります (実際のコードではなく、デモ用に作成した短いコードです):

VB6 コード

Public Sub Tick()
    Dim condition1 As Boolean
    Dim condition2 As Boolean
    Dim testNumber As Integer

    beginning:    'The GoTo label'

    ' (... Some Other Code Here ...)'

    If condition1 = True Then
        goto beginning
    Else
        ' (... Do some calculation ...)'
    End If

    If condition2 = True Then
        ' (... Do some calculation ...)'
        goto beginning
    End If

    Select Case testNumber
        Case 1: '(... Some code ...)'
        Case 2: '(... Some code ...)'
        Case 3: '(... Some code ...)'
        Case 4: goto beginning
    End Select
End Sub

実際のコードにはそれよりも条件が少ないかもしれませんが、基本的な考え方は、それ自体にループバックする原因となるいくつかの異なるものがあるということです。そのような状況でループを記述する良い方法はありますか、それとも goto ステートメントが受け入れられるケースですか? (確かに、非 goto ソリューションが望ましいでしょう)。

お時間をいただきありがとうございます。

注: ブレーク付きの while(true) ループを使用してみました。ステートメントを実行しましたが、プログラムが無限ループに陥り、ロックアップしました。複数の条件 (and/or など) を含む長い while ループを作成することをお勧めしますか?

4

6 に答える 6

6

ループの最後で、以前にgotoがあった場所while(true)で休憩があれば、ループは問題ないはずです。continueただし、これは間違いなく最初のステップにすぎないはずです。積極的なリファクタリングが求められているようです。

于 2010-07-07T15:27:31.083 に答える
1

そのループの本体を別の関数に配置することから始め、gotosを `return'sに置き換えます-またはおそらくいくつかの別の関数:

If condition1 = True Then 
    goto beginning 
Else 
    ' (... Do some calculation ...)' 
End If 

になる必要があります

If not condition1
      DoSomeCalculation()
End If

すぐに、いつループするか、いつ終了するかについてのロジックが明らかになります。その場合、このコードのリファクタリングは、これまでに行ったことと同じくらい簡単になるはずです。

于 2010-07-07T15:32:30.863 に答える
1

このケースは do/while true ループには十分に見えますが、そうでないケースもいくつか見てきました。

lexer やその他の FSA メカニズム以外では、2000 行に複数の goto がある場合は、何か間違ったことをしていると判断します。

もちろん、goto を持つ反復イディオムがある場合は、反復イディオムがスタイル ルールをオーバーライドするため、これは別の話です。イディオム = 一貫性がある、一貫性がある = 読みやすい。

于 2010-07-07T15:39:15.900 に答える
1

switch ステートメントで:

switch (groupMembershipStatus)
{
    case SocialGroupMembershipStatus.Banned:
        return redirect();
    case SocialGroupMembershipStatus.MembershipRequestDenied:
        Abc();
        goto case SocialGroupMembershipStatus.Banned;
}   

(ご覧のとおり、本番コードで goto を作成したばかりで、この goto の使用について C# で質問があるかどうか疑問に思っていました!)

于 2010-07-13T18:31:43.780 に答える
1

'(do some code)'最初のステップは、すべてを独自のメソッドに抽出することだと思います。これが完了すると、実際のコード フローが少し明確になります。

ネストの程度に応じて、これを実現する方法がいくつかあります (実際のコードがないと難しい)。

(私は C# コーダーです。VB はわかりません。ご容赦ください)

再帰的

Public Sub Tick()
    Dim condition1 As Boolean
    Dim condition2 As Boolean
    Dim testNumber As Integer

    If basecase = True Then
       return;
    EndIf

    ExecuteInitialzerStuff();

    If intialized = False Then
        Tick();
        return;
    Else
        ExecuteAffirmationStuff();
    End If

    If affirmed = True Then
        ExecutePostAffirm();
        Tick();
        return;
    End If

    Select Case testNumber
        Case 4: Tick();
    End Select
End Sub

別のオプションは、各オプションを個別のコードフローに分割することです

Public Sub Tick()
    Dim condition1 As Boolean
    Dim condition2 As Boolean
    Dim testNumber As Integer

    If condition1 = true Then
       Tick_Condition1();
       return;
    EndIf

    If condition2 = true Then
       Tick_Condition2();
       return;
    EndIf

    Tick_Switch(testNumber);

各コード セクションが達成しようとしている個別のタスクをそれぞれ分解すると、おそらく、このメソッドを完全に削除し、いくつかの個別の Tick() メソッドに分割して、それぞれを呼び出す必要があることが明らかになるはずですTickInit() TickDestroy(), TickSkyFalling();。状況によります。

この関数を適切にリファクタリングしようとするのは間違った決定だと思います。しかし、実際のコードを見ないとわかりません。

于 2010-07-07T15:44:12.090 に答える
0

それを単体テストでラップし、さまざまな値を実行して結果を記録します。

次に、コードを C# にリファクタリングすると、テストの結果を使用してアクションを検証できます。

于 2010-07-07T15:30:31.273 に答える