Java屋さんからVB.netプログラマになるために

## 1. Java屋さんからVB.netプログラマになるために

基本的にJava屋さんをやっていますが、とあるプロジェクトでVB.netでプログラムを書くことになりました。
VB.netはビミョーと思っていたのですが、実はJavaと大して変わらないのではと思い、備忘録として違いを記事にしてみました。
いわゆるポエムです。
もしJava屋さんからVB.netプログラマになる機会があれば、多少なりともお役に立てればと思います。

## 2. Java と VB.net の違い

Java屋さんの視点からVB.netとの違いについて説明したいと思います。
最初からコードで見たい人は[3. サンプル](#3-サンプル)を参照ください。

### 2.1. VB.net にも Class がある

VB.netは.Net Frameworkの一員なので、オブジェクト指向言語です。
VB6から来た人は使うことが少ないようですが、VB.netでも`Class`を定義できます。
使う時も`new`してオブジェクトを生成します。

### 2.2. 命名規約（メソッド、プロパティ）は Java が LowerCamelCase で VB.net は UpperCamelCase

どちらも`CamelCase`が基本ですが、VB.netはメソッドやプロパティも`UpperCamelCase`が基本です。
Java屋さんからすると`Class`とぱっと見で違いが分かりにくいですが、そういうものです。

### 2.3. Java の package は Namespace

VB.netにもパッケージの概念があります。`Namespace`というブロックで括ります。
Javaのパッケージはディレクトリ構成と紐付きますが、VB.netの`Namespace`はディレクトリ構成とは関係しません。

あと、`Class`名と`Namespace`名で名前を使うとビルドでエラーになります。
Javaはパッケージは小文字、`Class`名は`UpperCamelCase`なので判断がつきますが、VB.netは同じ命名規約では判断が付かないからだと思います。（たぶん）

### 2.4. Java の import は Imports

Javaの`import`は`Class`を指定（staticインポートは除く）しますが、VB.netの`Imports`は`Namespace`を指定します。
Javaで`import`にパッケージを指定することはないので違和感があります。（.*は見た目で分かる）
VB.netでもエイリアスを設定する場合は末端の`Class`を指定しますが、この場合、記述が異なるため見た目で分かります。

### 2.5. 戻り値が void のメソッドは Sub 

VB.netでは戻り値の有無でメソッドを定義する方法が異なります。
戻り値が無い場合、つまりJavaだと`void`の場合、`Sub`（サブルーチン）として定義します。

### 2.6. 戻り値が存在するメソッドは Function

戻り値が存在する場合、VB.netでは`Function`（関数）として定義します。
戻り値のありなしを変える場合、VB.netだとちょこっとメンドウですね。

### 2.7. Java の static は Shared

Javaでちょっとしたユーティリティ機能を実装する時は大体`static`メソッドにするかと思います。
VB.netでは`static`ではなく`Shared`がこれに該当します。

### 2.8. Java のアノテーションは VB.net のアトリビュート

VB.netにもJavaのアノテーション相当の機能があります。それがアトリビュートです。
Javaの`Bean Validation`とほぼ同様の入力チェック用のアトリビュートが基本機能として提供されています。
詳細については[マイクロソフトのページ](https://msdn.microsoft.com/ja-jp/library/system.componentmodel.dataannotations(v=vs.110).aspx)を参照ください。

### 2.9. VB.net にもジェネリクス（、型パラメータ）がある

最近のJavaではジェネリクス（、型パラメータ）はよく見る機能かと思います。
VB.netにももちろんこの機能が言語仕様として存在します。

## 3. サンプル

サンプルとして、Javaの`Bean Validation`を利用した入力チェックと同様のことをVB.netで実現してみたいと思います。
戻り値なしの`Sub`としたので、前述の`Function`は出てきませんが、それ以外は全て詰め込んでみました。
`Bean Validation`同様、アトリビュートを利用した入力チェックはシンプル＆簡単で便利です。

```vb:User.vb
Imports System.ComponentModel.DataAnnotations

Namespace Com.Example.Demo
    Public Class User
        <Display(Name:="ユーザID")>  _
        <Required(ErrorMessage := "{0} は必須入力です。")> _
        Public Property UserId As String
        
        <Display(Name:="名前")> _
        <Required(ErrorMessage := "{0} は必須入力です。")> _
        Public Property Name As String

        <Display(Name:="年齢")> _
        <StringLength(3, MinimumLength :=1 ,ErrorMessage := "{0} は{2}桁以上{1}桁以内で入力してください。")> _
        Public Property Age As String
    End Class
End Namespace
```

```vb:ValidateService.vb
Imports System.ComponentModel.DataAnnotations
Imports System.Collections.Generic

Namespace Com.Example.Demo
    Public Class ValidateService
        Public Shared Sub Validate(Of T)(target As T)
            Dim validationResults As New List(Of ValidationResult)
            Dim vc As New ValidationContext(target, Nothing, Nothing)
            Dim isValid As Boolean = Validator.TryValidateObject(target, vc, validationResults, true)
            If validationResults.Count > 0 Then
                Console.WriteLine("入力値チェック [NG]")
                For Each err As ValidationResult IN validationResults
                    Console.WriteLine("{0} : {1}", err.MemberNames(0), err.ErrorMessage)
                Next
            Else
                Console.WriteLine("入力値チェック [OK]")
            End If
        End Sub
    End Class
End Namespace
```

```vb:App.vb
Namespace Com.Example.Demo
    Public Module App
        Public Sub Main()
            Console.WriteLine("// ------- Validate 1 -------")
            ' 入力データ
            Dim input01 As new User()
            ' 入力値チェック
            ValidateService.Validate(Of User)(input01)

            Console.WriteLine("// ------- Validate 2 -------")
            ' 入力データ
            Dim input02 As new User()
            input02.UserId = "123456"
            input02.Name = "TARO TOYOSU"
            input02.Age = "1234"
            ' 入力値チェック
            ValidateService.Validate(Of User)(input02)

            Console.WriteLine("// ------- Validate 3 -------")
            ' 入力データ
            Dim input03 As new User()
            input03.UserId = "123456"
            input03.Name = "TARO TOYOSU"
            input03.Age = "123"
            ' 入力値チェック
            ValidateService.Validate(Of User)(input03)

        End Sub
    End Module
End Namespace
```

Javaは`javac`でコンパイルしますが、VB.netは`vbc`でコンパイルします。
もちろんJavaにMavenやAntのようなビルドツールがあるようにVB.netにも`MsBuild`というビルドツールもあります。

```bat:build.bat
@echo off
set DOTNET_HOME=C:\Windows\Microsoft.NET\Framework64\v4.0.30319
set path=%path%;%DOTNET_HOME%
vbc /out:DemoApp.exe /r:System.ComponentModel.DataAnnotations.dll ^
/r:System.ServiceModel.Web.dll ^
App.vb User.vb ValidateService.vb
```

`DOTNET_HOME`の環境変数は自身の環境に合わせて修正してください。
全てのファイルを同一ディレクトリに格納して`build.bat`を実行すると`DemoApp.exe`が作成されます。

```console:実行結果
C:\demo>build.bat
Microsoft (R) Visual Basic Compiler version 14.7.2558
for Visual Basic 2012
Copyright (c) Microsoft Corporation.  All rights reserved.

This compiler is provided as part of the Microsoft (R) .NET Framework, but only supports language versions up to Visual Basic 2012, which is no longer the lates
t version. For compilers that support newer versions of the Visual Basic programming language, see http://go.microsoft.com/fwlink/?LinkID=533241


C:\demo>DemoApp.exe
// ------- Validate 1 -------
入力値チェック [NG]
UserId : ユーザID は必須入力です。
Name : 名前 は必須入力です。
// ------- Validate 2 -------
入力値チェック [NG]
Age : 年齢 は1桁以上3桁以内で入力してください。
// ------- Validate 3 -------
入力値チェック [OK]

C:\demo>
```

## 4. さいごに

今回はJava屋さんの視点からJavaとVB.netの違い（一部）について説明しました。
VB.netはオブジェクト指向言語である.Net Frameworkの一員なので、同じオブジェクト指向言語であるJavaとそれほど変わらないというのが分かったかと思います。
C#であればさらにJavaに近いのですが、（残念ながら未だに）**VBが大好きというプロジェクトも多々ある**のでVB.netを利用することになった際にお役に立てれば幸いです。