🤩

GASのコーディングガイドラインについて

2021/03/08に公開

今回、GASを記述する上でのガイドラインを作成しましたので、公開いたします。

また、自分が今後書いていく際の備忘録でもあります。

ガイドラインを作る背景

Google Workspaceを使っているところで勤務しており、各々が効率化でスクリプト(GAS)をかいたりしていたのですが、レビューとかはせずに好き勝手書いてる現状があります。

そのため、下記の2つのような問題があります。

  • 保守性が悪い
  • 同じ処理を他のスクリプトで1から作っている

また、可読性を意識した開発を常にすることは技術の向上に繋がりますので、今回ガイドラインを作成します。

ガイドライン導入

目的

このガイドラインの目的は以下の3つです。

  • 保守性の向上
  • 可読性の向上
  • 再利用可能なコード

保守性

バグは起こりうるものでしょう。完全にはなくせないかもしれません。そういったバグの対応は緊急性が高いにもかかわらず、fixするのに時間がかかるシステムは悪です。

また、機能を既存のシステムに追加する際にバグが混入しやすいコードも悪です。

最小の変更で挙動を思うままに変更・修正できることを目指します。

可読性

そもそもコーディングする際、既存のシステムの処理がどういった流れなのかを理解するため、コードを読むでしょう。

そのコードが見辛い場合は、バグを修正するにせよ何にせよとても時間がかかります。長期的な視点に立てばそれらは解消すべきです。

再利用可能なコード

同じ処理を別のGASプロジェクトで使う場合が今後あるかもしれません。その際に1から開発するのでしょうか。車輪の再発明はやめましょう。

他の言語と同じようにGASでも部品化(関数化)すべきです。

詳しくはリンクを参照してください。

https://blog.pyq.jp/entry/Python_kaiketsu_180530

ガイドライン本編

注意事項を列挙します。

ファイル構成

基本的にこのようなファイル構成にしましょう。

fileArchitecture

  • function.gs (関数化した関数定義ファイル)
  • global_variable.gs (共通変数定義ファイル)
  • main.gs (main関数定義ファイル 処理に合わせて名前を変えてください。)
  • test.gs (テストコードファイル)
  • ※create_menu_bar.gs (必要に応じて、uiクラスを用いてメニューバーを作成しましょう)

命名法則

ファイル名

ファイル名はスネーク方式それ以外はローワーキャメル方式でかきましょう。

また、全て英語で記載しましょう。

https://designsupply-web.com/media/developmentlab/4052/

変数

変数はES6に則って使い分けましょう。

 const hoge ;
 let hoge ;
 var hoge ;

スコープも意識しましょう。

const hoge = 'hoge';
/*


多数の行


*/

console.log(hoge);//定義どこ?ってなりがち

加えて、型がわかりづらい際は書いてあげるといいかもしれません。

  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sh = ss.getActiveSheet();
  //多次元配列だと変数名でわかるようにする
  const sheetDataDoubleArray = sh.getRange(1,1,6,3).getValues(); 

またグローバル変数に関してですが、多数の別の関数で使われていたり、どうしてもプログラムの方でいじらなければいけない変数を定義したりする際に必要だと考えています。(バグが入りやすいと噂がありますが、適切にファイル分割して定義すれば危険性を軽減できるでしょう。)

下記を参照してください。

//全て大文字スネーク方式でかきましょう。
//グローバル変数とわかるように
const SHEET_ROW_NUM = 7;

関数

キャメルケースで命名しましょう。

また関数化した際に戻り値があるのであれば、何がリターンされるのか適切に表現するべきです。

//メインの処理を担当している関数で当該関数が登場した際に、中身を見なくても何をしているのかがわかる。
function getUserName(){
	 const userName = Browser.Input("Type your name.");
	 return userName;
}

処理がわかるように記載してください。

関数化

関数化するメリットはたくさんありますが、ここでは割愛します。

今後修正する可能性がある部分、処理が長く命名した方がスリムな部分、これらを関数化しましょう。

function.gs
function isUserDeviceMac(){
	 const result = 
		   Browser.msgBox(
		     "えらんでね", 
		     "あなたはmac?", 
		     Browser.Buttons.OK_CANCEL
		   );
	  if(result === "yes"){
	    return true;
	  }
	  if(result === "cancel"){
	    return false;
	  }
}
main.gs
function main(){
    if(isUserDeviceMac()){
        
    }else{
        
    }
}


実務で書く際には内部の表示するテキストを変更することも多いかと思います。
関数にしてメインの処理に依存しないようにしましょう。

また、main.gsのようにすれば処理が何をしているのかが一発で簡単にわかるようになります。

https://qiita.com/nakagawa1017/items/8b966af00fe271ff05fb

ネスト

下記の記事を参照してください。
ネストは浅くしましょう。

関数化や他の書き方によってネストは操作できますので、深くなってしまった場合には対処しましょう。

https://qiita.com/DeployCat/items/1ec901864d4ab11c8d6f

https://anopara.net/2014/06/27/do-not-write-deep-nested-code/

https://qiita.com/nskydiving/items/1076c411b002b0a3aec9

API

google固有の機能にアクセスするのが実行速度を遅める原因になります。

https://tonari-it.com/gas-spreadsheet-speedup/

この記事のようにsetValuesやgetValuesを繰り返していると、実行速度が長くなります。配列でget&setで対応しましょう。

MagicNumber

数字は何を意味しているのかわかりません。

const user = [
    [1,"satou"],
    [2,"yamada"]
];

console.log(user[0][1]);//satou

After


const userObj = [
    {
        id:1, 
        name:"satou"
    },
    {
        id:2, 
        name:"yamada"
    },
];

for(let i = 0; i < userObj.length; i++){
    console.log(userObj[i].name);//何が出力されるのかがわかりやすい!
}

同じような処理ですが、どうでしょう?obj形式だとアクセスした時に何が入っているのかわかりやすくなると思います。(追加する時も同様)

コメント

基本的にコードを読めばわかるコメントは書く必要がありません。

しかし、JSDOCは書かれているといいでしょう。

https://ics.media/entry/6789/

別に // これでも構いません。関数の前に引数の説明とそれから出る出力について記載されてた方が、後々関数をいじる際の負担が減ります。

// セットされた引数を返す関数============
function returnArgument(argument){
	return argument;
}
//=================================

また、コードを読んでもこれだけじゃわからない部分も補足説明を書きましょう。

例外処理

バグが起こる可能性はいつでもあります。

特にスプレッドシートの適用範囲や入力の型が違ったりした場合に思わぬ挙動が起きるかもしれません。

ちゃんとtry~catchしましょう。

userのリクエストに依存するような部分からtryで挟みましょう。

https://qiita.com/kuro_96/items/2a2b11be2a29459ded5c

ついでにそのシステムをプログラミングがわからない人が使う場合は、エラーメッセージを整形してあげるといいです。

try{
	//正常処理
}catch(e){
	let message = "再度検証してみてください!"
	messege += "それでもエラーの場合はプログラムがわかる人にみてもらってください!";
	messege += e;
	Browser.msgBox(message);
}

赤い文字と英語はユーザーを必要以上にビビらせてしまうので、配慮してあげましょう。

参考記事

ここまで記事を見た方は参考記事まで目を通してください。

https://www.webprofessional.jp/self-documenting-javascript/

https://sbfl.net/blog/2018/03/24/readable-javascript-code/

https://tonari-it.com/gas-coding-guide-line/#toc9

最後に

環境や会社によって異なるものなので、絶対の規約ではないです。その点ご注意を。

参考になれば幸いです。

Discussion