【テクニカル・上級編】Windows Formsの画面遷移における状態保持とメモリ管理:複数フォーム間の密結合を断ち切りDIコンテナを活用した保守性の高い設計 – Visual Basic (VB / VB.NET)解析バイブル

スポンサーリンク

Windows Formsの呪縛を解く:密結合を排した「画面遷移アーキテクチャ」の極意

多くのVB.NETエンジニアが、`Form1.Show()` と `Me.Hide()` の連鎖という「スパゲッティの迷宮」で立ち往生している。これは単なるコードの汚染ではない。メモリリーク、イベントハンドラの二重登録、そしてDispose漏れという、Windows Formsにおける「死の三重奏」を奏でているに等しい。

長年レガシーシステムの再構築に従事してきた経験から断言する。画面遷移を「画面同士の直接参照」で実装している限り、そのシステムは負債である。

本稿では、DIコンテナを応用した疎結合な画面遷移アーキテクチャを提示する。

—

1. なぜ「直接参照」がシステムを殺すのか

`Form1` が `Form2` を `New` して呼び出す。このとき、`Form1` は `Form2` の存在を物理的に知る必要がある。これではユニットテストは不可能であり、メモリのライフサイクル管理は個々の開発者の「善意」に委ねられることになる。

真のアーキテクトは、「画面は単なる表示器(View)であり、ビジネスロジックや遷移制御とは別個の存在である」と定義する。

2. インターフェイスによる抽象化とDIの導入

まずは、各フォームを制御するための抽象化を行う。ここで重要なのは、フォームの生成を自前で行わず、DIコンテナ(あるいはシンプルなファクトリパターン)に委譲することだ。

‘ 画面遷移を抽象化するインターフェイス
Public Interface IView
Sub ShowView()
Sub CloseView()
End Interface

‘ Form2のインターフェイス定義
Public Interface IForm2
Inherits IView
Property DataContext As String
End Interface

3. 画面遷移制御クラス(Navigator)の構築

フォーム同士を直接会話させず、`Navigator` クラスを介在させる。これにより、メモリ管理を一元化できる。

Public Class ViewNavigator
‘ フォームのインスタンスを保持し、再利用または明示的破棄を管理する
Private _currentForm As Form

Public Sub NavigateTo(Of T As {Form, IView})(factory As Func(Of T))
‘ 現在のフォームを閉じる前にリソースを明示的に解放
If _currentForm IsNot Nothing Then
_currentForm.Close()
_currentForm.Dispose()
End If

‘ コンテナからインスタンスを生成
_currentForm = factory()
_currentForm.Show()
End Sub
End Class

4. メモリ管理の極限:DisposeとGCの制御

VB.NETにおいて「フォームを閉じる」ことは、必ずしも「メモリを解放する」ことと同義ではない。特にWindows API(`SendMessage`等)をフックしている場合、`Dispose` を呼び出してもアンマネージリソースが残留することがある。

  • 明示的Disposeの徹底: `IDisposable` を実装し、`Components` コレクションの破棄を確実に行う。
  • GCの強制介入を避ける: `GC.Collect()` を安易に呼ぶのは素人の所業だ。オブジェクトのスコープを最小化し、不要な参照(特にイベントハンドラ)を `RemoveHandler` で切断することで、ガベージコレクタに「いつ掃除すべきか」を正しく教えるのがプロの仕事である。

‘ フォーム破棄時のイベントハンドラ切断(メモリリーク対策)
Private Sub Form2_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
‘ 購読しているイベントをすべて解除
RemoveHandler _service.DataChanged, AddressOf OnDataChanged

‘ アンマネージリソースの解放
‘ 必要に応じて、ここでMarshal.ReleaseComObject等を行う
End Sub

5. 結論:UIを「使い捨てのパーツ」にする

このアーキテクチャの最大の利点は、「Form2が壊れても、Form1には一切の影響がない」という点にある。開発者はインターフェイスを実装するだけで、複雑な遷移ロジックをNavigatorに投げることができる。

レガシーなVB.NET環境であっても、構造を変えるだけでパフォーマンスと保守性は劇的に改善する。

  • 密結合を断つ: `New` キーワードを避ける。
  • DIを活用する: 画面生成はコンテナかファクトリに一任する。
  • イベントを管理する: フォームを閉じる際は、必ず `RemoveHandler` で紐付けを断つ。

これが、我々アーキテクトが辿り着いた「Windows Formsを延命させ、かつ進化させるための唯一の解」である。コードは芸術ではない。極めて実用的で、冷徹なまでの論理の積み重ねであるべきだ。さあ、今すぐあなたのプロジェクトの `Form.Show()` を検索し、その呪縛を解き放て。

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