読みやすさと効率性が失われるため、コーディングの悪い方法として単一の出口点関数については常に耳にしました。反対側の主張を聞いたことがありません。
これはCSと関係があると思いましたが、この質問はcstheory stackexchangeで撃ち落とされました。
読みやすさと効率性が失われるため、コーディングの悪い方法として単一の出口点関数については常に耳にしました。反対側の主張を聞いたことがありません。
これはCSと関係があると思いましたが、この質問はcstheory stackexchangeで撃ち落とされました。
回答:
考え方にはさまざまな種類がありますが、それは主に個人的な好みに起因します。
1つは、出口点が1つしかない場合でも混乱が少ないことです。メソッドを通るパスが1つで、出口を探す場所がわかっています。マイナス側では、インデントを使用してネストを表す場合、コードは右に大きくインデントされ、ネストされたすべてのスコープをたどることが非常に難しくなります。
もう1つは、メソッドの本文全体で右側に5マイルインデントされていなくても、メソッドの本文で特定の条件がtrueであることを確認できるように、前提条件をチェックしてメソッドの開始時に早く終了できることです。これにより、通常、心配する必要のあるスコープの数が最小限に抑えられ、コードの追跡がはるかに容易になります。
3つ目は、好きなところにどこでも退出できることです。これは昔はもっと混乱していましたが、到達不能なコードを検出する構文カラーリングエディターとコンパイラーがあるため、処理がはるかに簡単になりました。
私は真ん中のキャンプにいます。単一の出口点を強制することは無意味な、または逆効果的な制限であるIMHOですが、メソッド全体でランダムに終了することは、特定のコードのビットが機能するかどうかを確認するのが困難になる、ロジックをたどるのが面倒な場合があります。実行されました。しかし、メソッドを「ゲート」することで、メソッドの本体を大幅に簡略化できます。
singe exit
パラダイムでgo to
ステートメントを使用することで回避できます。さらに、関数のローカルError
ラベルの下でいくつかの後処理を実行する機会が得られますが、これは複数return
のsでは不可能です。
私の一般的な推奨事項は、returnステートメントは、実用的な場合は、副作用のある最初のコードの前か、副作用のある最後のコードの後に配置することです。私は次のようなものを検討します:
if(!argument)//非nullかどうかを確認 ERR_NULL_ARGUMENTを返します。 ... null以外の引数を処理する もし(ok) 0を返します。 そうしないと ERR_NOT_OKを返します。
より明確:
int return_value; if(argument)//非null { .. null以外の引数を処理する ..結果を適切に設定 } そうしないと 結果= ERR_NULL_ARGUMENT; 結果を返す;
特定の条件によって関数が何も実行できない場合は、関数が何を実行するかよりも上の位置で、関数から早期に復帰することをお勧めします。ただし、関数が副作用を伴うアクションを実行したら、すべての副作用を処理する必要があることを明確にするために、下から戻ることを好みます。
ok
変数を管理する最初の例は、私にとっては単一リターンのアプローチのように見えます。また、もし-elseブロックは単純に書き換えることができます:return ok ? 0 : ERR_NOT_OK;
return
すべてを実行するすべてのコードの前にa があります。?:
演算子の使用に関しては、それを別々の行に書き込むことで、多くのIDEでデバッグブレークポイントをnot-okシナリオに接続することが容易になります。ところで、「単一の出口点」の真の鍵は、重要なのは、通常の関数への特定の呼び出しごとに、出口点が呼び出し直後の点であることを理解することにあります。今日のプログラマーはそれを当たり前のことと考えていますが、常にそうであるとは限りませんでした。いくつかのまれなケースでコードが...機能につながる、スタックスペースなしで取得する必要があり
単一の入り口と出口は、構造化プログラミングと段階的なスパゲッティコーディングの独自のコンセプトでした。変数に割り当てられたメモリ空間を適切にクリーンアップする必要があるため、複数の出口点関数にはより多くのコードが必要であると考えられています。関数が変数(リソース)を割り当て、適切なクリーンアップなしに関数から早期に抜けると、リソースリークが発生するシナリオを考えてみます。さらに、すべての出口の前にクリーンアップを構築すると、多くの冗長なコードが作成されます。
ほとんど何でも、それは成果物のニーズに帰着します。「昔」では、複数のリターンポイントを持つスパゲッティコードはメモリリークを引き起こしました。これは、その方法を好んだコーダーは通常、うまくクリーンアップできなかったためです。ネストされたスコープから戻る場合、スタックが戻り中にポップされたため、一部のコンパイラーが戻り変数への参照を「失う」という問題もありました。より一般的な問題は、関数の呼び出し状態を戻り状態とまったく同じにしようとする再入可能なコードの1つでした。oopのミューテーターはこれに違反し、コンセプトは棚上げされました。
複数の出口点が提供する速度を必要とする成果物、特にカーネルがあります。これらの環境には通常、独自のメモリとプロセス管理があるため、リークのリスクが最小限に抑えられます。
個人的には、returnステートメントにブレークポイントを挿入し、コードがそのソリューションをどのように決定したかについてコードインスペクションを実行するために、それを使用することが多いので、私は単一の出口を持っているのが好きです。私は入り口に行って一歩進むことができました。これは、広範囲にネストされた再帰的なソリューションで行います。コードレビュアーとして、関数の複数の戻り値には、より深い分析が必要です。つまり、実装を高速化するためにそれを実行している場合、Peterを奪ってPaulを救っています。コードレビューにはより多くの時間が必要となり、効率的な実装の推定が無効になります。
-2セント
詳細については、このドキュメントを参照してください:NISTIR 5459
multiple returns in a function requires a much deeper analysis
機能がすでに大きい場合にのみ(> 1画面)、それ以外の場合は分析が容易になります
私の見解では、関数(または他の制御構造)を1点のみで終了するというアドバイスは、しばしば売られ過ぎです。通常、1つのポイントでのみ終了する2つの理由が挙げられます。
2番目の理由は微妙であり、特に関数が大きなデータ構造を返す場合、いくつかのメリットがあります。しかし、私はそれをあまり心配しません...
学生の場合、クラスで最高の成績を収めたいと考えています。インストラクターが好むことを行います。彼はおそらく彼の観点からは正当な理由があります。したがって、少なくとも、あなたは彼の見方を学ぶでしょう。これ自体に価値があります。
幸運を。
私はかつては単一出口スタイルの擁護者でした。私の推論は主に痛みから来ました...
単一出口の方がデバッグが簡単です。
私たちが現在持っている技術とツールを考えると、単体テストとロギングによって単一の出口が不要になるため、これははるかに妥当な立場ではありません。つまり、デバッガーでコードの実行を監視する必要がある場合、複数の出口点を含むコードを理解して操作することははるかに困難でした。
これは、状態を調べるために割り当てを挿入する必要がある場合に特に当てはまりました(最新のデバッガーではウォッチ式に置き換えられました)。また、問題を隠したり、実行を完全に壊したりする方法で制御フローを変更することも簡単すぎました。
単一出口メソッドは、デバッガーでステップスルーするのが簡単で、ロジックを壊すことなく分解するのが簡単でした。
答えはコンテキストに大きく依存します。GUIを作成していて、APIを初期化し、メインの開始時にウィンドウを開く関数がある場合、エラーがスローされる可能性がある呼び出しでいっぱいになり、それぞれがプログラムのインスタンスを閉じます。ネストされたIFステートメントを使用してインデントすると、コードがすぐに右に歪む可能性があります。各ステージでエラーを返す方が、コードにいくつかのフラグを付けてデバッグするのと同じくらい簡単である一方で、よりよく、実際にはより読みやすいかもしれません。
ただし、メソッドの結果に応じてさまざまな条件をテストし、さまざまな値を返す場合は、単一の出口点を持つことをお勧めします。以前は、MATLABで非常に大きくなる可能性のある画像処理スクリプトを扱っていました。複数の出口点があると、コードの追跡が非常に難しくなる可能性があります。switchステートメントの方がはるかに適切でした。
最善の方法は、学習しながら学ぶことです。何かのコードを書いているなら、他の人のコードを見つけて、彼らがどのようにそれを実装しているか見てみてください。好きなビットと嫌いなビットを決めます。
関数に複数の出口点が必要だと思われる場合は、関数が大きすぎて実行しすぎています。
Robert C. Martinの本「Clean Code」の関数に関する章を読むことをお勧めします。
基本的に、関数は4行以下のコードで作成する必要があります。
Mike Longのブログからのメモ: