TTYF ~earlgrey の雑記~

主に自分用メモとか

VB レガシー機能の多くを封じる方法

今回は、2 年前にとある勉強会で発表した時のネタの一部ですが、今でもこれについて具体的に紹介した日本語のリソースが見当たらないので投稿することにしました。

VB6 おじさん

昨今良くネタにされる、SIer を始めとした労働集約型の開発チームだと、政治的理由でプラットフォームに VB が選択されることも良くあると思います。VB 自体はそこまで悪い言語ではないですが(ただし個人的にはやはり機能面で C# を推したいです)、そういうチームで往々にして問題になるのが、VB6 時代の知識で止まっている人たちの存在です。
私だったら VB であることはやむなしとして、なるべく最新の言語仕様による記述を心掛けたいと思うところですが、VB6 おじさん(30 歳ちょいでも結構いたりする...)はそんなのお構いなく VB6 風味のコードを量産してくれます。

IDEコンパイラレベルでの対策

Option Strict On オプションによる、型付の厳格化/遅延バインディングの抑止はわりと多くのプロジェクトで採用されているかと思いますが、これだけでもそれなりに効果的です。でもできればもうひと押し欲しい!!

Visual Studio 2010 SP1 以降が必要ですが、そんな状況では、プロジェクトファイル(.vbproj)を直接テキストエディタで開き、どこかの PropertyGroup 要素の配下に "<VBRuntime>Embed</VBRuntime>" を追加します。私はよく次の画像の位置に書いてます。

f:id:s_earlgrey:20160509014823p:plain

これを行うことで、そのプロジェクトではいくつかの VB 固有機能(多くは VB6 風味)を無効化することができます。主には次のようなものです。

次のような機能は依然として有効です。

  • モジュール
    • VB では拡張メソッドはモジュールに定義する必要があるので...。
  • 暗黙の縮小変換
    • Double から Integer への変換とか
  • Microsoft.VisualBasic.CompilerServices.Conversions クラス
  • AscW/ChrW メソッド
  • vbBack/vbCr/vbCrLf/vbFormFeed/vbLf/vbNewLine/vbNullChar/vbNullString/vbTab/vbVerticalTab 定数
  • XML リテラル
  • Function と同名の暗黙のローカル変数
  • With
  • プロパティの参照渡し
  • Nullable との比較における三値論理

というわけで、あまりうれしくない機能も残りますが(個人的に下から 4 つは心底忌み嫌っています)、わりと強力です。特に既定のインスタンスが無効化されるのはうれしいかもしれません。

注意として、CInt 等の変換関数の機能にも変化が表れます。例えば CInt("123") のような全角数字は、通常なら 123 に変換してくれますが、<VBRuntime>Embed</VBRuntime> を設定している場合は InvalidCastException になります。実行してみないと違いがわからないところが少し厄介かもしれません。
このあたりは Culture を参照するかどうかが変わってくるように感じていますが、あまり調べられていません。

現実問題

ではこの機能を使って VB6 風味のコードを積極的に制限すべきかというと、実はそうは思っていません。制限される機能は VB の持ち味でもあり、それらがないものはもはや C# の劣化版に過ぎないからです。品質に小うるさい案件では厳格なコードが必要とは思いますが、だったら素直に C# を使ったほうが良いかと。
メンバーの反発も予想されます。

というわけで、私も実際に適用したのは、限られたメンバーだけが編集するコアなライブラリのプロジェクトでだけです。

おまけ

ちなみに冒頭で触れた勉強会の発表資料はこちらです。2 年前のものですが特に加筆はしていません。

www.slideshare.net

過去に登壇したのはこの一度きりですが、また何かネタを見つけてチャレンジしたいですね。