はじめに
この記事は Visual Basic Advent Calendar 2018 の 16日目の記事です。
VB.NET って、言語仕様としては悪くないのに、ディスられ過ぎじゃない? 冷遇されすぎだよね??
そういった思いの中、「VB.NET のここがいい!」「こんなメリットや長所があるよ!」と思った事をつらつら書いていくエントリです。
VB.NET のいい所
オブジェクト指向と手続き型を併せた柔軟さを持つ
VB.NETは、れっきとしたオブジェクト指向言語です。
なので、Java や C# のようなピュアなオブジェクト指向としての書き方が可能です。
ですが、VB6 から VB.NET に流れてきたシステムやプログラマが多いせいか、手続き型のように書いても、特にマナー違反として非難される事は少ないのではないかと思います。
つまり要所において、手続き型言語の書き方をしてもよし、オブジェクト指向言語の書き方をしてもよし、という構成も、問題ないケースが多いのではないでしょうか。
「なんじゃそりゃ。」と思われるかもしれませんが、Python もそういう性質を備えているのでは?
Python をピュアなオブジェクト指向言語としてのみ使用するエンジニアは少数派なんじゃないかと思います。
(手続き型が最適な部分では手続き型を使用し、オブジェクト指向型が最適な場面ではオブジェクト指向型を使用する。)
それと同じような感覚だと思って頂ければ。
ダックタイピング可
遅延バインディングが出来るんで、こういう風にダックタイピングができる。
Dim individualService As Object
individualService = serviceFactory.CreateObject(params)
resDto = individualService.Execute
色々と端折ってるけど、だいたいこんな事しています。
- 「individualService」という、型を明示しない変数を定義
- 取得した パラメータ(POSTとか)の値により、実行する内容を変更。(パラメータの内容によって、生成するオブジェクトを変える)
- 生成したインスタンスの Executeメソッドを実行。
要は、「メイン処理に変更を加えることなく、機能を拡張できるようにする」という、オブジェクト指向なら、どの言語でもやってるような事を書いてます。
Java のような静的型付けのオブジェクト志向言語でこういう事を実現しようとすると、インターフェースを定義してクラスに implement して、場合によってはアダプタクラスを定義して・・・
と、結構面倒くさい。
初歩的なバグを減らす事ができる反面、
「こんな感じで行けるか、ちょっと試してみたいだけなのに、こんなに書かないといけないの?」と
妙なストレスを溜め込むことになる。
そうではなく、インターフェースもアダプタクラスも定義せずに、オブジェクトにメソッド生やす書き方は、
保守性よりも開発スピードを重視したい場面において、極めて有効に働いてくれる。
もちろん、Java みたいにガチガチに固める事もできる。
プロジェクトやチームに合わせて、どちらも柔軟に選択できるというのは、オブジェクト指向言語の中では珍しい位置付けなんじゃないかと思う。
C# で似たような事を実装しようとすると、Dynamic 型を使う事になるけど、そういう事したら行儀悪いと怒られそうな気がする。
標準機能にて、全角⇔半角の変換ができる
C# を触っててちょっとショック受けるのが、「全角⇔半角」の変換を標準機能として用意していない。
なので、以下のような工夫をする事になる。
- 自前で変換処理を実装する
- VB.NETの標準関数(StrConv)を使う
- サードパーティ製ライブラリを使う
上記の通り、VB.NET は標準で変換機能を用意してくれているので、変に悩まなくて済む。
列挙型が使いやすい
まずは C#
enum Signal:int
{
Red = 0,
Yellow = 1,
Blue = 2,
White = 3,
Black = 4
}
続いて VB.NET
Public Enum Signal As Integer
Red = 0
Yellow = 1
Blue = 2
White = 3
Black = 4
End Enum
VB.NET の場合、改行が構文の終端を意味するので、「,」(カンマ)を記述せずに済む。
列挙型の内容を1行にまとめて書く事なんてレアケースなんで、こっちの方がいいんじゃないかと思う。
また、使う場合も C# とは差がある。
まずは C#
if (param1 == (int)Signal.Red)
{
Console.WriteLine("Stop!");
}
続いて VB.NET
If parame1 = Signal.Red Then
Console.WriteLine("Stop!")
End If
C# は型を厳密に扱っているんで、どうしてもキャストが必要になるが、VB.NET は型のチェックが比較的緩いため、こういう書き方ができる。
列挙型にしている時点で、「0」と「"0"」の区別が必要な場面なんてほぼ無い訳だし、厳密に型チェックする事は、メリットよりもデメリットの方が大きいと感じる事が多い。(個人的感想。あくまで列挙型においての話です。)
ここでもわざわざキャストしてやらんといけないの?と、妙に不便さを感じる。
JavaScriptやPHPでも、等価演算子を全ケースにおいて「===」を使いたい訳ではなく、場面によっては「==」での比較がベストなケースもあるんじゃないかと思う。
VB.NETはそういった場面にも柔軟に使い分けができる。
With が使える
Python にもある With 構文が使える。
まずは C#(Withを使わない書き方)
User _user = new User();
_user.id = 1;
_user.Name = "Tom";
_user.Age = 30;
_user.JobCode = 5;
_user.IsMarried = true;
同じ事を VB.NET で With を使うと、こう書ける。
Dim _user = New User()
With _user
.Id = 1
.Name = "Tom"
.Age = 30
.JobCode = 5
.IsMarried = True
End With
便利くない?
With のスコープを無暗に広げたり、入れ子にしたりすると、あっという間にソースがカオス化するんで乱用は避けた方がいいけど、適切に使う分には、コードが凄くすっきりする。
個人的には、オブジェクト指向型言語においては、とっても有用な構文だと思ってる。
なんで C# でサポートしてないのか不思議なくらい。
構文の終わりの文字が不要
まずは C#。
User _user = new User();
_user.id = 1;
_user.Name = "Tom";
_user.Age = 30;
_user.JobCode = 5;
_user.IsMarried = true;
続いて VB.NET。
Dim _user = New User()
_user.Id = 1
_user.Name = "Tom"
_user.Age = 30
_user.JobCode = 5
_user.IsMarried = True
こんな感じに、C#は構文の終端に「;」が必要だが、VB.NETでは不要となっている。
ちょっとした事かもしれないけど、大量にコードを書いていくうえで、この差は大きい。
この快適さは Ruby や Python が好きな人とかは分かってくれるんじゃないかと思う。
引数が空の場合、「()」を省略できる
まずは C#
innerValue1 = param2.Trim();
innerValue2 = param2.ToString();
innerValue3 = param2.ToUpper();
VB.NET だと、こう書ける。
innerValue1 = param2.Trim
innerValue2 = param2.ToString
innerValue3 = param2.ToUpper
上記の param2 は、String型です。
Trim や ToString といった標準関数を例に出していますが、自身で定義したメソッドについても同様です。
個人の好みによる所も大きいんだろうけど、「() って書く必要ある?」と思ってしまう。
短く書ける方法があるなら、そっちがいい。
if 文における、つまらないコーディングミスが回避できる
まずは C#
isSwitchOn = false;
if (isSwitchOn = true)
{
Console.WriteLine("スイッチがONの時の処理");
}
else
{
Console.WriteLine("スイッチがOFFの時の処理");
}
続いて VB.NET
isSwitchOn = False
If isSwitchOn = True Then
Console.WriteLine("スイッチがONの時の処理")
Else
Console.WriteLine("スイッチがOFFの時の処理")
End If
上記のコードで意図している事は、
『isSwitchOn を falseにし、「スイッチがOFFの処理」を実行する』
という内容です。
が、C# 側にはコーディングミスがあるため、「スイッチがONの時の処理」に分岐します。
どういう事かと言うと、ifの条件式を、正しくは「isSwitchOn == true」と書かなければならないが、
「isSwitchOn = true」と書いてしまっているため、意図通りに条件が評価されない。
が、VB.NET はそういった処理をせず、
上記の書き方で、「isSwitchOn が True か?」を評価してくれる。
本当につまんないミスなんだけど、これが原因でハマった人は相当な数がいるのではなかろうか。
PHP とか JavaScript あたりだと特に。
総括
以上の通り、VB.NET は決して言語仕様としてダメな訳ではないと思っています。
それでも VB.NET がディスられる要因は、以下のような点でしょうか。
- COBOL や VB6 から流れてきたエンジニアに、コードが汚染されがち
- 現場によってはオブジェクト指向チックな書き方が禁止されている
- 言語が進化しても、それを取り入れる現場やプロジェクトが少ない
- AWS Lambda、Azure Functions、Cloud Functions といった FaaS (Function as a Service) からガン無視される。
- Heroku、AppHarbor、ロリポップ!マネージドクラウド といった PaaS(Platform as a Service) からもガン無視される。
- Microsoft が力を入れてるように見えない
- .NETのコミュニティ間でも、話題的に歓迎されにくい
- 「VB」という響きだけで無条件に見下す人が一定数居る
(追記:AWS Lambda にて VB.NET がサポートされました。)
といったように、あくまで VB.NETの言語仕様そのものが主な原因じゃない・・・
のではないかと思う。
読み手によっては、C# をディスっていると受け取られるかもしれませんが、特にそういった意図はありません。C#も好きでよく使っています。
が、C#のいい所は、色んな人が色んな所でアピールしているので、別にここで書かなくてもいいかな、と思って端折りました。
というか、VB.NET はタダでさえディスられる事が多いんで、これくらいは許して・・・。