【入門編】初心者向け:VB.NETにおけるModule(モジュール)の正しい使い方と、グローバル変数を乱用しないための設計指針 – Visual Basic (VB / VB.NET)解析バイブル

スポンサーリンク

こんにちは! 日々の開発、本当にお疲れ様です。
ExcelのVBAや古いマクロの記録から一歩踏み出し、「よし、本格的なVB.NETでアプリケーションを作ろう!」と意気込んでいるあなたへ。

今回は、VB.NETを学ぶ誰もが最初に直面する、そしてシステムの運命を分ける極めて重要なテーマについてお話しします。

そう、それは「Module(モジュール)」「グローバル変数」の正しい使い方です。

「どこからでも変数を呼び出せて、関数も自由に置けるModuleって、魔法のように便利だな……」
そう思っていませんか?

実はその便利さの裏側に、保守性をズタズタにする巨大な罠が潜んでいます。ここをクリアすれば、あなたの書くコードは「動くおもちゃ」から「プロ仕様の堅牢なシステム」へと劇的に生まれ変わります。さあ、一緒に本質を学んでいきましょう!

1. VB.NETの「Module(モジュール)」とは何か?

VB.NETにおける `Module` は、一言で言えば「インスタンス化(new)しなくても、中身をどこからでも呼び出せるカプセル」です。

通常、オブジェクト指向言語である.NETの世界では、処理を行うためにはまずクラスを実体化(`New`キーワードを使用)しなければなりません。しかし、Moduleの中に書いた変数やプロシージャ(SubやFunction)は、プログラムのどこからでも `Module名.メンバー名` (あるいは直接メンバー名)で呼び出せます。

VBA(Visual Basic for Applications)の標準モジュールに近い感覚で使えるため、初心者にとっては非常に親しみやすい存在です。

便利な使い方:共通関数(ユーティリティ)置き場

Moduleの最も正しい使い道の一つが、「どこからでも使いたい純粋な共通関数(ユーティリティ)」をまとめることです。

‘ 良い例:状態を持たない純粋な関数(引数だけで結果が決まる)
Module StringUtils

‘ 文字列が空かどうかを安全にチェックする関数
Public Function IsNullOrEmpty(ByVal value As String) As Boolean
Return String.IsNullOrEmpty(value)
End Function

End Module

このような「入力値に対して計算結果を返すだけ」の関数(副作用がない関数)を置く場所としては、Moduleは非常に優秀です。

2. なぜ「グローバル変数」の乱用は悪なのか?

しかし、Moduleの利便性に甘えて、次のようなコードを書くようになってはいけないと、伝説のアーキテクトたちは口を酸っぱくして言います。

VB
‘ 危険な例:すべてをModuleのグローバル変数で管理しようとする設計
Module AppData
Public CurrentUserId As String
Public IsLoggedIn As Boolean
Public DatabaseConnection As SqlConnection
Public RetryCount As Integer
End Module

これの何が問題なのでしょうか? 初心者が陥りがちな3大リスクを見てみましょう。

① 「誰が・いつ・どこで」書き換えたか分からない(追跡不可能の呪い)

グローバル変数は、プログラムのどこからでも読み書きが可能です。
もし「`CurrentUserId` が突然空っぽになってエラーになる」というバグが発生したとき、数万行あるコードのどこがこの変数を書き換えたのか、犯人を探すのは至難の業です。デバッグ地獄の始まりです。

② テストが不可能になる(結合度の罠)

プログラムのパーツ単体でテスト(単体テスト)をしようとしたとき、グローバル変数に依存しているコードは「特定の順番で変数に値が入っている状態」を作らないと動きません。環境や実行順序に依存するコードは、自動テストの最大の敵です。

③ マルチスレッド時代への完全な逆行

現代のPCやサーバーはマルチコアCPUが当たり前で、複数の処理を同時に行います(マルチスレッド)。グローバル変数は複数の処理から同時に書き換えられる可能性があり、データが破損する致命的なバグ(競合状態)を引き起こします。

3. オブジェクト指向に基づいた安全な設計へのステップアップ

では、グローバル変数を使わずに、どのようにデータを管理すればよいのでしょうか?
答えは簡単、「データを必要とするオブジェクト(クラス)に責任を持たせる」ことです。

先ほどの「ログインユーザー情報」を例に、グローバル変数に頼らないモダンなクラス設計を見てみましょう。

ステップ1:データを保持するクラスを作る(データモデル)

‘ ユーザー情報をカプセル化するクラス
Public Class UserSession
‘ プロパティを使って安全にデータを保持
Public Property UserId As String
Public Property UserName As String

‘ コンストラクタで初期化を強制する
Public Sub New(ByVal id As String, ByVal name As String)
Me.UserId = id
Me.UserName = name
End Sub

‘ このデータに関する振る舞い(メソッド)も持たせられる
Public Function IsAdmin() As Boolean
Return Me.UserId = “ADMIN_001”
End Function
End Class

ステップ2:必要な場所に「依存性」として渡す

グローバル変数から勝手に値を取るのではなく、「使う人に必要なものを渡す(依存性の注入)」という設計にします。

Public Class OrderProcessor

‘ フィールドとしてセッション保持用の変数を定義
Private ReadOnly _session As UserSession

‘ コンストラクタ経由で依存するオブジェクトを受け取る
Public Sub New(ByVal session As UserSession)
_session = session
End Sub

Public Sub ExecuteOrder()
‘ グローバル変数を見に行かなくても、手元の安全なインスタンスから値が取れる!
Console.WriteLine($”{_session.UserName} さんが注文を実行しました。”)
End Sub

End Class

このように設計することで、「誰がこのセッションを持っているか」「どのユーザーの権限で処理が行われているか」がコードの契約(シグネチャ)として明確になり、バグの入り込む余地が劇的に減ります。

4. まとめ:Moduleとどう付き合うべきか?

ここまでの話を整理しましょう。

  • Moduleの正しい使い道
  • 状態(変数)を持たない、純粋な共通関数(Math系やString処理など)の置き場。
  • アプリケーション起動時のエントリポイント(`Main`メソッドなど)。
  • 避けるべき使い方
  • アプリケーションの状態(ユーザー情報、設定値、フラグなど)をグローバル変数として保持すること。

「手軽だから」とModuleとグローバル変数に逃げると、コードが成長したときに必ず自分自身の首を絞めることになります。

マクロの記録やVBAのラフな記述から脱却し、クラスやインスタンスという「オブジェクト指向の武器」を手に入れたあなたなら、もう大丈夫。
「変数は必要なスコープに閉じ込め、責任の所在を明確にする」――この原則を胸に、安全で美しいVB.NETコードを書き上げていきましょう。

ここをクリアしたあなたなら、VB.NETの基本はもうバッチリです!
次回の解説もお楽しみに。お疲れ様でした!

タイトルとURLをコピーしました