VB.NETで脱・スパゲッティコード!DIコンテナで実現する「美しい画面遷移」の極意
こんにちは。現場で長年VB.NETと格闘してきたエンジニアです。
「Form1からForm2を開いて、値を渡して戻る……」
VB.NETで業務アプリを作っていると、誰もが一度は通る道ですね。しかし、多くの人がここで「Form1の中にForm2が直接書き込まれている(密結合)」という罠にハマり、最終的に修正不可能なスパゲッティコードを生み出してしまいます。
今日は、そんな泥沼から抜け出し、プロの現場で通用する「DI(依存性の注入)」を用いたクリーンな画面遷移アーキテクチャを伝授します。ここをクリアすれば、あなたのコードは「書き捨てのプログラム」から「保守可能なソフトウェア」へと進化しますよ。
—
1. なぜ「直接呼び出し」は悪なのか?
初心者がやりがちなのは、Form1の中に `Dim f2 As New Form2` と書いてしまうこと。一見簡単ですが、これには致命的な欠点があります。
- 密結合: Form2の仕様が変わると、Form1も修正しなければならない。
- メモリ管理の崩壊: フォームが閉じてもインスタンスが残り続け、メモリリークの原因になる。
- テスト不能: 画面を表示するたびに本物のフォームが立ち上がるため、単体テストができない。
これらを解決するのが「インターフェイス」と「DI(依存性の注入)」です。
—
2. アーキテクチャの設計図:インターフェイスを活用する
画面同士を直接くっつけるのではなく、「ルールブック(インターフェイス)」を介して会話させます。
ステップ1:ルールを定義する(インターフェイス)
まず、画面が持つべき機能をインターフェイスとして定義します。
‘ IView.vb – 画面が守るべきルール
Public Interface IView
Sub ShowView()
Sub CloseView()
‘ 必要に応じて、データのやり取り用プロパティも定義
Property Data As String
End Interface
—
3. 実践!DIコンテナで画面を管理する
DIコンテナとは、簡単に言えば「オブジェクトの作成と管理を代行してくれる管理人」です。今回はシンプルに、フォームを管理する「ナビゲータークラス」を作成しましょう。
ステップ2:ナビゲーター(画面遷移の司令塔)を作る
‘ Navigator.vb – 画面遷移を集中管理するクラス
Public Class Navigator
‘ 画面を生成して表示する責任を一手に引き受ける
Public Sub OpenForm(Of T As {IView, New})()
Dim view As New T()
view.ShowView()
End Sub
End Class
ステップ3:フォームの実装(インターフェイスの継承)
フォーム側は、インターフェイスを実装することで「誰から呼ばれてもいい状態」になります。
‘ Form2.vb
Public Class Form2
Implements IView
Public Sub ShowView() Implements IView.ShowView
Me.ShowDialog() ‘ ダイアログとして表示
End Sub
Public Sub CloseView() Implements IView.CloseView
Me.Close()
End Sub
Public Property Data As String Implements IView.Data
‘ フォームの破棄時にメモリを解放する(Disposeのオーバーライド)
Protected Overrides Sub Dispose(disposing As Boolean)
MyBase.Dispose(disposing)
End Sub
End Class
—
4. 呼び出し側のコードを劇的に簡潔にする
これまで `New` していた場所が、たった一行の呼び出しに変わります。
‘ Form1.vb
Private Sub btnOpen_Click(sender As Object, e As EventArgs) Handles btnOpen.Click
‘ ナビゲーター経由でForm2を呼び出す
Dim nav As New Navigator()
nav.OpenForm(Of Form2)()
End Sub
どうですか? Form1の中にForm2の影すら見えませんね。これが「疎結合」の力です。
—
5. 現場で役立つ!メモリ管理の極意
VB.NETのWindows Formsでメモリリークを防ぐには、以下の3原則を体に叩き込んでください。
1. `ShowDialog` を使え: `Show` はフォームが残り続けるため、閉じるまで制御が戻る `ShowDialog` が業務アプリには最適です。
2. `Using` ステートメントの活用: リソースを確実に解放するために `Using` を使いましょう。
Using f2 As New Form2()
f2.ShowDialog()
End Using ‘ ここで自動的にDisposeが呼ばれる
3. イベントハンドラの解除: フォームを閉じるとき、`RemoveHandler` を忘れないでください。これが残ると、ガベージコレクションがフォームを回収できず、メモリが食い尽くされます。
—
最後に:先輩からのアドバイス
「コードが動くこと」は最低条件です。本当に大切なのは、「半年後の自分が、このコードを読んで泣かないか」です。
今回紹介した「インターフェイス」と「DI」の考え方は、少し難しく感じるかもしれません。でも、一度覚えてしまえば、どんなに複雑な業務アプリでも怖くなくなります。
まずは小さな機能からで構いません。`New` を直接書くのをやめて、インターフェイス越しに画面を呼び出す練習をしてみてください。その小さな一歩が、あなたを伝説のエンジニアへと導くはずです。
何か詰まったら、いつでも聞いてくださいね。応援しています!
