web-dev-qa-db-ja.com

定数の代わりに変数を使用できないのはなぜですか?

定数の意味がわかりません。たとえば、PIの有名な例を使用できます。

PI = float(3.14) 

ここで私は定数なしで仕事を成し遂げる。プログラムの存続期間中に値が変化しないかどうか、またはそれがベストプラクティスであるかどうかは、誰が気にかけますか。

PIを変数として定義して、同じタスクを同様に実行できます。

5
dick smith

概念的には、変数または定数に値を割り当てるオプションは、次の1つの点のみが異なります。定数を再割り当てしようとすると、コンパイラーが警告を表示します

あなたは正しいです。定数ではなく変数に値を割り当てると、それに割り当てられた値を変更しないように注意している限り、ジョブが完了します。

たとえば、特定の半径の円の領域を見つけるプログラムを作成している場合は、次のように書くことができます。

float pi =  3.14
float area (float r) : 
    return pi*r*r

そして、誰かがpiの値を2.5のような何かに変更したとしたら、彼らは本当に自分の愚かさの犠牲者であると自分に考えてください。

また、不要な機能を自分で負担したくはありません。

ただし、プログラマーは、将来起こりうる問題をできるだけ多く排除する傾向があります。プログラムが大きく、多くのプログラマーが作業している場合、誰かが変数を再定義して(変数が機能するように)、変数の正しい値に依存する関数への次の呼び出しが返される可能性があります誤った結果。

現在、この可能性をなくすには2つの方法があります。変数を関数自​​体にローカルにすることができますが、それを参照する関数ごとに行う必要があるため、冗長になります。

または、プログラミング言語によって提供される気の利いた機能を使用して、定数に値を宣言し、定数の値を再割り当てしようとするとコンパイラーが警告を出すようにすることもできます。

8
  1. 英語の名前は、番号の目的が何であるかを明確にします。
  2. Piの精度は、プログラム全体で同じです。
  3. Piは1か所で定義されているため、小数点以下の桁数を変更する場合は、どこでも変更する必要はありません。
  4. コンパイラに定数を強制させることは、コードのどの部分もそれを別のものに変更する可能性がないことを意味し、潜在的に不明瞭なバグの原因を排除します。
20
Robert Harvey

プログラムの存続期間中に値が変更されないか、プログラミングがベストプラクティスであるかを気にする人。

誰も気にしない?あなたのコードを維持する必要がある人々。

プロジェクトマネージャーが数か月後に戻ってきて、「3.14」はアプリケーションのpiの十分な近似ではなくなったと言ったらどうなりますか?彼は次のスペースシャトルの構築に使用され、小数点以下8桁までの精度が必要であるため、プログラムをより正確にしたいと考えています。

職業はなんですか?プロジェクト内のすべてのコードで「3.14」から「3.14159265」を大量に検索して置換するだけですか。おめでとうございます。これで、別の優秀なプログラマーが値 "23.14994"をハードコード化した別の場所で別の計算を台無しにしました。その値は「23.14159265994」になり、スペースシャトルが爆発しました。

定数は、必要な場所で値の一貫性を保つのに役立ちます。もちろん、Tic-Tac-Toeのゲームが3列と3行を超えるとは思わないでしょうが、誰かがゲームを5〜5グリッドに拡大したいと思うかもしれません。また、コードが読みやすくなります。通常は、変数/定数を右クリックして、アプリケーションまたはファイル全体で名前を変更することにより、将来的にコードをリファクタリングすることもできます。

編集:質問の元のタイトルは「なぜプログラミングに定数が必要なのですか?」質問が「定数ではなく変数を使用できないのはなぜですか?」に変更されたためです。私もその質問にお答えします。

変数は変更される可能性があります。定数はできません。誰かが2桁の精度しか必要とせず、変数が8桁の精度を保持していると誰かが判断した場合、変数の重要でない桁が切り捨てられる可能性があります。残念ながら、これにより、元のより正確な値に依存していたアプリの他の部分で問題が発生する可能性があります。値を定数にすることで、コンパイル時エラーが発生し、アプリケーションの整合性が維持されます。

13
JackAce

意思の伝達

あなたの例では、プログラム全体で参照できるmutable変数PIを定義しています。 [〜#〜] dry [〜#〜]コードを作成しました。これは、定義を変更する場合にのみ、1か所で更新する必要があります。これは良いことです小さなプログラムで機能します開発者は1人だけで、コードは多くありません。

ただし、コードベースが大きくなるにつれて、そしてコードで作業を始める人が増えるにつれて、意図を伝えるが非常に重要になります。ほとんどの人はおそらくPiが数学定数であることを認識しており、それが変化することを期待していませんが、most定数については同じことが当てはまりません。定数として何かを宣言することで、その定数の意味を他の開発者(将来の自分を含む)に伝えます。

コンスタントは何を伝えますか?

値が定数として宣言されていることを確認すると、開発者は次のコードをcommunicatingします。

  1. この値は、プログラムの実行中に決して変化しません
  2. この値はおそらくスレッドセーフです(これは常に読み取られるだけで、書き込まれることはありません)。
  3. この値は、コード全体の多くの領域で参照されている可能性があります。
  4. 値の名前は、それが何を意味するかについて重要なことを示している可能性があります。
    • ほとんどの人は_3.14_がPiの近似値であることを知っていますが、多くの定数は名前がなければ意味がありません。 if (i > MaxNumberOfUsers)if (i > 10)よりもはるかに意味があります。

定数は他にどのようなメリットをもたらしますか?

値を定数として宣言すると、コンパイラにいくつかのことを伝えることもできます(ただし、これは言語やコンパイラによって異なります)。

多くのコンパイラはコンパイル時に定数値を最適化し、その結果をコードに直接挿入します。

_// No calculation will take place at runtime - all of these values
// can be replaced with their calculated results at compile time
const long BytesPerKilobyte = 1024;
const long BytesPerMegabyte = 1024 * BytesPerKilobyte; // Compiles as 1048576
const long BytesPerGigabyte = 1024 * BytesPerMegabyte; // Compiles as 1073741824

// ... elsewhere in the code ...
const long maxFileSize = BytesPerMegabyte * 40;
if (fileSize > maxFileSize) // actually compiles to `if (fileSize > 41943040) {...}`
{
    println("The file is too large to work with");
}
_

そう...

プログラミングの勉強を始めたとき、定数の意味がわかりませんでした。私はいくつかのクラスを超えるプロジェクトに携わったことがなく、すべてをまっすぐに保つのは簡単でした。

ほとんどのコードはこのようなものではありません。ほとんどのコードは非常に大規模な環境に存在し、複数の人がさまざまなタイミングで管理しています。取り組んでいるプロジェクトが大きくなるにつれて、他の開発者や自分が自分のコードが意図していることを伝達できることがますます重要になります。

これらの種類の環境では、すべてを頭の中でまっすぐに保つことに伴う精神的負荷の一部を取り除くものに感謝します。

6
KChaloux

プロジェクトがどんどん大きくなるにつれて、プロジェクトの維持がますます難しくなります。主な理由は 人間の心は、直接のコンテキストで保持できるものの数が限られている です。これを克服するために、通常はプロジェクトをより小さく単純なコンポーネントに分割したいので、他のコンポーネントがどのように機能するかを意識することなく、1つのコンポーネントで作業できます。他のコンポーネントを使用する場合でも、現在取り組んでいるコンポーネントに集中できるように、それらをブラックボックスとして使用したいと考えています。

多くのテクニック、ツール、ライブラリ、プログラミング言語機能は、プロジェクトを作業しやすいコンポーネントに分割するのに役立つように設計されています。コードのどの部分が何に責任があるかを明確にする原則の1つ。

通常、物事の宣言(変数、定数、クラス、関数など)は、物事が何ができて何ができないかを定義する責任があり、ツールがインテリジェントに警告するときに非常に役立ちます。あなたはそのことを誤用します。 sqrt(-18)を呼び出すとき、「sqrtを負の数で呼び出すことはできません!」というコンパイルエラーが発生するのは素晴らしいことです。実行時にそのエラーが発生することは、それほど良くはありませんが、それでも優れています。 sqrt(-18)が誤った値を使用したためにランダムな値が返されたため、奇妙な出力をさらに下げたくありません...

これは定数が適合する場所です。定数を使用すると、宣言時に値を実行時に変更しないように定義でき、その定義は使用時に適用されます。したがって、一部の開発者が値を変更できると考えた場合、コンパイラは怒鳴りつけます。

さて、 正しい心の誰もがPIの値を変更することはありません ですが、そうでない場合でも、他の値は変更可能に見える場合があります。それらを一定にすることは、メンテナが実行時にそれらを変更することの影響をサポートせず、他の開発者がそれらを変更することを禁止することを意味します。

ところで、私は「この開発者」と「他の開発者」に言及し続けていますが、同じ開発者でもかまいません。プログラムの構造全体を限られた人間の頭の中で維持することはできないため、別のコンポーネントで作業するときは、コンテキストを変更したために、別の開発者になることもできます。

3
Idan Arye

定数(特にコンパイラ定数)の主な理由の1つは、事前定義されたもの(つまり、pi、e、nullなど)に一貫した値を与えることです。

定数も時間の節約になります。特定の種類の数学を実行する必要がある場合、値を調べる必要はありません。

0
Adam Zuckerman

一部のプログラミング言語では、定数を呼び出すことは、それを不変としてマークする方法です。 PIの例を使用すると、PIと呼ばれる変数を定義して3.14に割り当て、コード全体でそれをPIの値として使用できます。ただし、コードを使用する一部のプログラマーが、コードにPIのより正確な表現が必要であると判断し、PI変数を3.141592に設定するとどうなりますか。既存のコードが追加された精度を処理できる場合、または3.1416に丸めるなどの奇妙な方法ですべてを壊す可能性がある場合は、問題が発生しない可能性があります(これは、間違いなくPIではありません)。

0
Eric Evans

@Robert Harveysの回答を拡張するには

  1. 多くのコンパイルされた言語はコンパイルされたコードに定数を埋め込むので、コンパイラ/インタプリタレベルの理由があります
  2. 3.14 PIは外部の世界にとって何かを意味しますが、定数として追加するまでは、プログラムの世界(またはドメイン)で何かを意味するわけではありません。プログラムを人として考えてください。伝えることが多ければ多いほど、賢くなります。
0
Shane