最近、ちまちまとGASのスクリプトを練習しています。
書き方が固まってきたので、頭を整理する意味でGAS用のコーディングガイドラインも残すことにしました。
大半はVBAの記事から引用したものも多いので、読んだことのある方は遠慮なく飛ばし読みを!
【VBA】自分用コーディングガイドライン - ゆるおたノート
このページについて
想定読者
優先度
各項目の【】の部分は、下記の順に優先としています。
| 優先度 |
意味 |
| MUST |
必ず守る |
| BETTER |
迷ったらこっち。絶対ではない。 |
| WISH |
検討中・勉強中。 |
VBAの記事と同様、クックパッド社のコーディング規約を参考にさせて頂きました(例)。
ただし、コーディングに自信があるわけではないので、2つ目はSHOULD(~すべき)ではなくBETTER(~した方が良い)としています。
全体
【MUST】コードの長さの制限
特別な理由がない限り、1つの関数は「1行100字程度×35行程度」までにする。
文字列の連結等で1行が長くなる場合は、再代入を積極的に使用する。
(並行して、コードの縦のラインが揃うように必ずレイアウトに気を使うこと。)
処理の分岐等でこれを超える場合は、関数の切り出しを検討する。
【MUST】省略せずに明記する
省略形は極力使わず、単語を明記する。
ただし、プログラミング用語として普及していて、運用担当者が一瞥で誤読なく識別できるものであれば、使用しても良い。
ビジネス用語などの所謂「横文字」の言葉も、可能な限り別の表現に言い換える。
これは、可読性が運用担当者のバックグラウンドに左右されやすいため。
間違いなく共通認識があるものは、この限りではない。
なお、インテリセンス(入力補完)を積極的に使用することとし、一般に普及している語句であれば~ation系の長い単語も使用可とする。
【BETTER】それ自体に意味を持たない単語を避ける
(日本人が)イディオムとして認識しやすい言葉を除き、その単語自体で意味を判別できない単語は、可能な限り使用しないようにする。
▼例
動詞
- do
- make
- take
- have
- set
- get
形容詞・名詞
【BETTER】数値の表現
| 単語 |
使いどころ |
Count |
数え上げる時 |
Number |
~の番号、数値の計算 |
【BETTER】前置詞
識別子1つあたり1つまでとする。
A of Bは、B Aと表現できることも多いので、言い換えが出来ないか検討する。
イディオム等を使用するときは、関数やメソッド名などの末尾に前置詞を置くと英文として読みやすくなる(気がする)。
コメント
全体
【MUST】読めば分かることは書かない
コードは主に英語を使用するが、コメントは日本語で書く。
しかし、コメントが「ただの翻訳」になってしまう時は、そもそも変数名や関数名を変更した方がスマートになることが多いので、検討すること。
数カ月後の自分が「コードを読むだけで処理の内容を把握できるもの」を目指すこと。
【MUST】操作の意図を示す
同じ結果を得るのに複数の選択肢がある場合や、何らかの処理を飛ばすような場合には、「なぜそうしたのか」を残すこと。
(後で考慮漏れを検証しやすくするため)
コメント
【BETTER】要約コメント
複数行に渡る処理には、段落分けの意味で要約コメントを付与してもよい。
(併せて処理の区切りごとに空行も必ず挟むこと。)
【BETTER】エラーの可能性の示唆
分かる範囲で。
「何が起こるとエラーになるのか」を記す。
資料として、ベン図やパターンの列挙があると尚良し。
(後で考慮漏れを検証しやすくするため)
ドキュメンテーション・コメント
【MUST】関数ごとに記載する
- 再利用しやすくするため、小分けした関数、メソッドごとにコメントを記載していく。
【MUST】書式
下記の書式とする(不要なものは削除しても良い)。
(記号●が多いのは、個人的に書き忘れ・消し忘れを防ぐためです。)
【BETTER】必要なデータの例示
- 「何」が「どうなっている」と「どう出るのか」を例として記す。
(後で考慮漏れを検証しやすくするため)
【BETTER】エラーの可能性の示唆
【BETTER】5W1Hの明記
曖昧な表現になりそうな時は、省略せずすべて記載する。
| 5W1H |
意味 |
| When |
いつ |
| Where |
どこで |
| What |
何を |
| Who/Whom |
誰が/誰に |
| Why |
何のために |
| How |
どのように |
プロジェクト
全体
【MUST】命名規則
{作成日}_プロジェクト名とする。
なお、プロジェクト名は、アッパーキャメルケース記法とする。
20251130_YuruwotaNoteMaker
ファイル
【MUST】命名規則
メイン処理をindex.gs、テスト関数をtest.gsで固定、各クラスを{クラス名}.gsとする。
なお、クラス名はアッパーキャメルケース記法とする。
【MUST】フォルダ分け
index.gsとtest.gsのみMainフォルダ、クラス.gsやHTML関係をSubフォルダに分類して格納する。
これは、ファイルがアルファベット順で自動的にソートされるので、視認性を上げるのが主な目的。
Main/index.gs
Main/test.gs
Sub/HTML/index.html
Sub/HTML/style.html
Sub/Props.gs
また、ライブラリの作成時などで、使い方を説明するときはMainフォルダにsample.gsを追加しても良いが、test.gsと内容が被ることもあるので必要性を検討した上で追加すること。
ライブラリ
【MUST】命名規則
ライブラリ作成側は{作成日}_識別子とする。
なお、識別子はアッパーキャメルケース記法とする。
20251130_YuruwotaNote
ライブラリ使用側は、エラーにならないように{作成日}_を削除し、識別子のみとする。
YuruwotaNote
【BETTER】クラスの使用
まとめられる処理は、積極的にクラスとしてまとめる。
その際、クラス全体を無名関数に隠し、インテリセンスの候補として表示させる準備をする。
(function(global){
class YuruwotaNote {
method() {
}
global.YuruwotaNote = YuruwotaNote;
})(this);
さらに、インテリセンスの候補に表示させたいメソッドは、index.gsへ擬似的なグローバル関数として定義しておく。
function load() {
return new YuruwotaNote();
}
function post(message) {
throw new Error('loadメソッドを呼び出してから呼び出してください。');
}
関数
全体
【MUST】命名規則
すべて「キャメルケース記法」とし、目的により1文字目(と末尾)を変える。
また、名前は動詞始まりの1~5語程度の語句とする。
▼例
| 目的 |
1文字目 |
例 |
| メイン処理 |
大文字 |
PostToHanetaBLog |
| サブ処理 |
小文字 |
generateBody_ |
また、サブ処理の中で実行する関数の候補に挙げる必要の無いものは、末尾に_をつける。
【MUST】求める結果 > 処理の内容
実際の処理は関数の中に閉じ込めることにして、関数名は「どんな結果になるか」が読み取れる名前を優先する。
【MUST】インデントはスペースを2つずつ
【MUST】早期リターン/ガード節の推奨
n重ループや処理の分岐などは、If文と組み合わせて改善すること。
▼例(複数条件)
const improveIfNests = () => {
if (isAbc()) return;
if (d !== e) return;
if (f === g) return;
}
▼例(ループのスキップ)
const improbeForNestsByContinue = () => {
const arr = ["a", "b", "c"];
for (let i = 0; i < arr.length; i++) {
if (arr[i] === "b") continue;
}
}
▼例(ループの抜け出し)
const improbeForNestsByBreak = () => {
const arr = ["a", "b", "c"];
for (let i = 0; i < arr.length; i++) {
if (arr[i] === "b") break;
}
}
▼例(n重ループの抜け出し)
const improveForDoubleNestsByBreak = () => {
const arr = [["a", "b", "c"], ["d", "e", "f"]];
for (let r = 0; r < arr.length; r++) {
let row = arr[r];
for (let c = 0; c < row.length; c++) {
if (row[c] === "b") break;
}
}
}
【MUST】条件を判定する関数
原則、下記の命名規則とする。
If文で呼び出すときに肯定文となるように書く。
if (is確認すること()) {
}
▼例
const Example = () => {
if (!checkPathWheterValid(sourcePath)) return;
}
const checkPathWheterValid = (sourcePath) => {
}
const Example = () => {
if (!isInvalidPath(sourcePath)) return;
}
const isInvalidPath = (sourcePath) => {
}
【BETTER】「~にする」という表現
make ~などの表現は、1語で言い換えられないか検討する。
参考
| 接頭辞・接尾辞 |
意味 |
使いどき |
~ize |
<名詞>化する、<名詞>にする |
|
~fy |
<名詞>化する、<名詞>にする |
|
en~ |
より<形容詞>にする |
|
make~ |
~にする |
上記どれも一般的な単語がない場合 |
【BETTER】「~を行う」という表現
do ~やtake ~などの表現は、1語で言い換えられないか検討する。
【BETTER】補助関数
- スニペットなどに登録する際は、抽象的な名前も可とする。
- 実際にコード中でヘルパー関数として使用する時は、「何がどう変わるのか」を(可能な限り)明示した名前に変更する。
変数・定数
基本方針
【MUST】定数優先
基本的にconstを使って定数とし、値の変化が必要な場合のみletで変数とする。
【MUST】スコープは狭く
基本的にローカル、もしくはブロックスコープを使用し、値や名前が衝突しないよう気を使うこと。
命名規則
【MUST】スコープごとに1文字目の大文字/小文字を統一する
▼例
| スコープ |
1文字目 |
例 |
| グローバル |
大文字 |
YuruwotaNote |
| ローカル |
小文字 |
yuruwotaNote |
【MUST】変数名は3語まで
- 可能であれば2語。
- 動名詞
~ing、動詞の名詞形~ationなどを積極的に使用すること。
【BETTER】似たものを対で扱う時は、名前やフォーマットを寄せる
▼例1
const sourcePath = 'xxxxxxxxxxx';
const destinationPath = 'yyyyyyyyyy';
const srcPath = 'xxxxxxxxxxx';
const dstPath = 'yyyyyyyyyyy';
▼例2
const ssIdABc = 'xxxxxxxxxxxxx';
const ssAbc = SpreadsheetApp.openById(ssIdABc);
const sheetNameAbc = 'xxxxxxxxxxxxx';
const sheetAbc = ssAbc.getSheetByName(sheetNameAbc);
const abcSsIdc = 'xxxxxxxxxxxxx';
const abcSs = SpreadsheetApp.openById(abcSsId);
const abcSheetName = 'xxxxxxxxxxxxx';
const abcSheet = abcSs.getSheetByName(abcSheetName);
【BETTER】配列やオブジェクトの命名
クラス、オブジェクト
全体
【MUST】命名規則
アッパーキャメルケース記法とし、1~3語程度の名詞句とする。
YutuwotaNote
メソッド
【MUST】原則、関数と同じ
特にこだわりが無い限り、原則ルールは関数と同じ。
【MUST】関数との違い
サブ処理は「先頭」に_をつける。
プロパティ
【MUST】命名規則
ロワーキャメルケース記法とし、1~3語程度の名詞句とする。
yutuwotaNote
スクリプトプロパティ
命名規則
【MUST】記法
すべて大文字のアッパースネークケース記法で統一する。
'YURUWOTA_NOTE'
【MUST】命名規則
サービス名がある場合は、先頭に名前を付与して(可能な限り)フォルムを整える。
HATENA_API_KEY
HATENA_API_TOKEN
処理
【BETTER】クラスにまとめる
クラスにまとめ、メインの処理を書くときにインテリセンスが効くようにする。
▼例
class Props {
constructor() {
const props = PropertiesService.getScriptProperties();
this.ssId = props.getProperty('SPREADSHEET_ID');
this.channelId_test = props.getProperty('CHANNEL_ID_TEST');
this.channelId = props.getProperty('CHANNEL_ID');
this.folderId = props.getProperty('IMAGE_FOLDER');
}
}
参考
以下を参考にさせて頂きました。
記事・サイト
命名規則についてまとめてみた(キャメルケース,パスカルケース,スネークケース,ケバブケース, etc...) #命名規則 - Qiita
GASのライブラリでクラス化と補完 #GoogleAppsScript - Qiita
Google Apps Scriptライブラリの作り方 #GoogleAppsScript - Qiita
Google Apps Script でクラス型のコードを書いたさいのスクリプトエディタでの補完への対処方法 (Bad Hack) - ChangeLog - noissefnoc
書籍
ダスティン・ボズウェル/トレバー・フォシェ オライリー・ジャパン 2012年06月