これだけ読めば全てわかる、Google Apps Scriptライブラリの作り方
ライター 秦
本記事では、Google Apps Scriptのライブラリの使い方と作り方、JSDocコメントやコード補完まで、ワンストップ(2部構成)で全部わかるように詳しく解説しています。
ライブラリの使い方についてはコチラ↓
💡 この記事で得られる知識
・ ライブラリの作り方と公開方法
・ JSDocコメントの書き方
・ スクリプトエディタのコード補完について
4. ライブラリの作り方
4-1. ライブラリを作る
ライブラリの作成手順を説明します。
1) 新しいスクリプトファイルを作成する
Googleドライブで新規に「Google Apps Script」ファイルを作成します。
2) コードを書く
3) 新しい版として保存する
メニュー > 「ファイル」 > 「版を管理」を選択します。
版(=バージョン)の説明を「Desribe what has changed...」に記載し、「Save new version」で新しい版として保存します。
4) 共有設定をする
全公開、全公開(リンクを知っているユーザーのみ)、組織内、組織内(リンクを知っているユーザーのみ)、特定のユーザーのみ、などの共有設定をします。
5) スクリプトIDを公開する
3-1.に記載した手順にてスクリプトIDを参照し、公開します。利用者はスクリプトIDさえ知っていれば良いので、ブログやQiita、GitHubなど、公開場所は好きな場所で構いません。
4-2. ライブラリ作成時の注意事項
ライブラリを作成する際に気を付ける点について説明します。ECMAScriptより実装可能なクラスの利用、スクリプトエディタでのコード補完について解説します。
4-2-1. クラスの利用
ライブラリ内にクラスを自作した場合、「識別子.クラス名」としてもライブラリのクラスを参照することはできません。
下記のような結果になります。
▶︎ ライブラリ側(識別子=Lib)
▶︎ 利用側
これを解消するためには、以下のような方法があります。
1) クラスをsuper global領域にセットする
2) クラスを取得するsuper globalな関数を作成する
3) クラスのインスタンスを生成し取得するsuper globalな関数を作成する
---
📝 globalについて
JavaScriptのランタイムではいくつかのオブジェクトを持っていますが、このオブジェクトはツリー構造になっています。
共通して出てくる「super global」という言葉ですが、ここで言う「super global」とはその最上位を指しています。
Google Apps Scriptではネストのない場所か、ネストのない場所に書いた「this」がsuper globalな階層に該当します。ただし、ネストのない場所に書いたletやconstはsuper globalのひとつ下の階層(local globalと呼称します)に位置します。
以下の「宣言」と「階層の確認」のコードでそれが確認できます。
▶︎ 宣言
▶︎ 階層の確認
test()を実行すると、以下のようなログが出力されます。
1
2
undefined
undefined
5
1
2
3
4
5
letで宣言したc、constで宣言したdはthisの直下には存在しませんが、test()内からは参照できる場所に位置していることがわかります。
つまり、以下のことが言えます。
・a, b, e()はsuper globalに位置している
・a, b, c, d, e()はlocal globalに位置している
尚、「super global」や「local global」は、あくまでも本記事内での説明のために使用している用語です。正確な用語があるかもしれません。
---
話を戻して、次よりクラスを利用する3つの方法について実際のコードを交えて説明していきます。
1) クラスをsuper global領域にセットする
2) クラスを取得するsuper globalな関数を作成する
3) クラスのインスタンスを生成し取得するsuper globalな関数を作成する
1) クラスをsuper global領域にセットする
thisのプロパティに対してクラスを代入します。
▶︎ ライブラリ側(識別子=Lib)
▶︎ 利用側
2) クラスを取得するsuper globalな関数を作成する
クラスを取得するfunctionを作成します。
▶︎ ライブラリ側(識別子=Lib)
▶︎ 利用側①
▶︎ 利用側②
3) クラスのインスタンスを生成し取得するsuper globalな関数を作成する
クラスのインスタンスを生成して返却するfunctionを作成します。
▶︎ ライブラリ側(識別子=Lib)
▶︎ 利用側
4-3. JSDocとコード補完
4-3-1. JSDoc
JSDocの説明について、Wikipedia記事からの引用を拝借します。
JSDocは、JavaScriptのソースコードにアノテーションを追加するために使われるマークアップ言語である。JSDocをコメントの中に含めることで、プログラマーは自分が書いたコードのAPIを記述するドキュメントを追加することができる。JSDocをさまざまなツールで処理することで、HTMLやRich Text Formatなどの形式のアクセス可能なドキュメンテーションを自動生成することができる。JSDocは、Apache License 2.0の元にライセンスされている自由ソフトウェアである。
引用元:
https://ja.wikipedia.org/wiki/JSDoc
Google Apps Scriptでサポートされているアノテーションは以下です。
表3. Google Apps Scriptでサポートされているアノテーション
※ Libraries | Apps Script | Google Developers より引用
Only the @param and @return annotations are currently supported.
JSDocですが、3-1.で触れたAPIドキュメントを生成するための元ネタになります。メンテナンスする際や、GitHubなどでライブラリのソースコードを公開する際にも、使い方のヒントになりますので記述しておくと良いです。
▶︎ JSDocドキュメンテーションの例
4-3-2. コード補完
Google Apps Scirptのスクリプトエディタにはコード補完の機能があります。
ライブラリについてもコード補完することが可能ですが、残念ながら完全ではありません。ライブラリ内にclassを定義して利用してもらう場合には注意が必要です。
注意点については検証を交えながら解説していきますが、先に結論を記載します。
・ライブラリ内のglobalなfunctionはコード補完が効く
・classについては補完に問題がある
従って、以下のいずれかの方針でライブラリの作成を検討する。
・ コード補完の完全性までを考慮してライブラリを作成するのであれば、classは使わずにglobalなfunctionのみで構成する
・ ライブラリのAPIを別途ドキュメントで補うという方針であれば、classを使っても問題はない
参考)TypeScriptベースですが、こちらの記事でも検証されていますので、リンクを掲載させていただきます
Google Apps Script でクラス型のコードを書いたさいのスクリプトエディタでの補完への対処方法 (Bad Hack) - ChangeLog - noissefnoc
補完検証 step1
前述の2)のコードの補完は以下のようになります。
▶︎ ライブラリ側(識別子=Lib)
▷ 検証結果
foo()は認識されましたが、戻り値の型がvoidになっています。
補完検証 step2
JSDocを追加してみます。
▶︎ ライブラリ側(識別子=Lib)
▷ 検証結果
戻り値の型がドキュメント通りになりました。
補完検証 step3
次に、Fooクラスのメソッド、プロパティが補完されるかを検証します。
▶︎ ライブラリ側(識別子=Lib)
▷ 検証結果
残念ながら、何も補完されませんでした。
補完検証 step4
さて、ではどのようにすれば補完されるでしょうか。以下の方法で補完されるようになります。検証してみましょう。
1) Fooクラスのインスタンスを生成するfunctionを作成、さらにJSDocの戻り値の型は識別子にする
2) Fooクラスのメソッドをglobalなfunctionとして宣言、さらにJSDocもメソッドと同じ内容にする
▷ 検証結果
hogeが補完されるようになりました。
補完の副作用
しかしながら、この方法には副作用があります。先に完全ではないと述べた理由がこちらです。
❗️ Fooインスタンスからの補完にcreateメソッドが表示されてしまう
❗️ Lib識別子からの補完にhogeメソッドが表示されてしまう
余計なものが表示されてしまう上に、これらは全て実行可能であるため、予期せぬトラブルの原因にもなります。
さらに言うと、重複したようなコードとコメントを書かなければならないため、ライブラリの改修コストも上がります。
補完の補足
ちなみに、ES5仕様でオブジェクト指向実装をした場合ですが、classと同じようなJSDocを書いても補完されません。
▶︎ ES5での定義
▷ 検証結果
hogeES5は補完されません。
結論
これまでの検証より、以下のことがわかります。
・ライブラリ内のglobalなfunctionはコード補完が効く
・classについては補完に問題がある
従って、コード補完の完全性までを考慮してライブラリを作成するのであれば、classは使わずにglobalなfunctionのみで構成する、といった作り方になるでしょう。
ライブラリのAPIを別途ドキュメントで補うという方針であれば、classを使っても問題はないでしょう。
ライブラリを作成する際には上記の点について注意が必要です。
5. おわりに
作成したライブラリはclaspでダウンロードしてGit上で管理しておくと良いです。
claspについては、以下の記事が参考になりますのでリンクを掲載させていただきます。Bitbucketで管理する方法が書かれています。
claspを使い、Google Apps Scriptプロジェクトをgitでバージョン管理する