自分用のツールだけでなくお仕事としてVBAを書くことが増えてきたので、自分用のコーディングガイドラインを作ってみました。
勉強中のため、全部は固まっておらずところどころ説明が空欄だったり例が適当だったりしますが、「今のところ」の話として公開します。
今後も随時更新予定です。
- このページについて
- 全体
- 【BETTER】それ自体に意味を持たない単語を避ける
- 【BETTER】数値の表現
- 【BETTER】前置詞
- コメント
- プロジェクト
- モジュール
- プロシージャ
- 変数/定数
- 参考
- 注釈
このページについて
想定読者
最近は作ったツールを誰かに渡すことが多いため、その点を念頭に置いて作成しています。
作成者自身で使用する場合や、熟練者同士のコーディングなどにはそぐわない部分もあるかもしれません。あらかじめご了承ください。他の誰かが作ったものを改修する場合は、当ページの内容より作業中のルールを優先することとします。
優先度
各項目の【】
の部分は、下記の順に優先としています。
優先度 | 意味 |
---|---|
MUST | 必ず守る |
BETTER | 迷ったらこっち。絶対ではない。 |
WISH | 検討中・勉強中。 |
クックパッド社のコーディング規約を参考にさせて頂きました(例)。
ただ、まだコーディングに自信があるわけではないのでSHOULD
(~すべき)ではなくBETTER
(~した方が良い)としています。笑
考え中のこと、疑問点など
勉強中の身なので、まだ自分の中で確立できていないこともあります。
そのような部分には、🤔(考えていること)としてコメントを記載します。
全体
【MUST】プロシージャは1画面に収める
特別な理由がない限り、80字程度×20~30行程度までにする。
- 1行が長くなる場合は、改行(
_
)を積極的に使用する。
(並行して、コードの縦のラインが揃うように必ずレイアウトに気を使うこと。) - 処理の分岐等でこれを超える場合は、プロシージャの切り出しを検討する。
【MUST】省略せずに明記する
省略形は極力使わず、単語を明記する。
なお、プログラミング用語(特にVBA)として普及していて、運用担当者が一瞥で誤読なく識別できるものであれば、使用しても良い。ビジネス用語などの所謂「横文字」の言葉も、可能な限り別の表現に言い換える。
- 可読性が運用担当者のバックグラウンドに左右されやすいため。
- 間違いなく共通認識があるものは、この限りではない。
インテリセンス(入力補完)を積極的に使用することとし、一般に普及している語句であれば
~ation
系の長い単語も使用可とする。
【BETTER】結論ファースト
結果として出力したいものを最初に書き、段落(コードブロック)の要約の意味も持たせる。
- 目的の変数
- 補助的な変数
- 補助的な変数…
- 中間処理
- 中間処理
- 中間処理…
- 結果
▼例1
Dim shAbc As Worksheet '目的の変数 Dim baseBook as Workbook '補助的な変数(一瞬しか使わないもの) set baseBook = ThisWorkbook '中間処理 set shAbc = baseBook.Worksheets("シート名") '結果
▼例2
'メイン処理 ───────────────── Sub Main() Call SubProcess1 Call SubProcess2 End Sub '中間処理1 ───────────────── Sub SubProcess1() Dim 変数 As 型 変数 = 中間の中間1 Call 中間の中間2 End Sub Private Function 中間の中間1()As 型 '処理 End Function Private Sub 中間の中間2() '処理 End Sub '中間処理2 ───────────────── Sub SubProcess2() '処理 End Sub
【BETTER】それ自体に意味を持たない単語を避ける
(日本人が)イディオムとして認識しやすい言葉を除き、その単語自体で意味を判別できない単語は、可能な限り使用しないようにする。
例
動詞
- do
- make
- take
- have
- set
- get
形容詞・名詞
- target
【BETTER】数値の表現
単語 | 使いどころ |
---|---|
Count |
数え上げる時 |
Number |
~の番号、数値の計算 |
🤔(Number of ~
はどうする?)
【BETTER】前置詞
識別子1つあたり1つまでとする。
A of B
は、B A
と表現できる(ことが多い)ので、言い換えが出来ないか検討する。プロシージャやメソッド名などの末尾に前置詞を置くと、英文として読みやすくなる(気がする)。
コメント
コメント
【MUST】読めば分かることは書かない
コードは主に英語を使用するが、コメントが「ただの翻訳」になってしまう時は、そもそも変数名やプロシージャ名を変更した方がスマートになることが多い。
数カ月後の自分が「コードを読むだけで処理の内容を把握できるもの」を目指すこと。
【MUST】操作の意図を示す
- 同じ結果を得るのに複数の選択肢がある場合や、何らかの処理を飛ばすような場合には、「なぜそうしたのか」を残すこと。
(後で考慮漏れを検証しやすくするため)
【BETTER】要約コメント
- 複数行に渡る処理には、段落分けの意味で要約コメントを付与してもよい。
(併せて処理の区切りごとに空行も必ず挟むこと。)
【BETTER】エラーの可能性の示唆
分かる範囲で。
「何が起こるとエラーになるのか」を記す。
資料として、ベン図やパターンの列挙があると尚良し。
(後で考慮漏れを検証しやすくするため)
ドキュメンテーション・コメント
【MUST】プロシージャごとに記載する
- 再利用しやすくするため、小分けしたプロシージャごとにコメントを記載していく。
🤔(全部に書くのは冗長かな…?)
【MUST】書式
下記の書式とする(不要なものは削除しても良い)。
'' ' ●概要● ' ' @note ' ●注意事項● ' ' 【参照設定】 ' [Name] ●●●● ' [note] ●●●●●●●●●●●● ' ' 【参考】 ' ●記事名● | ●サイト名● ' ●URL● ' ' 【参考】 ' ●著者●(●発行年●)『●タイトル●』●出版社● ' ●URL● ' 第●版第●刷(p.●●●) ' ' @param {●型●} name ●概要● ' @param {●型●} name ●概要● ' @param {●型●} name ●概要● ' ' @return {●型●} ●概要● ' ' @customfunction ●概要● '
(記号●
が多いのは、個人的に書き忘れ・消し忘れを防ぐためです。)
【BETTER】必要なデータの例示
- 「何」が「どうなっている」と「どう出るのか」を例として記す。
(後で考慮漏れを検証しやすくするため)
【BETTER】エラーの可能性の示唆
分かる範囲で。
前項に関連して、「何が起こるとエラーになるのか」を記す。
ベン図やパターンの列挙があると尚良し。
(後で考慮漏れを検証しやすくするため)
【BETTER】5W1Hの明記
曖昧な表現になりそうな時は、省略せずすべて記載する。
5W1H | 意味 |
---|---|
When | いつ |
Where | どこで |
What | 何を |
Who/Whom | 誰が/誰に |
Why | 何のために |
How | どのように |
プロジェクト
【WISH】単一プロジェクトのプロジェクト名
🤔(VBAProject
のままで良い?)
【WISH】複数プロジェクトのプロジェクト名
(勉強中)
モジュール
全体
【MUST】記法
シートモジュール(後述)を除き、パスカル記法とする。
▼例
OpenWorkbook
ImportRawData
SheetFormatter
標準モジュール
【WISH】オブジェクト名
(考え中)
ブックモジュール
【MUST】単一プロジェクトのオブジェクト名
ThisWorkbook
のままとする。
【BETTER】複数プロジェクトのオブジェクト名
(勉強中)
シートモジュール
【MUST】オブジェクト名
sh<シート名>
とする。
※オブジェクトブラウザでのフォルム統一のため、接頭辞をsh
とする。
クラスモジュール
【MUST】オブジェクト名
- 名詞形とする。
※~er
や~ist
など、「~するもの」といった表現だと尚良し。
ユーザーフォーム
【WISH】オブジェクト名
(勉強中)
プロシージャ
全体
【MUST】記法
すべて「キャメルケース記法」とし、スコープにより1文字目を変える。
▼例
スコープ | 1文字目 | 例 |
---|---|---|
パブリック | 大文字 | OpenBook |
プライベート | 小文字 | sumPopulation |
【MUST】求める結果 > 処理の内容
実際の処理はプロシージャの中に閉じ込めることにして、プロシージャ名は「どんな結果になるか」が読み取れる名前を優先する。
【MUST】ネストは3つまで
Withブロック
やSelect Case文
を含めて、ネストは3つまでとする。ネスト1階層あたり1段のインデントとする。
ネストが深くなる時は、関数化や早期リターン、ガード節を積極的に使用すること。
【MUST】早期リターン/ガード節の推奨
n重ループや処理の分岐などは、If文
と組み合わせて改善すること。
▼例(複数条件)
Sub improveIfNests() If isAbc() Then Exit Sub If Not d = e Then Exit Sub If f = g Then Exit Sub 'すべてFalseのときの処理 End Sub
▼例(ループのスキップ)
Sub improveForNestsBySkip() Dim i As Long For i = 0 to Ubound(array1d) If array1d(i) = 1 Then goto Continue '繰り返し処理 Continue: Next i End Sub
▼例(ループの抜け出し)
Sub improveForNestsByExitFor() Dim i As Long For i = 0 to Ubound(array1d) If array1d(i) = 1 Then Exit For '繰り返し処理 Next i End Sub
▼例(n重ループの抜け出し)
Sub improveForNestsByBreak() Dim cell As Range Dim i As Long For Each cell In searchRange For i = 0 to Ubound(array1d) If cell.Value = 1 Then goto Break Next i Next cell Break: '次の処理 End Sub
【BETTER】「~にする」という表現
make ~
などの表現は、1語で言い換えられないか検討する
参考
接頭辞・接尾辞 意味 使いどき ~ize
<名詞>化する、<名詞>にする ~fy
<名詞>化する、<名詞>にする en~
より<形容詞>にする make~
~にする 上記どれも一般的な単語がない場合
【BETTER】「~を行う」という表現
do ~
やtake ~
などの表現は、1語で言い換えられないか検討する
【BETTER】補助関数
- スニペットなどに登録する際は、抽象的な名前も可とする。
- 実際にコード中でヘルパー関数として使用する時は、「何がどう変わるのか」を(可能な限り)明示した名前に変更する
Subプロシージャ、Functionプロシージャ
【MUST】命名
動詞始まりの1~5語程度の語句とする。
文型
- V(動詞)
- VO(動詞、目的語)
- VOO(動詞、目的語1、目的語2)
- VOC(動詞、目的語、補語)
GAS(ないしJavaScript)のメソッド名も参考とする。
(英文として平易な表現が多い(気がする)ため。)
【MUST】条件を判定する関数
原則、下記の命名規則とする。
is~
can~
has~
If文で呼び出すときに肯定文となるように書く。
If is確認すること()[ = True] Then ~
🤔(中止の条件判定の場合は、否定形の形容詞の方が自然かも?)
▼例
- bad
Sub Example() If checkPathWhetherValid() = False Then Exit Sub '処理 End Sub Private Function checkPathWhetherValid() As Boolean '条件の判定処理 End Function
- good
Sub Example() If isInvalidPath(sourcePath) Then Exit Sub '処理 End Sub Private Function isInvalidPath(ByVal sourcePath As String) As Boolean '条件の判定処理 End Function
プロパティプロシージャ
【MUST】命名
名詞句とする。
【BETTER】プロパティの接頭辞を統一する
接頭辞
接頭辞 命名 意味 なし プロパティ名
プロパティ名 p
pプロパティ名
プライベートレベルのモジュール変数 a
aプロパティ名
プロパティプロシージャの引数 名前を揃えることでプロシージャごとの置き換えがしやすくなり、フォルムも揃えやすい(はず)。
▼例1
Private pPropName As 型 Property Get PropName(ByVal arg1 As 型, _ ByVal arg2 As 型) As 型 PropName = pPropName(arg1, arg2) End Property Property Let PropName(ByVal arg1 As 型, _ ByVal arg2 As 型, _ ByVal 代入値 As 型) pPropName(arg1, arg2) = 代入値 End Property
▼例2
ワンライナーの場合。
(横に長くなりやすいので、出来るだけ避ける。)
Private pPropName As 型 Property Get PropName(ByVal arg1 As 型, ByVal arg2 As 型) As 型: PropName = pPropName(arg1, arg2): End Property Property Let PropName(ByVal arg1 As 型, ByVal arg2 As 型, ByVal 代入値 As 型): pPropName(arg1, arg2) = 代入値: End Property
変数/定数
全体
【MUST】記法
定数のみ「スネークケース記法」とし、それ以外はすべて「キャメルケース記法」とする。
なお、VBAではハイフン-
を識別子として使用できない*1ので、必要な場合はアンダースコア_
等で代用する。
▼例
種類 | 例 |
---|---|
定数 | ・MAX_SHEET_COUNTS ・ AUTHOR_NAME |
それ以外 | ・abcBookName ・ stopTime |
【MUST】スコープごとに1文字目の大文字/小文字を統一する
▼例
スコープ | 1文字目 | 例 |
---|---|---|
パブリック | 大文字 | AppointList |
プライベート | 小文字 | appointList |
【MUST】数値の型を統一する
数値 | 型 |
---|---|
整数 | Long型 |
小数 | Currency型 |
【MUST】変数名は3語まで
- 可能であれば2語。
- 動名詞
~ing
、動詞の名詞形~ation
などを積極的に使用すること。
【BETTER】型は変数名ではなく宣言に任せる
- メソッド、関数で使用するものなど、文脈で型が分かるものは型名を変数名に付与しなくても良い。
▼例
- not worse
Dim objAbcBook As Workbook
- better
Dim abcBook As Workbook
【BETTER】似たものを対で扱う時は、名前やフォーマットを寄せる
対になる変数を扱う時や型によって操作を分けるような時は、型名を明示した方が読みやすくなることもある。
この場合は、コードのフォルムを整えられるように(可能な限り)文字数を統一すること。
(一瞥で差異を見つけやすくなるため)
▼例1
- not worse
Dim sourcePath As String Dim destinationPath As String
- better
Dim srcPath As String Dim dstPath As String
▼例2
not worse
🤔(例が微妙…)
Dim wbAbcBook As Workbook Dim nameAbcBook As String Dim pathAbcBook As String
- better
Dim abcBookObj As Workbook Dim abcBookName As String Dim abcBookPath As String
変数/定数
【BETTER】配列やコレクションの命名
原則、複数形を使用する。
単数形と複数形の区別がない単語や、複数形にするとかえって読みづらい語句の場合は、
~Array
、~Collection
も可とする。
オブジェクトの定義・宣言
【BETTER】固有オブジェクト型の推奨
Object型
ではなく、各オブジェクト固有の型で宣言すること。
(インテリセンスが適用され、コーディングのスピード、可読性ともに向上するため。)Workbook
Worksheet
- 独自クラス、など
【WISH】参照設定したライブラリのオブジェクトを使用する時は、条件付きコンパイルを添える
列挙体
「変数・定数の中に入れるべきか」というのはあるけど、用途が似ているので…
【MUST】型名の接尾辞はe
とする
enumeration
のe
。
【BETTER】メンバーは大文字始まりとする
🤔(たまに変数と被るのがちょっと…)
🤔(メンバーにも接頭辞つけたらうるさい…?)
【BETTER】引き数の選択肢として列挙体を使う
- モードの切替など、プロシージャの引き数の選択肢として使うと、インテリセンスが使えるようになり少しだけコーディングが楽になる。
▼注意!
列挙体は宣言セクションにしか宣言できない。
つまり、呼び出し元のプロシージャと距離が離れてしまうことが多いので、出来るだけモジュール1つにつき2~3個までに抑える。VBAの仕様により、クラスモジュールなどではパブリックレベルでないと使えない。
他のモジュールのものと名前がバッティングしないように確認しながら使用する。
▼例
Public Enum eBookType InputBook SharedBook TemplateBook End Enum Sub Main() Call openBook(eBookType.InputBook) End Sub Private Sub openBook(ByVal bookType As eBookType) Dim book As Workbook Dim bookPath As String bookPath = "c:\\abc.xlsx" Select Case bookType Case eBookType.InputBook Set book = Workbooks.Open Filename:=bookPath, _ ReadOnly:=False, _ IgnoreReadOnlyRecommended:=True Case eBookType.SharedBook Set book = Workbooks.Open Filename:=bookPath, _ ReadOnly:=True, _ IgnoreReadOnlyRecommended:=False Case eBookType.TemplateBook bookPath = "c:\\abc.xltx" Set book = Workbooks.Open Filename:=bookPath, _ Editable:=True, _ ReadOnly:=False, _ IgnoreReadOnlyRecommended:=True End Select End Sub
構造体
「変数・定数の中に入れるべきか」というのはあるけど(ry
【MUST】型名の接尾辞はt
とする
type
のt
。
【BETTER】メンバーは大文字始まりとする
🤔(たまに変数と被るのがちょっと…)
🤔(メンバーにも接頭辞つけたらうるさい…?)
参考
以下を参考にさせて頂きました。
記事・サイト
書籍
注釈
*1:「ケバブ形式」なる記法があるらしい(美味しそう…)