何であれ、一つの側面からの考え方に縛られて柔軟性を欠く事は、長い人生において幸福とは言えない結果をもたらす。
プログラミングの世界でもそういった事は多々あり、「~は悪だ」という考えに固執していると、往々にして良い結果にはならない。今回は、その中でも「マジックナンバー・マジックストリングは悪だ」という決め付けに一石を投じる。
如何なるマジックナンバーも嫌い、あらゆる数値を定数や設定ファイルにしてしまうと可読性が非常に下がる。以下の 2 つの例はどちらが見易いだろうか。
class Program
{
private string _option;
private string _targetFile;
static void Main(string[] args)
{
_option = args[0];
_targetFile = args[1];
}
}
class Program
{
private const int ArgsIndexOption = 0;
private const int ArgsIndexTargetFile = 1;
private string _option;
private string _targetFile;
static void Main(string[] args)
{
_option = args[ArgsIndexOption];
_targetFile = args[ArgsIndexTargetFile];
}
}
コマンドライン引数から値を取り出しているだけだが、マジックナンバーを完全に避けようとする人は2番目のコードを書く。コマンドライン引数の値は、しっかりした名前を持った変数に値を入れられているのだから「ArgsIndex~」の定数は以後使用されない。この定数はまったく無意味である。
ASP.NET の開発では、文字列で何かをするという事が非常に多い。最終的に単なる文字列である HTML を出力する事が目的だから当たり前である。ASP.NET で頻繁に使用されるメソッドの1つに Page.FindControl、Control.FindoControl がある。サーバーコントロールの ID を文字列で指定してサーバーコントロールの参照を取得するメソッドだ。
private void Func()
{
TextBox passwordTextBox = FindControl("PasswordTextBox") as TextBox;
if (passwordTextBox == null) throw new ApplicationException("id = PasswordTextBox の TextBox がない");
string password = passwordTextBox.Text;
}
private const string PasswordTextBoxID = "PasswordTextBox";
private void Func()
{
TextBox passwordTextBox = FindControl(PasswordTextBox) as TextBox;
if (passwordTextBox == null) throw new ApplicationException(String.Format("id = {0} の TextBox がない", PasswordTextBoxID));
string password = passwordTextBox.Text;
}
GridView 内のテキストボックス等、状況によって数が変化するコントロールは、否応なしに FindControl を使用してコントロールの参照を取得せざるを得ない。
さて、上記の2つを見比べて、どちらのコードが見易いだろうか?
「直値、あるいは直文字列は保守性が悪い」という意見もあるだろうが、それは違う。一体、何を保守すると言うのだろうか?コマンドライン引数の1番目と2番目を入れ替えたい場合に備えるのか?aspx ファイルに書いてある「PasswordTextBox」という文字列を変更したい場合に備えるのか?そのような類の保守に労力を使う事に何の意味があろうか。
コマンドライン引数はプログラム開始直後に処理する。これだけで良い。コマンドライン引数のインデックスをわざわざ目の届かない所に移す必要はない。あろうことか、コマンドライン引数のインデックスを設定ファイルにしてしまうなど愚の骨頂である。
aspx ファイルに書いてあるサーバーコントロールの ID を定数にしても意味がない。どうせ、aspx ファイルに書いてある文字列と定数はリンクしていない。どちらか一方を変更したら、もう片方を探して変更せねばならない。しかも、定数は「意味的に」リンクしていないのだから探すのは大変だ。だったら、そのサーバーコントロールを処理しているところを探す方が「意味的に」リンクしているので探しやすい。そもそも ID は変更されるという前提を持ってはいけない。
マジックナンバーは、意味が全く分からないから駄目なのだ。
double area = 2 * 2 * 3.14;
上記の 3.14 は十中八九「円周率」だ。しかし、100 % とは言い切れない。2 は半径か?このように意味が明白でない場合は、下記のように名前を付けた方がよいのは当然だ。
double radius = 2;
double pi = 3.14;
double area = radius * radius * pi;
マジックのような不思議で意味のわからない数値をマジックナンバーというのであり、たとえ直値でも意味のある値はマジックナンバーとは言わない。
「コマンドライン引数の1番目」「サーバーコントロールの ID の名前」という立派な意味を持つ値や文字列はマジックではない。