例外処理のベストプラクティス(VB/フォーム編)

VB

はじめに

以下記事のフォーム版となりますが、基本的な考え方は以下記事を参照してください。

こんなエラーメッセージボックスを見たことはありませんか?

普段システムを利用している人なら一度はこんなエラーメッセージボックスを見たことがあるのではないでしょうか。

使っている側からすると、怖い印象がありますよね。どうしたらよいのかわかりませんし…

このメッセージは何かというと、例外エラーが発生したけど、Try~Catchで捕捉できなかった場合に表示される .NET Framework 標準のエラーメッセージです。つまり、上手く例外エラーを処理できていないことを意味しています。

私はこのようなメッセージボックスは極力表示させないようにし、代わりの独自のエラーメッセージボックスを表示させるようにしています。

この記事では、その方法について、個人的なベストプラクティスとして2つご紹介します。

個人的なベストプラクティス

独自のエラーメッセージボックスを作成する

既に完成されているシステムに対しては、独自のメッセージボックスを作成することは難しいと思いますが、新規で作成するシステムに関しては、例外エラーが発生したときに表示される共通のエラーメッセージボックスを作成した方が良いです。さほど工数もかかりませんので。

例えば、以下のようなメッセージボックスです。

利用者側から見ると、第一印象は.NET Framework標準メッセージボックスの時とさほど変わらないかもしれませんが、2つのことがわかるようになりました。

1つ目は、「管理者に連絡すればよいこと」です。.NET Framework標準メッセージボックスでは、利用者側がこの後何をすれば良いのかわかりませんでしたが、この独自メッセージボックスでは、管理者に連絡すればよいことがわかります。

2つ目は、「エラー内容をログファイルに保存できること」です。「名前を付けて保存」ボタンを押下することで、例外エラーの内容をログファイルに出力することができます。管理者に連絡する時に、このエラーログを合わせて送れば、障害調査をスムーズに進めることができます。

ここでは、ソースコードの一部をご紹介します。

VB
Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Try
            Debug.WriteLine("処理開始 - Button1_Click")
            Method1()
            Debug.WriteLine("処理終了 - Button1_Click")
        Catch ex As Exception
            Dim errorMessageBox As New ExceptionMessageBox
            errorMessageBox.Exception = ex
            errorMessageBox.AdditionalInformation = "" '補足情報があればココにセットする
            errorMessageBox.ShowDialog()
        End Try
    End Sub

    Private Sub Method1()
        Dim num As Integer
        num = "A"
    End Sub
End Class
VB
Public Class ExceptionMessageBox

    Public Property Exception As Exception
    Public Property AdditionalInformation As String

    Private Sub ErrorMessageBox_Load(sender As Object, e As EventArgs) Handles Me.Load
        PictureBoxIcon.Image = SystemIcons.Error.ToBitmap
        Dim addMessage As New Text.StringBuilder
        addMessage.AppendLine("発生時刻:" & Now.ToString("yyyy/MM/dd HH:mm:ss"))
        addMessage.AppendLine("----------------------------------------------------------------------------------------------------------------")
        Me.TextBoxDetail.Text = addMessage.ToString & Exception.ToString

        Dim add2Message As New Text.StringBuilder
        add2Message.AppendLine("")
        add2Message.AppendLine("---------------------------------------------------------------------------------------------------------------")
        add2Message.AppendLine("追加情報:")
        add2Message.AppendLine(AdditionalInformation)
        add2Message.AppendLine("---------------------------------------------------------------------------------------------------------------")
        Me.TextBoxDetail.AppendText(add2Message.ToString)
    End Sub

    Private Sub ErrorMessageBox_Shown(sender As Object, e As EventArgs) Handles Me.Shown
        Me.ButtonSave.Focus()
    End Sub

    Private Sub ButtonSave_Click(sender As Object, e As EventArgs) Handles ButtonSave.Click
        Using sfd As New SaveFileDialog()
            sfd.FileName = Now.ToString("例外エラー情報_yyyyMMdd_HHmmss") & ".log"
            sfd.Filter = "ログファイル(*.log)|*.log|すべてのファイル(*.*)|*.*"
            sfd.FilterIndex = 1
            sfd.Title = "保存先のファイルを選択してください"
            sfd.RestoreDirectory = True
            sfd.OverwritePrompt = True
            sfd.CheckPathExists = True
            If sfd.ShowDialog() <> DialogResult.OK Then Return
            Using objSW As New System.IO.StreamWriter(sfd.FileName, False, System.Text.Encoding.GetEncoding("shift_jis"))
                objSW.WriteLine(Me.TextBoxDetail.Text)
            End Using
        End Using
    End Sub

    Private Sub ButtonClose_Click_1(sender As Object, e As EventArgs) Handles ButtonClose.Click
        Me.Close()
    End Sub

    Private Sub TextBoxDetail_KeyDown(sender As Object, e As KeyEventArgs) Handles TextBoxDetail.KeyDown
        If e.KeyCode = Keys.A AndAlso e.Control Then
            DirectCast(sender, TextBox).SelectAll()
        End If
    End Sub

End Class

改良することで、例えば「管理者に自動メール送信をする」や「エラー発生時の画面のスクリーンショットを自動取得する」ことも出来るようになると思います。独自のメッセージボックスであれば、機能を後から付け加えることができるので便利です。

イベント単位に例外エラー捕捉する

面倒ですが、すべてのイベント処理で例外エラーを捕捉するようにします。以下のコードとなります。

VB
Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Try
            Debug.WriteLine("処理開始 - Button1_Click")
            Method1()
            Debug.WriteLine("処理終了 - Button1_Click")
        Catch ex As Exception
            Dim errorMessageBox As New ExceptionMessageBox
            errorMessageBox.Exception = ex
            errorMessageBox.AdditionalInformation = "" '補足情報があればココにセットする
            errorMessageBox.ShowDialog()
        End Try
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        Try
            Debug.WriteLine("処理開始 - Button2_Click")
            Method1()
            Debug.WriteLine("処理終了 - Button2_Click")
        Catch ex As Exception
            Dim errorMessageBox As New ExceptionMessageBox
            errorMessageBox.Exception = ex
            errorMessageBox.AdditionalInformation = "" '補足情報があればココにセットする
            errorMessageBox.ShowDialog()
        End Try
    End Sub

    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        Try
            Debug.WriteLine("処理開始 - Button3_Click")
            Method1()
            Debug.WriteLine("処理終了 - Button3_Click")
        Catch ex As Exception
            Dim errorMessageBox As New ExceptionMessageBox
            errorMessageBox.Exception = ex
            errorMessageBox.AdditionalInformation = "" '補足情報があればココにセットする
            errorMessageBox.ShowDialog()
        End Try
    End Sub

    Private Sub Method1()
        Dim num As Integer
        num = "A"
    End Sub
End Class

どんなに例外エラーが起こらなそうなイベントだったとしても、やはり例外エラーは発生するものなので、例外エラーが発生しないように思えるイベントについても、必ずTry~Catchで捕捉するようにしています。例外エラーを捕捉していない場合は最初にお見せした、.NET Framework標準のエラーメッセージが表示され、利用者側に不安を抱かせてしまうことになります。

ご紹介した2つのベストプラクティスを意識することで、例外エラーと上手く付き合えるようになると思います。皆さんもぜひ参考にしてみてください。

コメント

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