可能な場合、ローカル変数を削除する必要がありますか?


95

たとえば、AndroidでCPUをオンに保つには、次のようなコードを使用できます。

PowerManager powerManager = (PowerManager)getSystemService(POWER_SERVICE);
WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "abc");
wakeLock.acquire();

しかし、私はローカル変数powerManagerと考えるwakeLockことができます:

((PowerManager)getSystemService(POWER_SERVICE))
    .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakelockTag")
    .acquire();

同様のシーンがiOSアラートビューに表示されます。例:from

UIAlertView *alert = [[UIAlertView alloc]
    initWithTitle:@"my title"
    message:@"my message"
    delegate:nil
    cancelButtonTitle:@"ok"
    otherButtonTitles:nil];
[alert show];

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    [alertView release];
}

に:

[[[UIAlertView alloc]
    initWithTitle:@"my title"
    message:@"my message"
    delegate:nil
    cancelButtonTitle:@"ok"
    otherButtonTitles:nil] show];

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    [alertView release];
}

スコープ内で一度だけ使用される場合、ローカル変数を削除するのは良い習慣ですか?


95
必ずしも。ワンタイム変数を使用するとコードがより明確になる場合があり、ほとんどの適切なプログラミング言語では、これらの追加変数のランタイムコストは(あるとしても)ほとんどありません。
ロバートハーベイ

75
また、デバッガを使用してコードをステップ実行するのがより困難になります。また、最初の式がNULLでもエラーでもないことを確認する必要があります(言語によって異なります)。
GrandmasterB

78
いいえ、そうではありません。実際、メソッド呼び出しのチェーンを中断するためにローカル変数を導入することをお勧めします。生成されたマシンコードは同一である可能性が高く、ソースコードは読みやすくなることがほぼ保証されているため、より優れています。
キリアンフォス

48
やってみて デバッガを接続して、PowerManagerまたはWakeLockの状態を確認してください。あなたの間違いを認識してください。私は、コードの調査にほとんどの時間を費やさなければならないまで、同じことを考えていました(「これらすべての地元の人たちは何ですか?」)。
ファリンデル

42
あなたの例でさえ、あなたの「除去された」バージョンにはスクロールバーがあり、私の画面に完全に収まらないので、読みにくくなります。
エリック

回答:


235

コードは書かれているよりもはるかに頻繁に読まれるので、6か月後(あなたかもしれません)にコードを読まなければならない貧しい人の魂に同情し、最も明確で理解しやすいコードを目指して努力する必要があります。私の意見では、ローカル変数を使用した最初の形式の方がはるかに理解しやすいです。1行に3つのアクションではなく、3行に3つのアクションが表示されます。

そして、ローカル変数を取り除くことで何かを最適化していると思うなら、そうではありません。最新のコンパイラーは、ローカル変数を使用するかどうかにかかわらず、メソッドを呼び出すためにpowerManagerレジスター1に入れnewWakeLockます。同じことはにも当てはまりますwakeLock。したがって、どちらの場合も同じコンパイル済みコードになります。

1宣言とローカル変数の使用との間に多くのコードが介在している場合、スタックに置かれる可能性がありますが、それは細部ではありません。


2
たくさんのコードがあるかどうかはわかりません。オプティマイザーはいくつかの関数をインライン化するかもしれません。
マチューM.17年

2
反対に、ローカル変数が使用可能な各関数で複数回初期化されるのを見ると、可能な場合は属性ではなく、理由を検索し、基本的に行を徹底的に読んで比較するだけですそれらが同じであることを確認してください。だから時間を無駄にします。
ウォルフラット

15
@Walfratローカル変数が複数回初期化されますか?痛い。誰も地元の人々を再利用することを提案しません
でした

32
@Walfratメンバーは副作用を引き起こすため、パブリックメンバーへの呼び出し間で特に状態を維持する場合にのみ使用してください。この質問は、中間計算の一時的な保存のためのローカルの使用を扱っているようです。
ガスドール

4
Q:可能な場合、ローカル変数を削除する必要がありますか?A:いいえ。
サイモン

94

いくつかの非常に支持されたコメントがこれを述べましたが、私が見た答えはどれもなかったので、答えとして追加します。この問題を決定する主な要因は次のとおりです。

デバッグ可能性

多くの場合、開発者はコードを書くよりもはるかに多くの時間と労力を費やします。

ローカル変数、次のことができます。

  • 割り当てられている行のブレークポイント(条件付きブレークポイントなど、他のすべてのブレークポイントの装飾を含む)

  • ローカル変数の値の検査/監視/印刷/変更

  • キャストが原因で発生する問題をキャッチします。

  • 読みやすいスタックトレースを使用します(行XYZには10ではなく1つの操作があります)

ローカル変数がなければ、上記のタスクはすべて、デバッガーに応じて、はるかに難しい、非常に難しい、またはまったく不可能です。

そのため、悪名高い格言(次の開発者が自分の住んでいる場所を知っている狂った狂人であるかのようにコードを書いてください)に従い、デバッグ容易にするために、ローカル変数使用することを意味します


20
単一行に多くの呼び出しがある場合、スタックトレースの有用性ははるかに低いと付け加えます。行50にNULLポインター例外があり、その行に10の呼び出しがある場合、ガウンはあまり狭まりません。本番アプリケーションでは、これは多くの場合、欠陥レポートから取得する情報の大部分になります。
ジミージェームズ

3
コードのステップ実行も非常に困難です。call()-> call()-> call()-> call()がある場合、3番目のメソッド呼び出しにステップインするのは大変です。4つのローカル変数があればはるかに簡単になります
-gnasher729

3
@FrankPuffer-私たちは現実の世界に対処しなければなりません。デバッガがあなたが提案したことをしない場合。
DVK

2
@DVK:実際には、式を調べたり監視したりできると思ったよりも多くのデバッガーがあります。MS Visual Studio(バージョン2013以降)には、C ++およびC#用のこの機能があります。EclipseにはJava用があります。別のコメントで、ファリンデルはJSのIE11に言及しました。
フランクパファー

4
@DVK:ええ、多くの現実世界のデバッガーは私が提案したことをしません。しかし、それは私のコメントの最初の部分とは関係ありません。私のコードを保守しようとしている人が、主にデバッガーを使用してコードとやり取りすると思い込んでいるのはおかしいです。デバッガーは特定の目的には優れていますが、コードを分析するためのメインツールを入手した場合、何か重大な問題があると言い、コードをよりデバッグ可能にするのではなく、修正しようとします。
フランクパファー

47

コードが理解しやすくなる場合のみ。あなたの例では、読みにくくなると思います。

コンパイルされたコード内の変数を削除することは、優れたコンパイラーにとって簡単な操作です。出力を自分で調べて確認できます。


1
これは、変数の使用と同じくらいスタイリングに関係しています。質問は編集されました。
ジョドレル

29

あなたの質問は、「ローカル変数がスコープ内で一度だけ使用される場合、ローカル変数を削除することは良い習慣ですか?」間違った基準をテストしています。ローカル変数のユーティリティは、使用回数に依存するのではなく、コードを明確にするかどうかに依存します。意味のある名前で中間値にラベルを付けると、コードをより小さく、より消化しやすいチャンクに分解するため、あなたが提示するような状況で明確さを向上させることができます。

私の見解では、あなたが提示した変更されていないコードは、変更されたコードよりも明確であるため、変更しないでください。実際、わかりやすくするために、変更したコードからローカル変数を引き出すことを検討します。

ローカル変数によるパフォーマンスへの影響は期待していません。1つでも、プログラムの速度が重要な部分でコードが非常にタイトなループにある場合を除いて、検討する価値はありません。


これは、スタイル設定や空白の使用と関係があると思います。質問が編集されました。
ジョドレル

15

多分。

個人的には、タイプキャストが関係する場合はローカル変数を削除することをためらうでしょう。ブラケットの数が私が持っている精神的な限界に近づき始めると、あなたのコンパクト版は読みにくくなります。さらに、ローカル変数を使用するもう少し冗長なバージョンでは必要なかった新しい括弧のセットを導入します。

コードエディタによって提供される構文の強調表示により、このような懸念がある程度緩和される可能性があります。

私の目には、これがより良い妥協点です。

PowerManager powerManager = (PowerManager)getSystemService(POWER_SERVICE);
powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "abc").acquire();

したがって、1つのローカル変数を保持し、他のローカル変数を捨てます。C#では、タイプキャストが既にタイプ情報を提供しているため、最初の行でvarキーワードを使用します。


13

ローカル変数を好む回答の妥当性を受け入れますが、悪魔の擁護者を演じ、逆説的な見解を提示します。

個人的には、文書化の目的だけでローカル変数を使用することに多少反対ですが、その理由自体は、プラクティスに価値があることを示しています。ローカル変数は、コードを効果的に擬似文書化します。

あなたの場合、主な問題はインデントであり、変数がないことです。次のようにコードをフォーマットできます(また、そうする必要があります)。

((PowerManager)getSystemService(POWER_SERVICE))
        .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"MyWakelockTag")
        .acquire();

ローカル変数を使用したバージョンと比較してください。

PowerManager powerManager=(PowerManager)getSystemService(POWER_SERVICE);
WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"abc");
wakeLock.acquire();

ローカル変数を使用すると、名前によってリーダーに情報が追加され、タイプが明確に指定されますが、実際のメソッド呼び出しは見えにくくなり、(私の意見では)明確に読み取れません。

ローカル変数を使用しない場合:より簡潔でメソッド呼び出しがよりわかりやすくなりますが、返されるものについての詳細情報を要求する場合があります。ただし、一部のIDEではこれを表示できます。

さらに3つのコメント:

  1. 私の意見では、機能的な用途のないコードを追加することは、混乱を招く場合があります。たとえば、このメソッドが100行の長さである場合、メソッド全体を読まない限り、ローカル変数(およびメソッド呼び出しの結果)が後の時点で不要になることは明らかではありません。

  2. ローカル変数を追加すると、それらのタイプを指定する必要があり、そうしないとコードに依存関係が生じます。メソッドの戻り値の型が簡単に変更された場合(たとえば、名前が変更された場合)、コードを更新する必要がありますが、ローカル変数がない場合は変更しません。

  3. デバッガがメソッドから返された値を表示しない場合、ローカル変数を使用するとデバッグが容易になります。しかし、その修正は、コードを変更するのではなく、デバッガーの欠陥を修正することです。


あなたのさらなるコメントに関して:1.ローカル変数は使用される場所にできるだけ近く宣言され、メソッドを適切な長さに保つという慣習に従えば、これは問題になりません。2.型推論を備えたプログラミング言語ではありません。3.よく書かれたコードは、多くの場合、デバッガをまったく必要としません。
ロバートハーベイ

2
最初のコード例は、流なインターフェイスまたは「ビルダー」パターンを使用してオブジェクトを作成する場合にのみ機能します。パターンは、コードのどこでも使用せず、選択的にのみ使用します。
ロバートハーヴェイ

1
この質問は、ローカル変数が機能的に冗長であるため、そのタイプのインターフェースがケースに必要であると仮定していると思います。それ以外の場合はさまざまなゆがみによってローカルユーザーを削除できますが、単純なケースを見ていることを念頭に置いていました。
rghome

1
読みやすくするために、バリアントをさらに悪化させます。私はVB.netにあまりにも多くさらされていたかもしれませんが、あなたのサンプルを見たとき、私の最初は「WITHステートメントはどこに行きましたか?誤って削除しましたか?」です。何が起こっているのかを二度見る必要があり、それは何ヶ月も後にコードを再検討する必要があるときは良くありません。
トニー

1
私にとって@Tonny、それはより読みやすいです:ローカルは文脈から明らかでないものを追加しません。私は自分のJavaを真剣に考えていますwith。これは、Javaの通常のフォーマット規則です。
-rghome

6

ここには動機の緊張があります。一時変数を導入すると、コードが読みやすくなります。ただし、メソッドの抽出や、TempをQueryに置き換えるなど、他のリファクタリングを防止したり、見にくくしたりすることもできます。これらの後者のタイプのリファクタリングは、必要に応じて、多くの場合、temp変数よりもはるかに大きな利点を提供します。

これらの後者のリファクタリングの動機について、ファウラーは次のように書いています

「tempsの問題は、一時的でローカルなことです。使用されるメソッドのコンテキストでのみ表示されるため、tempsはtempに到達する唯一の方法であるため、より長いメソッドを推奨する傾向があります。 tempをクエリメソッドに置き換えると、クラス内のすべてのメソッドが情報を取得できます。これは、クラスのコードをよりきれいにするのに役立ちます。」

そのため、特にコードが読みやすくなる場合、特にそれがあなたとあなたのチームにとってローカルな規範である場合、tempsを使用します。ただし、そうすることで、より大きな代替の改善点を見つけるのが難しくなる場合があることに注意してください。そのような臨時雇用者なしで行く価値があるときに感じる能力を開発し、そうすることでより快適になることができれば、それはおそらく良いことです。

FWIW私は個人的にファウラーの本「リファクタリング」を読むことを10年間避けました。私は完全に間違っていました。最終的にそれを読んだとき、それは私の毎日のコーディング慣行を大きく変えました。


1
素晴らしい答え。私が書いた(そして他の人から見た)最高のコードには、多くの場合、そのような一時変数の代わりに使用できる多数の小さな(2、3行)メソッドがありました。関連するのは、プライベートメソッドが悪臭を放つという物議を醸すテイクです。
スティンデウィット

この質問の臨時雇用者はすでに関数を参照しているため、この回答はOPの質問とは無関係です。
user949300

@ user949300無関係だとは思わない。はい、OPの特定の例のtempは、関数またはメソッドからの戻り値です。しかし、OPは非常に明確であり、これは単なる例のシナリオです。実際の質問は、はるかに一般的な「できる限り一時変数を削除すべきか」です。
ジョナサンハートリー

1
OK、私は売り切れました**、票を変えようとしました**。しかし、OPの質問の限られた範囲を超えたとき、私はうんざりします。だから気まぐれになることがあります... :-)。
えー

@ user949300聖なる牛!問題を思慮深く考えて考えを変える人!あなたは、珍しいです、そして、私はあなたに私のキャップをオフにします。
ジョナサンハートリー

3

それにより、コードを読みやすくすることができる場合は、ローカル変数を削除することお勧めします。あなたの長い一行は読めませんが、それからかなり冗長なオブジェクト指向スタイルに従います。のようなものに減らすことができれば

acquireWakeLock(POWER_SERVICE, PARTIAL, "abc");

それはおそらく良いアイデアだと思います。おそらく、ヘルパーメソッドを導入して、それを似たようなものに要約することができます。このようなコードが複数回現れる場合、それは価値があるかもしれません。


2

ここでデメテル法則について考えてみましょう。LoDに関するウィキペディアの記事には、次のことが記載されています。

関数のDemeterの法則では、オブジェクトOのメソッドmは、次の種類のオブジェクトのメソッドのみを呼び出すことができます。[2]

  1. O自体
  2. mのパラメーター
  3. m内で作成/インスタンス化されたオブジェクト
  4. Oの直接コンポーネントオブジェクト
  5. Oでアクセス可能な、mのスコープ内のグローバル変数

この法律に従うことの結果の1つは、上記の2番目の例に示すように、長いドットで区切られた文字列で他のメソッドによって返されるオブジェクトのメソッドを呼び出さないようにすることです。

((PowerManager)getSystemService(POWER_SERVICE)).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"MyWakelockTag").acquire();

これが何をしているのかを理解するのは本当に難しいです。それを理解するには、各プロシージャが何をするのかを理解してから、どの関数がどのオブジェクトで呼び出されているのかを解読する必要があります。最初のコードブロック

PowerManager powerManager=(PowerManager)getSystemService(POWER_SERVICE);
WakeLock wakeLock=powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"abc");
wakeLock.acquire();

何をしようとしているのかが明確に示されています-PowerManagerオブジェクトを取得し、PowerManagerからWakeLockオブジェクトを取得してから、wakeLockを取得しています。上記はLoDのルール#3に従います-これらのオブジェクトをコード内でインスタンス化しているため、これらを使用して必要なことを実行できます。

おそらく別の考え方は、ソフトウェアを作成するとき、簡潔にするためではなく、明確にするために書くべきだということを覚えておくことです。すべてのソフトウェア開発の90%はメンテナンスです。維持するのが苦手なコードを書かないでください。

幸運を祈ります。


3
流動的な構文がこの答えにどのように適合するかに興味があります。正しい書式設定により、流動的な構文は非常に読みやすくなります。
ガスドール

12
それは「デメテルの法則」の意味ではありません。デメテルの法則は、点を数える練習ではありません。それは本質的に「あなたの直接の友人とだけ話す」ことを意味します。
ロバートハーベイ

5
中間変数を介して同じメソッドとメンバーにアクセスすることは、デメテルの法則に違反することと同じくらい深刻です。修正するのではなく、隠しただけです。
ジョナサンハートリー

2
「デメテルの法則」に関しては、どちらのバージョンも等しく「悪い」です。
ハルク

@Gusdorは同意しました。これは、質問例のスタイルに関するコメントです。質問は編集されました。
Jodrell

2

注意すべきことは、コードが異なる「深さ」で頻繁に読み取られることです。このコード:

PowerManager powerManager = (PowerManager)getSystemService(POWER_SERVICE);
WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "abc");
wakeLock.acquire();

「スキム」するのは簡単です。3つのステートメントです。最初にPowerManager。それから私達はWakeLock。その後、我々。これは、各行の先頭を見るだけで簡単にわかります。単純な変数の割り当ては、「Type varName = ...」として部分的に認識し、「...」を単に精神的にざっと読むだけです。同様に、最後の文は明らかに割り当ての形式ではありませんが、2つの名前のみが関係するため、「主な要点」がすぐにわかります。多くの場合、「このコードは何をするのか」と答えようとしているのかどうかを知る必要があるだけです。高いレベルで。acquirewakeLock

ここにあると思われる微妙なバグを追いかけている場合は、明らかにこれをさらに詳しく調べる必要があり、実際には「...」を覚えています。しかし、個別のステートメント構造は、一度に1つのステートメントを実行するのに役立ちます(特に、各ステートメントで呼び出されるものの実装をさらに深く掘り下げる必要がある場合に役立ちます。次のステートメントに進むことができます)。

((PowerManager)getSystemService(POWER_SERVICE))
    .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakelockTag")
    .acquire();

これで、すべて1つのステートメントになりました。最上位レベルの構造は、簡単に読むことが簡単ではありません。OPの元のバージョンでは、構造を視覚的に伝えるために改行やインデントを使用しなかったため、括弧をカウントして3つのステップのシーケンスにデコードする必要がありました。マルチパート式の一部がメソッド呼び出しのチェーンとして配置されるのではなく、互いに入れ子になっている場合、これと同様に見える可能性があるため、括弧をカウントせずにそれを信頼することに注意する必要があります。そして、私がインデントを信頼し、このすべての推定されるポイントとして最後の事に目を通すだけなら、それだけで何が.acquire()わかりますか?

しかし、時にはそれがあなたの望むものになります。変換を途中で適用して書いた場合:

WakeLock wakeLock =
     ((PowerManeger)getSystemService(POWER_SERVICE))
    .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyWakeLockTage");
wakeLock.acquire();

これはWakeLock、「get a then then 」という簡単なスキムと通信しacquireます。最初のバージョンよりもさらにシンプル。取得されるものがであることはすぐに明らかですWakeLock。を取得することPowerManagerがこのコードのポイントにとってかなり重要ではないサブディテールであるwakeLockが、それが重要な場合、実際にPowerManager物を埋めることができるので、すぐに取得しようとしている場合はそれをざっと見るのが自然ですこのコードが何をするかのアイデア。名前を付けないこと、それ一度だけ使用されることを伝え、時にはそれが 重要なこと(スコープの残りが非常に長い場合、それが再び使用されるかどうかを知るためにすべてを読む必要があります。ただし、言語がサポートしている場合、明示的なサブスコープを使用することは別の方法で対処できます)

これは、それがすべてコンテキストとあなたが伝えたいものに依存していることをもたらします。自然言語で散文を書くのと同様に、情報内容の点で基本的に同等である特定のコードを書くための多くの方法が常にあります。自然言語で散文を書く場合と同様に、一般的にどちらを選択するかは、「1回だけ発生するローカル変数を削除する」などの機構的なルールを適用することでありません。むしろ方法コードを書き留めることを選択すると、特定のものが強調され、他のものが強調されなくなります。あなたが実際に強調したいものに基づいて、意識的にそれらの選択をするよう努力する必要があります(技術的な理由で読みにくいコードを書く選択を含む)。特に、(さまざまなレベルで)コードの「要点を把握する」だけの読者に役立つものについて考えてください。これは、式ごとの非常に近い読み取りよりもはるかに頻繁に発生するためです。


私にとっては、APIの知識がなくても、変数がなくてもコードが何をするかは非常に明白です。getSystemService(POWER_SERVICE)パワーマネージャを取得します。.newWakeLockウェイクロックを取得します。.acquireそれを取得します。OK、すべてのタイプを知っているわけではありませんが、必要に応じてIDEで見つけることができます。
rghome

コード何をすべきかはあなたには明らかかもしれませんが、実際に何をするのかはわかりません。バグを探している場合、どこかのコードが本来の動作をしていないことを知っているだけで、どのコードを見つける必要があります。
gnasher729

@ gnasher729はい。バグハンティングは、すべての詳細を注意深く読む必要がある場合の例です。そして、本来あるべきことをしていないコードを見つけるのに本当に役立つことの1つは、元の作者の意図が何であるかを簡単に確認できることです。
ベン

私が戻ってきたとき、「1つのユニット」を完全に理解し、次のステートメントに進むことができます。実は違う。実際、ローカル変数はその完全な理解を妨げます。彼らはまだ長引くされているので...精神的なスペースを取って...何が...次の20文の中で彼らに起こるしようとしているドラムロール ...地元の人々がなければ、あなたは何もするオブジェクトがなくなっていたことを確認してくださいとは不可能であろう次の行でそれらと一緒に。それらについて覚えておく必要はありません。return同じ理由で、可能な限り迅速にメソッドを使用するのが好きです。
スティンデウィット

2

これは、Train Wreckという名前のアンチパターンです。交換を回避するいくつかの理由がすでに述べられています。

  • 読みにくい
  • デバッグが難しい(変数の監視と例外の場所の検出の両方)
  • デメテルの法則(LoD)の違反

このメソッドが他のオブジェクトから多くを知っているかどうかを検討してください。メソッドチェーンは、カップリングの削減に役立つ代替手段です。

また、オブジェクトへの参照は本当に安いことを覚えておいてください。


Ehmは、メソッドチェーンを行う修正されたコードではありませんか?編集はリンクされた記事を読むので、私は今違いを見る。かなり良い記事ありがとう!
スティンデウィット

レビューしていただきありがとうございます。とにかく、メソッド連鎖はいくつかのケースで機能するかもしれませんが、変数を残すだけが適切な決定かもしれません。人々があなたの答えに同意しない理由を知ることは常に良いことです。
ボルジャブ

「電車の残骸」の反対は「ローカル線」だと思います。ほとんどの日は誰も乗車していなくても、誰かが乗り降りしたい場合に備えて、2つの主要都市間の列車がその間のすべての田舎の村で止まります。
rghome

1

述べられている質問は、「できるならローカル変数を削除すべきか」です。

いいえ、できるからといって排除すべきではありません。

ショップのコーディングガイドラインに従う必要があります。

ほとんどの場合、ローカル変数はコードの読み取りとデバッグを容易にします。

あなたがしたことが好きですPowerManager powerManager。私にとって、このクラスの小文字は、1回限りの使用であることを意味します。

すべきでないのは、変数が高価なリソースを保持する場合です。多くの言語には、クリーンアップ/リリースが必要なローカル変数の構文があります。C#では使用しています。

using(SQLconnection conn = new SQLconnnection())
{
    using(SQLcommand cmd = SQLconnnection.CreateCommand())
    {
    }
}

これは実際にはローカル変数に関係するのではなく、リソースのクリーンアップに関係します...私はC#に精通してusing(new SQLConnection()) { /* ... */ }いませんが、合法ではない場合は驚きます(役に立つかどうかは別の問題です:)。
スティンデウィット

1

1つの重要な側面は、他の回答では言及されていません。変数を追加するたびに、可変状態が導入されます。これは通常、コードをより複雑にし、したがって理解とテストが難しくなるため、悪いことです。もちろん、変数のスコープが小さいほど、問題は小さくなります。

実際に必要なのは、値を変更できる変数ではなく、一時的な定数です。したがって、言語で許可されている場合は、コードでこれを表現することを検討してください。Javaでは使用できfinal、C ++では使用できますconst。ほとんどの機能言語では、これがデフォルトの動作です。

ローカル変数が変更可能な状態の中で最も有害なタイプではないことは事実です。メンバー変数はより多くの問題を引き起こす可能性があり、静的変数はさらに悪化します。それでも、コードでできる限り正確に表現することが重要だと思います。また、後で変更できる変数と、中間結果の単なる名前には大きな違いがあります。そのため、言語でこの違いを表現できる場合は、それを実行してください。


2
私はあなたの答えに賛成票を投じませんでしたが、何らかの長期的な方法について話していない限り、命令型言語ではローカル変数が一般に「状態」と見なされないという事実に関連していると思います。final / constをベストプラクティスとして使用することに同意しますが、チェーンコールを単純に分割するために変数を導入すると、可変状態に起因する問題が発生する可能性はほとんどありません。実際、ローカル変数を使用すると、可変状態に対処できます。メソッドが異なる時間に異なる値を返すことができる場合、それ以外の場合は本当に興味深いバグが発生する可能性があります。
ジミージェームズ

@JimmyJames:私の答えに説明を追加しました。しかし、私が理解していなかったあなたのコメントの一部があります:「ローカル変数の使用は、可変状態に対処するのに役立ちます」。これを説明してもらえますか?
フランクパファー

1
たとえば、値を確認する必要があり、10を超える場合はアラートが発生するとします。この値がmethodに由来すると仮定しますgetFoo()。ローカル宣言を回避するとif(getFoo() > 10) alert(getFoo());、最終的にはgetFoo()が2つの異なる呼び出しで異なる値を返す可能性があります。10以下の値を持つアラートを送信できますが、これはせいぜい紛らわしく、欠陥として私に戻ってくるでしょう。この種のことは、並行性により重要になります。ローカル割り当てはアトミックです。
ジミージェームズ

非常に良い点。たぶん私は、これらの地元の人々が好きではない理由は....あなたはするつもりですやることで何か、このメソッドを呼び出した後にインスタンスを?メソッドの残りの部分を確認しましょう。そして、あなたが得たこの こと...あなたはそれで何をしていますか(まだ方法の残りをスキャンしています)... ああ、もっと読みやすいはずです...しかし、それらがなければ、あなたはもうそれらを使用しないと確信しているので、残りのメソッドを読む必要はありません。PowerManagerWakeLock
スティンデウィット

最近の講演で、スピーカーは、変数が最終的であることを示す最良の方法は、変数が変化しないことが明らかな短いメソッドを書くことだと主張しましたfinalメソッドのローカル変数で必要な場合、メソッドが長すぎます。
user949300
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.