前述のように、これについては2つの考え方があります。
1)年は1987年なので、関数の最上部ですべてを宣言します。
2)最初の使用に最も近く、可能な限り最小の範囲で宣言します。
これに対する私の答えは「両方」です!説明させてください:
長い関数の場合、1)リファクタリングが非常に困難になります。開発者がサブルーチンのアイデアに反対しているコードベースで作業している場合、関数の最初に50の変数宣言があり、それらの一部はforループの「i」である可能性があります。関数の下部。
したがって、私はこれからPTSD宣言を作成し、オプション2)を宗教的に実行しようとしました。
オプション1に戻ったのは、短い関数という1つの理由からでした。関数が十分に短い場合、ローカル変数はほとんどなくなります。関数が短いため、関数の先頭に配置すると、最初の使用に近くなります。
また、最初に宣言したいが、初期化に必要な計算をまだ行っていない場合の「宣言してNULLに設定」のアンチパターンは、初期化に必要なものが引数として受け取られる可能性が高いため、解決されています。
だから今私の考えは、あなたは関数の一番上で、そして最初の使用にできるだけ近いところで宣言すべきだということです。両方!そして、その方法は、よく分割されたサブルーチンを使用することです。
ただし、長い関数で作業している場合は、メソッドを抽出するのが簡単になるため、最初の使用に最も近いものを配置します。
私のレシピはこれです。すべてのローカル変数について、変数を取得してその宣言を一番下に移動し、コンパイルしてから、宣言をコンパイルエラーの直前に移動します。それが最初の使用です。これをすべてのローカル変数に対して行います。
int foo = 0;
<code that uses foo>
int bar = 1;
<code that uses bar>
<code that uses foo>
次に、宣言の前に始まるスコープブロックを定義し、プログラムがコンパイルされるまで終了を移動します。
{
int foo = 0;
<code that uses foo>
}
int bar = 1;
<code that uses bar>
>>> First compilation error here
<code that uses foo>
fooを使用するコードがいくつかあるため、これはコンパイルされません。fooを使用しないため、barを使用するコードをコンパイラが通過できたことがわかります。この時点で、2つの選択肢があります。機械的な方法は、コンパイルするまで「}」を下に移動することです。もう1つの選択肢は、コードを検査して、順序を次のように変更できるかどうかを判断することです。
{
int foo = 0;
<code that uses foo>
}
<code that uses foo>
int bar = 1;
<code that uses bar>
順序を切り替えることができる場合は、一時的な値の寿命が短くなるため、おそらくこれが必要です。
もう1つ注意すべき点として、fooの値は、それを使用するコードのブロック間で保存する必要がありますか、それとも両方の異なるfooにすることができますか。例えば
int i;
for(i = 0; i < 8; ++i){
...
}
<some stuff>
for(i = 3; i < 32; ++i){
...
}
これらの状況は私の手順以上のものを必要とします。開発者は、コードを分析して何をすべきかを決定する必要があります。
しかし、最初のステップは、最初の用途を見つけることです。視覚的に行うこともできますが、場合によっては、宣言を削除し、コンパイルして、最初の使用の前に戻すほうが簡単です。最初の使用がifステートメントの内部にある場合は、そこに配置して、コンパイルされるかどうかを確認します。その後、コンパイラーは他の用途を識別します。両方の用途を含むスコープブロックを作成してみてください。
この機械的な部分が完了すると、データの場所を分析することが容易になります。変数が大きなスコープブロックで使用されている場合は、状況を分析し、同じ変数を2つの異なるもの(2つのforループで使用される「i」など)に使用しているかどうかを確認します。用途が無関係の場合は、これらの無関係の用途ごとに新しい変数を作成します。