【実務・中級編】コメントアウトの極意:コードの「意図」を残すための記述ルールとメンテナンス性 – Excel VBA解析バイブル

スポンサーリンク

コメントアウトの極意:数ヶ月後の自分を救う「意図」の残し方

開発現場で数多くのVBAコードレビューを行っていると、ある共通した「悪臭(Bad Smell)」に気づく。
それは、コードの行数に対して圧倒的に情報量の少ない、あるいは有害ですらあるコメントの乱立だ。

‘ iを1から10までループする
For i = 1 To 10
‘ wsのA列にiを代入する
ws.Cells(i, 1).Value = i
Next i

このコードを見て、私はいつもこう問いかけたくなる。
「そんなこと、コードを見れば0.5秒でわかる。なぜそれを書いたのか?」

プログラミング言語は、コンピュータに「何をさせるか」を伝えるためのものだ。しかし、コメントは、「未来の自分や他の開発者(人間)に、なぜその実装を選んだのか」を伝えるためのラブレターでなければならない。

今回は、実務の現場で保守性に苦しむ開発者へ向け、バグを生まない堅牢な設計思想に基づいた「コメントアウトの極意」を授けよう。

1. 「What(何をしているか)」ではなく「Why(なぜそうしたか)」を書け

初心者は「処理の説明」をコメントに書く。プロは「背景・制約・意図」を書く。
実務のシステム開発において、最もコストがかかるのは「新規コードを書くこと」ではない。「既存コードの仕様変更やバグ修正」だ。

数ヶ月後、あるいは数年後、あなたが修正を迫られたとき、次のようなコメントに出くわしたらどうだろう?

  • 「× 悪例:Whatのコメント」

‘ 最終行を取得してオートフィルタをかける
lastRow = ws.Cells(ws.Rows.Count, “A”).End(xlUp).Row
ws.Range(“A1:D” & lastRow).AutoFilter Field:=1, Criteria1:=”完了”

何をしているかはコードを見ればわかる。知りたいのは「なぜA列を基準にしているのか」「なぜC列やD列ではなくA列なのか」という業務上のルールだ。

  • 「〇 正解:Whyのコメント」

‘ 業務ルールにより、A列(管理ID)が空白の行はデータ行とみなさないため、
‘ A列の最終行を基準としてオートフィルタを適用する。
lastRow = ws.Cells(ws.Rows.Count, “A”).End(xlUp).Row
ws.Range(“A1:D” & lastRow).AutoFilter Field:=1, Criteria1:=”完了”

この「なぜ」が残されているだけで、後任のエンジニア(あるいは未来のあなた)は、「あ、このA列の判定は業務要件に基づいているから、勝手にB列基準に変えてはいけないんだな」と一瞬で判断できる。これがバグを防ぐ堅牢な設計の第一歩だ。

2. 現場で使える!「意図」を伝えるコメント設計ルール

実務で破綻しないコードを書くために、以下の3つのルールをプロジェクトの標準として定着させてほしい。

1. 「ハック(応急処置)」には必ず理由とチケット番号を残す
Excelの仕様や、外部システムの制約で、泣く泣く「変な書き方」をせざるを得ない場面がある。その時は「なぜこんな変なコードを書いているのか」を赤裸々に書く。
2. マジックナンバーには背景を添える
「なぜ `3` なのか」「なぜ `86400` なのか」。定数化するか、コメントでビジネスロジックの根拠を示す。
3. 「変更履歴」はコメントではなくGit等のバージョン管理、またはプロシージャヘッダーに限定する
コードの途中に `’ 2023/10/1 〇〇修正` と書くのは、コードの可読性を著しく下げるため禁止する。

3. 【実践】プロダクションコード例:保守性を極限まで高めたデータ連携処理

ここでは、外部のCSVファイルを読み込み、データベース(または別シート)へ安全に書き込む実務さながらのモジュールを提示する。
「動くだけのコード」ではなく、「数ヶ月後の自分が読み解けるコード」のコメント構造をその目で確認してほしい。

Option Explicit

‘ =========================================================================
‘ 模块名: 業務データ取り込みモジュール
‘ 概要: 外部CSVから日次売上データをインポートし、基幹システム連携用フォーマットに整形する。
‘ 特記事項:
‘ – Excelのメモリリークを防ぐため、画面描画と自動計算を明示的に抑制しています。
‘ – 2024年要件定義書v2.1の仕様に基づき、金額の端数処理は「切り捨て」を採用。
‘ =========================================================================
Sub ImportDailySalesData()

‘ — 変数宣言(スコープは最小限に、意味のある命名規則を徹底) —
Dim wsTarget As Worksheet
Dim csvFilePath As String
Dim wbCsv As Workbook
Dim lastRow As Long
Dim i As Long

‘ エラーハンドリングの有効化(異常終了時のリソース解放を担保するため)
On Error GoTo ErrorHandler

‘ — 1. 環境設定の最適化(パフォーマンス・安定性向上) —
‘ 【意図】描画更新と自動計算の停止は、数万行規模のループ処理における
‘ 実行時間を約1/10に短縮するため必須。
With Application
.ScreenUpdating = False
.Calculation = xlCalculationManual
.EnableEvents = False
End With

Set wsTarget = ThisWorkbook.Sheets(“SalesData”)

‘ — 2. 外部ファイルの安全な取得 —
‘ 【意図】ハードコーディングを避け、ユーザーにダイアログ選択させることで
‘ ファイル名変更による「ファイルが見つかりませんエラー」を防止。
csvFilePath = Application.GetOpenFilename( _
FileFilter:=”CSVファイル (.csv), .csv”, _
Title:=”本日の売上CSVファイルを選択してください” _
)

If csvFilePath = “False” Then
‘ ユーザーがキャンセルした場合は静かに抜ける
GoTo Finally
End If

‘ — 3. データの一括インポートと整形処理 —
‘ 【意図】Workbooks.Openで開くとかえって保護ビュー等のダイアログに阻まれるリスクがあるため、
‘ 安定動作を優先してQueryTableではなく通常オープンを採用。
Set wbCsv = Workbooks.Open(Filename:=csvFilePath, ReadOnly:=True)

With wbCsv.Sheets(1)
lastRow = .Cells(.Rows.Count, “A”).End(xlUp).Row

‘ 【意図】パフォーマンスのため、セルへの個別アクセスを避け、配列一括転送を検討したが、
‘ 「特定のエラー行をスキップする」という業務例外処理(チケット#402)があるため、
‘ あえて行単位のループを採用している。安易な高速化よりも保守性を優先。
For i = 2 To lastRow
‘ 日付フォーマットの揺れ(YYYY/M/DとYYYY-MM-DD)を吸収する
wsTarget.Cells(i, 1).Value = Format(.Cells(i, 1).Value, “yyyy/mm/dd”)

‘ 金額データ(C列)のバリデーション:数値以外が混入する異常データ対策
If IsNumeric(.Cells(i, 3).Value) Then
wsTarget.Cells(i, 2).Value = .Cells(i, 3).Value
Else
‘ 異常値は「0」として記録し、後続の監査ログシートに転記する設計(仕様書P.14参照)
wsTarget.Cells(i, 2).Value = 0
Call LogErrorData(“行 ” & i & ” の金額が不正です: ” & .Cells(i, 3).Value)
End If
.Next i
End With

‘ CSVファイルを変更なしで閉じる
wbCsv.Close SaveChanges:=False

MsgBox “データの取り込みが正常に完了しました。”, vbInformation, “完了”

ErrorHandler:
If Err.Number <> 0 Then
‘ 【意図】予期せぬエラー発生時は、ユーザーに詳細を伝えつつ、
‘ 開発者向けのデバッグ情報をメッセージに出力する。
MsgBox “エラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“内容: ” & Err.Description, vbCritical, “システムエラー”
End If

Finally:
‘ — 4. 環境設定の確実な復元(リソースリーク防止) —
‘ 【意図】どんなに異常終了しても、必ずExcelの基本設定を元の状態に戻すこと。
‘ これを怠ると、次から起動するすべてのブックで計算や画面更新が停止したままになる。
With Application
.ScreenUpdating = True
.Calculation = xlCalculationAutomatic
.EnableEvents = True
End With

Set wbCsv = Nothing
Set wsTarget = Nothing
End Sub

‘ 簡易エラーログ出力用サブルーチン
Private Sub LogErrorData(ByVal errorMessage As String)
‘ 実務ではここで専用のログシートやテキストファイルにエラーを蓄積する
Debug.Print “[ERROR] ” & Now & ” : ” & errorMessage
End Sub

4. チーフアーキテクトからのメッセージ

優れたコードとは、まるで上質な小説のように、上から下へと自然なストーリーを持って読めるものである。
そして、そのストーリーの行間を埋めるのが「適切なコメントアウト」だ。

「どうせ自分しか見ないから」「めんどくさいから」と、動くだけのスパゲッティコードに「What」のコメントを乱立させるのは、未来の自分に爆弾を仕掛けているのと同じことだ。

明日からコードを書くときは、キーボードを叩く手を一度止め、自分にこう問いかけてみてほしい。
「このコードを選んだ『私の意志と理由』は、数ヶ月後の自分にちゃんと伝わるだろうか?」

その一手間が、あなたの業務自動化ツールを「使い捨てのオモチャ」から「組織を支える堅牢なシステム」へと昇華させるのだ。

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