プログラムを作る際、必ず変数を定義する必要があります。一言に変数と言っても、int
やstring
などの基本型だけでなく、何かのクラスオブジェクトの場合もあります。
この記事では、スコープを意識して変数を定義する理由とメリットを紹介します。
この記事のまとめ
- 変数のスコープとは、参照・更新可能な範囲のこと
- スコープの種類は、どこからでも参照できる「グローバル」や、「関数の中だけ」のスコープなどがある
- すべてグローバル変数にしてしまうと、ソースコードは書きやすくなるが、思いがけないバグが発生する可能性がある
- 基本的には関数内だけ参照・更新可能なスコープで定義し、関数の内外で受け渡ししたい場合は、引数でやりとりする
変数のスコープとは
- スコープとは、参照・更新が可能な範囲のこと
変数のスコープとは、参照・更新が可能な範囲のことです。
スコープの種類はプログラム言語の思想によって種類が様々です。
例えば、
int score
という変数を定義した場合、どこからでも参照・更新可能なのか、一部の関数の中だけで参照・更新可能なのか、を考えるのがスコープです。
スコープの種類
- グローバル
- クラス内
- 関数内
- ルーチン内
例えばC#では、以下のようなスコープがあります。
グローバル変数とは、どのクラス・関数からでも参照・更新可能な変数です。
クラス変数とは、そのクラスの中からのみ参照・更新可能。
「関数内」のみ参照・更新可能なスコープや、関数内の一部のルーチンの中だけ参照・更新可能なものなどがあります。
全てグローバル変数として定義した場合、何が懸念されるか?
- バグの温床になる
- 変数名が冗長化しやすい、多くの変数が定義されてしまう
- ソースコードが読みにくくなる
すべてグローバル変数で定義してしまえば、プログラミングが簡単にできそうです。
確かに、プログラムはたくさんのクラスや関数からできています。1つの変数をどのクラス・関数からでも参照・更新できれば、柔軟性が上がります。
しかし、問題点がいくつかあります。
1つ目は、思いがけないタイミングで変数が更新されてしまい、バグの温床になります。
例えば「得点」を保持する変数を定義した場合、
- 初期化
- 特定の科目の得点
- 合計得点
- 平均点
など、様々な利用用途・更新タイミングが考えられます。
利用用途を制限して、更新タイミングが明確に把握できていれば問題ありませんが、グローバル変数を使用するということは、これらを明確にしないといけないということです。
利用用途を分けるために、別々の変数を定義するという方法が考えられます。
2つ目の問題点は、変数名が冗長化しやすいということです。
上記の「得点」という変数の例で言えば、
- 初期化 =
initializedScore
- 特定の科目の得点 =
mathScore
,englishScore
- 合計得点 =
totalScore
- 平均点
averageScore
など、変数名が長くなってしまい、余計な変数が生まれてしまいます。
今はパソコンのCPUやメモリが多く搭載されていますので問題になりませんが、余計な変数を定義するということは、余計なメモリを消費するということに直結します。
3つ目の問題点は、ソースコードが読みにくくなることです。
グローバル変数であるということは、どこからでも更新が可能ということですので、その変数がどの値になっているかは、先頭から順番にソースコードを読んでいかないと分かりません。
規模の小さいプログラムであれば問題になりませんが、大きなプログラムであれば、もはや人間が解読できるコードからかけ離れてしまう可能性もあります。
ソースコードが読める規模というのは、保守やメンテナンスがし易くなります。
正しいスコープの使い方
- できるだけ、関数内やクラス内のスコープを使用する
- グローバル変数は基本的には使用しない
正しく変数を使うためには、できるだけ関数内のスコープに留めておきましょう。
必要であればクラス内スコープを使用し、グローバル変数の使用は避けましょう。
理由としては、上述したとおり、バグの温床になったり、ソースコードが読みにくくなるためです。
プログラムは1度作成すれば完成になることはほとんどありません。必ずといっていいほど修正が発生します。
その修正のタイミングが、まだ記憶に新しい数日後などであればいいですが、1年後や2年度、もしくは他の誰かが作ったソースコードの修正を任された場合などは、読みやすさが重要になります。
読みやすいソースコードを書くためのアイデアは、以下にもまとめていますので、よろしければご覧ください。
コメント