8

最近、私はレガシーvb.netコードに取り組んでおり、コードピアレビュー中に、Exit Sub / Functionを使用せず、代わりにIFステートメントにすべての機能をネストすることが推奨されました。

私が最初に開発を始めたとき、私は本能的にこの方法でそれを行っていました(Nest the IF)、それはより論理的に見えただけでなく、混乱が少ないように見えました。

ただし、ある時点で、ネストされたIFを「悪」として扱うチームと協力したため、Exit subs/functionsが優先されると言われました。これをバックアップするために、MSのベストプラクティス資料が作成されたと確信しています。

それで、この質問は経験豊富な開発者のためのものです、どちらの方法が本当に好ましいですか?あなたが答えを与えるならば、あなたはまたあなたの情報源を述べてください、あるいはこれがあなたのチーム/会社/個人によって好まれる好みであると単に述べて、理由を与えてください。

前もって感謝します。

要求に応じて編集:コードサンプル

サブを終了:

Private Sub DoSomeWork()
 if not conditionMetFromAnotherFunction() then
      exit Sub 
 end if

 'Method work starts here
End Sub

ネストされたIF:

Private Sub DoSomeWork()
 if conditionMetFromAnotherFunction() then
     'Method work starts here
 end if
End Sub
4

6 に答える 6

22

関数を早期に終了しないと、コードが次のようになるポイントに到達します。

コードにつまずく

これが関数から早く戻るよりも良いスタイルだとは誰にも言えません。

于 2012-07-09T12:16:58.420 に答える
6

コードピアレビュー中は、Exit Sub / Functionを使用せず、代わりにすべての機能をIFステートメントにネストすることをお勧めします。

これは恐ろしいアドバイスです。それはそれと同じくらい簡単です。それを無視します。実際、特にネストされたインデントが必要な場合や、パラメーターの有効性を確認して早期に終了する可能性がある場合は、通常、反対のことが当てはまります。質問のコードはその良い例です。ここで早期終了を使用してください。

そのための「公式の」情報源はありませんが(公式なものは何でしょうか?)、これに反対するごく少数の少数派で、優れたプログラマーの間でほぼコンセンサスが得られています。これに関する詳細については、プログラマーに関する説明を参照してください。

Returnただし、の代わりに使用することをお勧めしExit {Sub|Function}ます。

于 2012-07-09T12:13:32.070 に答える
4

Davidがコメントで指摘したように、ネストされたifステートメントはコードの複雑さを増す可能性があります。

次の(簡略化された)コードを想像してみてください。

Private Sub DoSomeWork()
    if conditionMetFromAnotherFunction() then
        if conditionDependantUponPreviousCondition then
            ' Do the work
        end if
    end if
End Sub

または次の

Private Sub DoSomeWork()
    if not conditionMetFromAnotherFunction()
        return
    else if not conditionDependantUponPreviousCondition 
        return
    end if


    ' If we're here, everything's all good
    ' Do the work...
End Sub

条件がより複雑になった場合、戻ると、条件によってはコードが何も実行していないことを理解しやすくなり、コードが読みやすくなります。

それ以外の場合は、すべての関数を読み取り、ネストされたifを精神的に解析して、何も行われていないことを確認する必要があります。

于 2012-07-09T12:17:48.513 に答える
3

何でもそうですが、「状況によって異なります」。間違ったコンテキストで使用すると、どちらかが不快になる可能性があります。

たとえば、何をconditionMetFromAnotherFunction()チェックしていますか?ある種の必要な前提条件をチェックしている場合DoSomeWork()は、関数を静かに終了するのではなく、例外を通過することさえあります。 ArgumentExceptionたとえば、関数に渡された引数の有効性をチェックする場合に役立ちます。システム内の何かが実際に間違っていた場合、静かに終了することは正しくないようです。

ネストされた条件の場合、それは間違いなく厄介です。関数は「1つのことを行う」必要があるという経験則を覚えておいてください。 その状態をチェックすることは一つのことです。したがって、その場合、'Method work starts hereは実際に作業を行う別のメソッドの呼び出しにすぎないはずです。1つの大きな条件ですべてがラップされたコードの行が多く ないようにする必要があります。また、関数名は、実行していることを正確に反映している必要があります。したがって、これはDoWorkIfConditional(考案された例では)であり、他の方法はですDoWork

関数が作業を行う前に前提条件を確認しても問題ありません。前提条件が満たされていない場合は、例外をスローすることを検討します。しかし、それはこの例では実際には伝えられていないアプリケーションの実際のロジックに依存します。

于 2012-07-09T12:17:21.000 に答える
2

このトピックに関する良いまとめとして、ここで回答を読むことをお勧めします。

要約すると、関数への複数のエントリポイントを持つことができ、コード内の異なる位置に戻ることもできる言語で開発されたシングルエントリ/シングルエグジット。から戻ることができるコード内の1つのポイントのみを許可するものとして誤って解釈されています。

サブプログラムでreturn/exitステートメントを1つだけ使用する「ベストプラクティス」は、明示的なヒープ管理を備えた言語に由来します。この場合、サブプログラムのリソースはサブプログラムの最後で解放されるため、制御フローはそこを通過する必要があります。これは、.NETまたはJVMに基づく言語には適用されません。

全体として、複数のリターンの使用が許可されている場合、コードは通常、より読みやすくなります。

于 2012-07-09T12:16:31.777 に答える
1

IMOは、恐ろしいスパゲッティコードへの非常に迅速なルートである場合にネストされます。一般的に言えば、コードを深くネストしている場合は、メソッドで多くの作業を行おうとすると、より小さな部分にリファクタリングすることでメリットが得られる可能性があります。

とはいえ、避けられないこともあるので、すべてに当てはまる答えはありません。

于 2012-07-09T12:18:27.310 に答える