【VBA設計】「契約による設計(DbC)」の考え方をVBAのコメントとコード設計に取り入れる方法
Excel VBAで保守性の高いコードを書くためには、単に処理を動かすだけでなく、「契約による設計(DbC: Design by Contract)」の概念をコメントやエラーハンドリングに取り入れることが非常に効果的です。
この記事では、「戻り値」と「事後条件」の明確な違いから、DbCの考え方を取り入れた推奨コメントテンプレート、さらに事前条件をコードで強制する実践的なテクニックまでを解説します。
1. 「戻り値」と「事後条件」の違い
Excel VBAにおいては、戻り値(出力)と事後条件を以下の理由から明確に区別して考える必要があります。
- 戻り値 (Return Value): プロシージャが計算・処理した結果として呼び出し元へ返す「値」のこと。(Functionプロシージャのみ)
- 事後条件 (Postconditions): プロシージャが正常終了した時点で、「システム(またはオブジェクト)がどのような状態になっていることを保証するか」という約束です。
なぜ戻り値の説明だけではダメなのか?
VBAでは、「セルの値を書き換える」「シートを非表示にする」「ファイルを出力する」といった副作用(状態の変化)を伴う処理が非常に多いからです。
【例:データをデータベースに保存し、成功フラグを返す関数】
VBAでは、「セルの値を書き換える」「シートを非表示にする」「ファイルを出力する」といった副作用(状態の変化)を伴う処理が非常に多いからです。
【例:データをデータベースに保存し、成功フラグを返す関数】
- 戻り値: 成功なら
True、失敗ならFalse - 事後条件:
・(Trueの場合) 指定されたデータがDBに書き込まれていること。
・(Trueの場合) 対象シートの背景色がグレーアウトされていること。
Sub プロシージャ においては、「事後条件=このプロシージャが終わった時に何が保証されているか」を明記することが、まさに処理の目的そのものになります。2. 契約による設計を取り入れた推奨フォーマット
前回のフォーマットの「前提条件・依存関係」と「出力」部分を、DbCの概念である Requires(事前条件) と Ensures(事後条件) に再構築した、より堅牢なコメントテンプレートです。
' ==============================================================================
' [機能名] プロシージャの概要を1〜2行で記述
'
' [処理内容]
' ・処理のステップやビジネスロジックを簡潔に記述
'
' [引数]
' @param {型} 引数名 : 必須/任意 : 引数の説明
'
' [事前条件 (Requires)]
' ・呼び出し元が満たしておくべき契約(満たない場合の動作は保証しない)
' ・例: ワークブック "Data.xlsx" が開かれていること
' ・例: 引数 `rowIdx` が 1 以上であること
'
' [事後条件 (Ensures)]
' ・プロシージャ終了時に保証されるシステムの状態(副作用を含む)
' ・例: "Result" シートの A1:D10 に集計結果が書き込まれていること
' ・例: 処理対象のファイルが別フォルダに移動されていること
'
' [戻り値] (Functionの場合のみ)
' @return {型} 戻り値の説明(事後条件を満たしたかどうかの結果など)
'
' [例外処理 (Throws)]
' ・事前条件が満たされているにも関わらず発生しうるシステムエラーの挙動
'
' [履歴]
' YYYY/MM/DD [氏名] 新規作成
' ==============================================================================
' [機能名] プロシージャの概要を1〜2行で記述
'
' [処理内容]
' ・処理のステップやビジネスロジックを簡潔に記述
'
' [引数]
' @param {型} 引数名 : 必須/任意 : 引数の説明
'
' [事前条件 (Requires)]
' ・呼び出し元が満たしておくべき契約(満たない場合の動作は保証しない)
' ・例: ワークブック "Data.xlsx" が開かれていること
' ・例: 引数 `rowIdx` が 1 以上であること
'
' [事後条件 (Ensures)]
' ・プロシージャ終了時に保証されるシステムの状態(副作用を含む)
' ・例: "Result" シートの A1:D10 に集計結果が書き込まれていること
' ・例: 処理対象のファイルが別フォルダに移動されていること
'
' [戻り値] (Functionの場合のみ)
' @return {型} 戻り値の説明(事後条件を満たしたかどうかの結果など)
'
' [例外処理 (Throws)]
' ・事前条件が満たされているにも関わらず発生しうるシステムエラーの挙動
'
' [履歴]
' YYYY/MM/DD [氏名] 新規作成
' ==============================================================================
3. 実践における DbCコメントのメリット
この書き方をチームで徹底すると、保守や引き継ぎにおいて以下のような絶大なメリットがあります。
- 責任の切り分けが明確になる:エラーが起きた際、「事前条件を満たさずに呼び出した側(親)」が悪いのか、「事後条件を満たせなかった側(子)」の実装が悪いのか、責任の所在(契約違反者)が瞬時に判明します。
- ブラックボックスでも安全に使える:「事前条件」さえ整えて呼び出せば、「事後条件」の状態になることが約束されているため、中の複雑なコード(処理内容)を一切読まなくても、安全にそのプロシージャを再利用できます。
さらに堅牢にするためのワンポイント(事前条件のコード化)
VBAには本格的な Assert 機能がないため、プロシージャの冒頭で「事前条件」をコードとしてチェックする設計にするのが非常にお勧めです。
VBAには本格的な Assert 機能がないため、プロシージャの冒頭で「事前条件」をコードとしてチェックする設計にするのが非常にお勧めです。
Sub UpdateData(ByVal targetRow As Long)
' --- 事前条件のチェック(契約違反は即座にはじく) ---
If targetRow < 1 Then
Err.Raise Number:=513, Description:="事前条件違反: targetRowは1以上である必要があります。"
End If
' (以降、メイン処理)
End Sub
' --- 事前条件のチェック(契約違反は即座にはじく) ---
If targetRow < 1 Then
Err.Raise Number:=513, Description:="事前条件違反: targetRowは1以上である必要があります。"
End If
' (以降、メイン処理)
End Sub
このように、コメントに書いた「事前条件」「事後条件」を意識することで、VBAのコードの品質は他のモダン言語に匹敵するレベルまで引き上げることが可能です。ぜひ毎日の開発に取り入れてみてください!
PR