2012年04月22日

VBScript の Option Explicit 変数宣言不要論

VBScript のファイルの先頭に、Option Explicit を記述すると、変数の Dim 宣言を必須にすることで、面倒だけど、いろいろな警告によって品質の高いプログラムを低いコストで作ることができると考えられてきましたが、そうでもないようです。

変数の宣言が必要なプログラミング言語の場合、変数の宣言をし忘れて書き直すことがよくあり、コストになっています。 さらに、任意型の宣言は、意味がよく分からないため、可読性を下げます。 逆に言えば、変数宣言が不要であれば、可読性を上げるのです。 このためか、新しいプログラミング言語 Python などは、ローカル変数の宣言を無くしています。

VBScript で、Option Explicit を使った場合、よく遭遇するのは、変数を宣言していないというエラーです。 このエラーを対処するには、デバッガーを使う形で最初からやり直して、衝突している変数を知って、Dim 宣言を追加して、また最初からやり直す必要があります。 つまり、2回も再起動が必要になります。 これは結構なコストです。 もし、デバッガーが無ければ、対処は更に困難になります。 Option Explicit を使っている人は、このコストの大きさに気づいていません。(私も気づくのに時間がかかりました)

VBScript の Dim は、変数名の衝突を早期に検出すること以外に機能はありません。 プログラミング言語によっては変数の型を決めることがありますが、VBScript は、変数にどの型の値でも入るため変数の型を決める機能はありません。

衝突を検出するだけの命令文は、プログラムが何かをする命令文ではありません。 これは問題です。 プログラムが何をしようとしているのかを理解しようとするときに、実は何もしていないモノに遭遇しても、何をしようとしているのか懸命に探します。 この脳の状態で、実は何もしていない、ということに気づくのは大変なことです。 大きなコストになります。 また、何もしていないことを読まされることは不快です。

Dim 命令の説明でよくあるのが、使っている変数を挙げているとありますが、別に Dim 命令が無くても使っている変数は分かります。 変数を初期化している文で、よく理解できます。 Dim はくどいのです。

変数宣言を不要とした場合、変数名が衝突していないことを裏付けることが、Dim 文を実行するときから、テストに合格するときまで遅れます。 これにより、衝突している問題を解決することが、少しだけ難しくなります。

どれだけ難しくなるかを、見てみましょう。

Sub MyTest()
 name = "MyName"
 name = "YourName"
 Assert FuncA( name ) = "Taro"
End Sub

これは、name = "MyName" であることを期待しているテスト・スクリプトで、name が "YourName" に変わったためにテストに失敗しています。 この原因を追究するときは、name の値をどこで代入しているかを調べることになります。 name を上方向に検索して、name = "YourName" が見つかり、それを対処することになります。 実は、これは、変数が衝突したときよりも発生頻度が高い、一般的なミスによって name の値が違っているケースと同じ対処法です。 確かに Dim 文によって衝突を検出した方が速く原因が特定できますが、検出しなくても一般的な対処法で済むわけです。

ローカル変数同士が衝突した場合、原因は、その関数の中だけに絞られます。 つまり、呼び出した先の関数に原因がある一般的なミスに比べると、原因がある範囲が限定的なので、対処が比較的簡単です。

グローバル変数同士の衝突は、一般的なミスの対処と変わりません。 また、Option Explicit を使っても、VBS ファイルをモジュール別に分けていると、Dim を使っても衝突を検出できません。

ローカル変数のつもりで使った変数が、実はグローバル変数だったとき、つまり、グローバル変数がローカル変数に衝突した場合は、ローカル変数のつもりでデバッグを行おうとするため、対処が困難でしょう。 しかし、グローバル変数の名前の先頭に "g_" を付けるコーディング・ルールなどを適用すれば、その問題は無くなります。 Python では、「global」 命令によって問題を回避しています。

変数名が衝突するミスは、Dim 文の記述を忘れるミスに比べると、かなり発生頻度が低いです。 衝突する頻度が低い理由は、意味が異なる変数には、通常異なる名前を付けるからです。 Dim 文の記述を忘れることが多い理由かは、Dim が何かをする命令文ではないからです。 何かをさせるために記述しているときに、させることが全て記述できたら、完成と思うからです。

以上から、発生頻度と修正コストを総合して考えると、Option Explicit をつけた方がコストが高くなるというわけです。

下記のホームページでは、Dim の必要性を説明していますが、必要の根拠となる機能が無くても、すぐに別のエラーで知ることが出来るため、問題として挙げられていることが真の問題の解決を困難にすることはありません。

参考: 変数宣言を強制しないといけないのか。
http://www.asahi-net.or.jp/~ef2o-inue/vba_k/sub04_200_030.html

sage_p at 22:48│Comments(3)TrackBack(0) プログラミング 

トラックバックURL

この記事へのコメント

1. Posted by 通りすがりのVBer   2012年04月23日 00:43
Option Explicitをつけないことによる最大の恐怖は「変数名の間違い」ではないでしょうか。

『処理は正しく流れたようだが、結果が期待した通りにならない。コードを追って見たら○○Dateを○○Dataと書いてた。また、○○Flagを○○Flgと書いていた。』

こうしたミスは起こりうると思いませんか?
こういうエラーの出ないバグほど調査コストが大きくなりますよね。
また、これは全ての変数のスペルチェックを自分でしない限り、バグが潜在しているリスクを表してもいます。

Option Explicitはスペルミスというリスクを減らせるだけでも大きなコスト減に繋がると思うのですが。
2. Posted by T's-Neko   2012年04月29日 22:23
確かに指摘のとおりのミスが起きたときは、変数宣言を必須にしないときより、修正コストは増えます。 しかし、最大の恐怖とおっしゃるほど重大な問題になることは、ほとんどありません。 一般的な論理的なミスと変わりません。

その代わりに、変数の宣言をし忘れることが頻繁にあるために、そのコストが高いという話です。

私は、わかりやすい変数名にするために変数名が長くなる傾向があるため、変数名は常にコピー&ペーストしているためか、スペルミスはほとんど発生しません。 それが、Option Explicitをつけない方が修正が少ないと感じている要因かと思います。
3. Posted by \・\a\I\e \N\o\×\1   2013年11月16日 12:38
\3\a\o\E£o\¨\e\a\1 \¬c`\C\o\Nc`\A\£ mm£¬O≫°aμA?E\¬c`\C\o\Nc`\A\££D£I£¨£A£´…§?{!¢・u£3£¶£a£i£c?e?e?aO≫≫O?e´o?-??£I£I£¨\μ\A\≪c`\Uc`\e£2??・O3I¶E£c\μ\?\o?C?1!£AADD?I?r?aADDO?C?a?a3O?A?E?E?i?T?1!£E≪Ia?I±!?A?i!¢\μ\?\E?aIA2??I\・\s?A?i??C\1\i£¨£´?≪EuE≪?A£c?¬?¢?e?T?1!£AU?E?I!¢μ×Aa\i\¶c`?E?A?i!¢\E\i\e2?・O?E\・\s?A?i?¬?¢?e?T?1!£\I\o\E\e?IA?oA?C!¢E≪IaμA?EER・O?-?i???C?1!£EC・C?3?I?C≫a?E£!

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔