【実務・中級編】モーダルダイアログの戻り値(DialogResult)をカスタムオブジェクト経由で拡張し、呼び出し元へリッチなデータを返す設計パターン – Visual Basic (VB / VB.NET)解析バイブル

スポンサーリンク

VB.NETのモーダルダイアログを「最強のデータ搬送装置」に変える設計術

多くのVB.NET開発者が、モーダルダイアログから値を戻す際に「グローバル変数」や「Publicなプロパティへの直接参照」という悪魔の誘惑に負けている。

「とりあえず動けばいい」という考えで書かれたコードは、数ヶ月後のメンテナンスで必ず牙を剥く。呼び出し元と呼び出し先の密結合(Tight Coupling)は、バグの温床であり、ユニットテストを不可能にする最大の要因だ。

今日は、プロとして現場で通用する、「カスタムオブジェクト経由でリッチなデータを安全に返す」ための設計パターンを伝授する。

—

1. なぜ「DialogResult」だけでは足りないのか

標準の `DialogResult` は、単なる「OK」か「キャンセル」かのフラグに過ぎない。しかし、業務システムの実務では、「どの顧客を選んだか」「どのパラメータで処理を実行するか」「入力されたバリデーション結果はどうだったか」といった、構造化されたデータが必要になる。

これを実現するために、フォーム自体をデータコンテナとして汚染させるのではなく、「結果格納用クラス(DTO: Data Transfer Object)」を介在させるのが、堅牢なシステム設計の基本だ。

—

2. 実装パターン:Resultクラスを用いた疎結合設計

このパターンでは、呼び出し先(子フォーム)で生成した結果オブジェクトを、呼び出し元(親フォーム)が受け取る。

手順①:結果格納用クラスの定義

まずは、受け渡し専用のクラスを作る。これは単なるデータの箱だ。

”’

”’ 子フォームからの戻り値を保持するデータクラス
”’

Public Class CustomerSelectionResult
Public Property CustomerId As Integer
Public Property SelectedName As String
Public Property IsValidated As Boolean
‘ 必要に応じて複雑なオブジェクトやリストも保持可能
End Class

手順②:子フォーム(ダイアログ)の実装

子フォームは「自分の結果を自分で用意する」という責任を持つ。

Public Class CustomerSelectForm
‘ 結果を保持するプロパティ(初期値はNothing)
Public Property ResultData As CustomerSelectionResult

Private Sub btnOk_Click(sender As Object, e As EventArgs) Handles btnOk.Click
‘ データの構築とバリデーション
If Not ValidateInputs() Then Return

‘ 結果オブジェクトの生成
ResultData = New CustomerSelectionResult With {
.CustomerId = CInt(txtId.Text),
.SelectedName = txtName.Text,
.IsValidated = True
}

‘ 正常終了を通知
Me.DialogResult = DialogResult.OK
Me.Close()
End Sub
End Class

手順③:呼び出し元(親フォーム)の実装

親フォームは、子フォームが閉じられた直後に `ResultData` を安全に取り出す。

Private Sub btnOpenDialog_Click(sender As Object, e As EventArgs) Handles btnOpenDialog.Click
Using dlg As New CustomerSelectForm()
If dlg.ShowDialog() = DialogResult.OK Then
‘ ここで安全にデータを回収する
Dim res = dlg.ResultData

If res IsNot Nothing Then
Console.WriteLine($”選択された顧客: {res.SelectedName} (ID: {res.CustomerId})”)
‘ ここからDB更新やファイル出力処理へ繋げる
End If
End If
End Using ‘ Usingブロックで確実にメモリ解放
End Sub

—

3. 現場で「バグらせない」ための3つの極意

① Using ステートメントを徹底せよ

Windows Formsにおいて、フォームは `IDisposable` を継承している。`ShowDialog()` を呼ぶ際は、必ず `Using` ブロックで囲むこと。これを怠ると、特に画像やDB接続を含むフォームで、メモリリークやハンドル不足による不可解なクラッシュが発生する。

② 不変性(Immutability)を意識する

もし可能であれば、`ResultData` のプロパティを `ReadOnly` にし、コンストラクタ経由で値をセットするように設計すれば、データが途中で書き換えられるリスクをゼロにできる。

③ 戻り値のNullチェックを怠るな

`DialogResult.OK` が返ってきたとしても、何らかの理由で `ResultData` がセットされていない可能性を考慮せよ。「呼び出し元で `Nothing` チェックを行わない」のは、実務においては手抜きである。

—

まとめ:アーキテクトからの助言

今回紹介した「DTOを介したデータ受け渡し」は、単なるコードの書き方ではない。「どの部品が何を知っているべきか(関心の分離)」という設計思想そのものだ。

  • 子フォームは「どうデータを集めるか」を知っている。
  • 呼び出し元は「結果をどう料理するか」を知っている。
  • DTOは「データの形」だけを知っている。

この境界線を守るだけで、あなたの書くVB.NETコードは、泥臭いスクリプトから、堅牢で拡張性の高いエンタープライズ・アプリケーションへと変貌を遂げる。

「動けばいい」という次元を卒業し、保守性を愛するエンジニアであれ。健闘を祈る。

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