
スコープっていつ意識するの?
ノンプロ研でGAS勉強中です。
今日は、GAS中級講座 講義1日目の復習ブログです。学んだことを実務でいかすにはどうしたらよいのか?を軸に復習していきたいと思います。
1日目はスコープと関数について学びました。ということで前編のスコープについて。
スコープって何?
まずスコープという聞き慣れない単語から。
scope
〔行動・思考・知覚・調査などの〕範囲、領域
ということで、スコープ=範囲ですね。GASの場合は変数・定数がどこからそれを参照できるかという範囲のこと。
グローバルスコープは万能選手?八方美人?
グローバルスコープで宣言した変数・定数は、プロジェクト全体から参照できる万能選手(?)ということは、関数を書く度に何度も書いていたような定数・変数はグローバルスコープに入れちゃえばいいのでは?
ということで、スプレッドシートとかだとこういう定数はポイポイ入れちゃってます。
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheetActive = ss.getActiveSheet();
const rangeActive = ss.getActiveRange();
プロジェクト内のどんな関数を実行しても毎回実行されるのが、このグローバルスコープなので、アクティヴな〜という定数は、相性が良い気がしています。
スタンドアローンでもカレンダーとか日付系を扱うとき用にこういうのもポイポイしてます。
// 日付に関するグローバル定数(すべてDateオブジェクト)
const now = new Date();
const today = now;
// 曜日をプロパティにそのインデックスを値に持つオブジェクト
const indexDayWeek = {
Sun: 0,
Mon: 1,
Tue: 2,
Wed: 3,
Thu: 4,
Fri: 5,
Sat: 6
};
ふむ便利。
書いてはいけない
反面、グローバル領域にむやみにコードを書いてはいけないとも講座でふれられていて、
■ 毎回実行される
■ プロジェクト全体から影響を受ける
■ 名称のバッティング
■ 宣言と使用位置が遠い
がむやみに書いてはいけない理由だとか。
たしかに、使わないのに毎回実行されるのは効率悪そうな気もするので、よく使うものに厳選して、よりすぐりのメンバーだけを残していこう。
あと、定数・変数名の名前の付け方が大事な気がしてきました。
value~ とか number~ とか場当たり的に名前を付けてると、どこかで被ってしまって、バッティングして変なことになるみたいなことはありそう。
たしかに学習初期に書いたコードの定数・変数名は、今見返すとなぜこのチョイス?と自分で思うことあり。また、自分がわかりやすく名付けたにも関わらず、意味がすぐわからなくなってたりします。
現時点での定数・変数名の付け方のルール
ということで、今は個人的にルール作りをして運用しています。
1. オブジェクトは接頭詞の部分で明確に
スプレッドシートの場合
sheetオブジェクトだったらsheetXxxxx
rangeオブジェクトだったらrangeXxxxx
カレンダーの場合
calendarオブジェクトだったらcalXxxxx
evnetオブジェクトだったらeventXxxxx
Gmailの場合
GmailThreadオブジェクトだったらthreadXxxxx
GmailMessageオブジェクトだったらmail(複数を配列で取得した場合はmessages)
そのほか
日付を扱うDateオブジェクトだったらdateXxxxx
などにして定数・変数名を見れば、どのようなオブジェクトが格納されているかわかるようにしています。
例外は、上記のようなオブジェクトから要素を取り出した場合で、
sheetオブジェクトからシート名を取り出した時はsheetXxxxxName
evnetオブジェクトからタイトルを取り出した時はeventXxxxxTitle
あと、単語そのものが明示的にとあるオブジェクトを指し示す場合も例外としています。
現在の日時を表すDateオブジェクトとしてのnowやtoday
みたいにしています。
2. 数値型も接頭詞にnum
1. の展開例ですが、数値型の場合はnumXxxxxとして、数値型であることを明示した上で、何の数値なのか明示します。
例:numStock, numPerson, numKeys...
単語そのものが明示的にとある数値を指し示す場合は例外です。
例:index, age, height, width, price...
3. 文字列型は連想できる単語であればOK
これは直感的。ただ、できるだけGASのドキュメントで引数等に使われているような単語を選ぶようにして、ドキュメントとの心理的距離を近くにたもってます。
例:name, id, title, url, subject, recipient, body, email...
4. 配列型は複数形を基本に
配列型は格納されている要素に応じた単語名の複数形を基本にします。
例:dataXxxxx, membersXxxxx, sheetsXxxxx, eventsXxxxx...
関数内で、先に空の配列を用意するときや、次元をいじるときには、aryXxxxx, ary1D, ary2Dなども使います。
オブジェクトも同様にobjXxxxxみたいなイメージです。
5. 定数・変数名を考える時にof等の前置詞は省略する
情報量が多い定数・変数名をつけようとすると長くなりがちなので、「〜の〜」みたいな名前を付けたい時には英語のofは省略するようにしています。他の前置詞も状況に応じて省略しています。
例:dayWeek(day of week = 曜日), endThisMonth(end of this month = 今月末)
スコープから脱線しました。
狭いスコープも便利かも
あまり使ってはいけないとされる広いスコープの反面、狭いスコープの良さみたいなのもあまりわかってなかったのですが、影響範囲が限定されるということで、定数・変数名の新しくてユニークなものを考え続けなくて良いのはメリットかもと思い至りました。
function myFunctionday3_04() {
const text = `|TH|TH|
|---|---|
|TD|TD|
|TD|TD|`;
// 改行区切りの一次元配列に
const ary1D = text.split('\n');
console.log(ary1D);
// バーティカルバー区切りの二次元配列に
const ary2D = [];
for (const element of ary1D) {
ary2D.push(element.split('|'))
}
console.log(ary2D);
// 空の孫要素を削除
const newAry2D = [];
for (const element of ary2D) {
const trimElement = element.filter(Boolean);
newAry2D.push(trimElement);
}
console.log(newAry2D);
// [ [ 'TH', 'TH' ],
// [ '---', '---' ],
// [ 'TD', 'TD' ],
// [ 'TD', 'TD' ] ]
}
これはGAS中級講座のとある宿題の回答ですが、for文などで配列の要素に処理をしているのですが、その際にelementという定数が重複して登場します。
配列の要素ですからelementという定数名を使いたいのは当然だと思いますが、お互い独立しているとは言え何度も登場するから名前を変えたほうがいいかも… と以前は思っていたのですが、今はスコープ閉じているから同じ名前でいいよねとなりました。
定数・変数名を考えるのってけっこう意志力を消費するので、定番の名前を使い回せるのは、非常にありがたいと思いました。
スコープ使いこなすには定数・変数名のネーミングのセンスが大事ね
ということで今日のまとめです。
スコープについて学んだことが実務にどう関係あるかな?という考察でしたが、定数・変数名のネーミングのセンスがしっかりしていればグローバルスコープに普遍的な定数・変数を用意しておくのはありなのではという結論です。
逆に狭いスコープでは、スコープをしっかり理解していれば、定数・変数名を新しくひねり出さなくてもド定番な名前を何度も使いまわしたほうが考えることが少なくて済む上に、後から読み返しても混乱が少ないのではと思いました。