プログラマーのメモ書き

伊勢在住のプログラマーが気になることを気ままにメモったブログです

OSC名古屋 2018 に出展してきました

先日(2018年5月19日)、OSC名古屋が開催されました。

www.ospn.jp

今回は、ここに、『三重勉強会・コミュニティ共同ブース』として出展しましたので、出展時の様子とその背景などをメモっときます。

当日の様子

当日のブースはこんな感じでした。

f:id:junichim:20180521093520j:plain

基本、チラシをおいてるだけです。(ほぼ)チラシだけなので、ブースには一人入れば全く問題なしですが、当日は、Little Coder Mie の @ さんが来ていただけましたので二人で入ってました。

ちなみにご紹介した勉強会・コミュニティさんはこんな感じです。

CoderDojo伊勢

f:id:junichim:20180521093432j:plain

coderdojo-ise.jimdo.com

今のところ、三重県内の CoderDojo は CoderDojo伊勢 だけだそうです。

Little Coder Mie

f:id:junichim:20180521094320j:plain

ws.moyashi-koubou.com

昔から子供向けのプログラミングイベントをやってます。毎回趣向を凝らして、いろんなイベントで楽しさを体験できるようにされています。

WordBench 三重

f:id:junichim:20180521094515j:plain

ホーム | 三重 | WordBench

今年3月(2018年3月)から立ち上がったそうです。県内でこういう活動があることを、多くの方に知れ渡ってほしいですね。

伊勢ギーク・フェア/チーム伊勢

f:id:junichim:20180521095017j:plain

f:id:junichim:20180521095048j:plain

https://www.facebook.com/igfaire/

今年も伊勢ギーク・フェア開催するそうです。ぜひ、出展等、ご検討ください。

伊勢IT交流会

f:id:junichim:20180521095140j:plain

https://www.facebook.com/iseitkouryuukai/

自分が主催者なんで、改めて紹介もなんですが、伊勢で雑談とLTを中心にした、IT系の交流会やってます。 次回は、6月2日(土)にやりますよ(申し込みは connpass からお願いします)。

なんでこんなことしているのか

ブースとしては、三重県内で活動しているIT系の勉強会やコミュニティを紹介するブースです。まあ、紹介といっても大げさなものではなく、チラシ置いといて、興味のありそうな方とお話しするだけなんですが。

地方(この場合は三重県)にいる技術者の方はよくわかると思うのですが、勉強会を探そうとしてもなかなか見つからなかったり、たまにあっても定期開催していなくて、次はいったいいつなんだ?(その後開催がなかったり・・・)となったりすることが多々あると思います。それはそれで事情があるので致し方ないと思います。

そうなると次は、地理的な要因が許す場合は、機会を見つけては近隣の(比較的大きな)都市まで出かけて勉強会に参加する、といったことがよくあると思います。 まあ、近隣の勉強会に参加することも、得るものも大きくこれはこれで悪くはないのですが、いかんせん、金銭的・時間的な負担が大きいのが難点です(私の場合、家族持ちエンジニアになってからは特に後者に悩まされるようになりました)。

とはいっても、地方でやってる勉強会やコミュニティもまったくないわけではないので、その存在をぜひ知ってもらい、勉強会・コミュニティを探している人と主催側の両方にプラスになればと思いました。

じゃあ、具体的にどうするか?ですが、三重県の場合、何かあれば名古屋に出てくるパターンが多いかな?という予想もあって、OSC名古屋に出展することにしました(大阪、京都、に行くよという意見もありますがここは私の都合で決めました)。

ということで、同じ県内で活動している方々に声をかけさせていただいて、紹介ブースとして出てみたという具合です。

まあ、実は、似たようなことは昨年の OSC名古屋2017 で『伊勢志摩地域コミュニティ共同ブース』という形でやったのですが、それも元々は名古屋の勉強会さんのほうで『名古屋勉強会・コミュニティ協同ブース』という形で出展されていたのをパクったインスパイアされて始めたことです。

まずは、地方でも意外と勉強会・コミュニティとかあるんだ、と知ってもらえればと思います。

効果

まあ、実際の効果のほどはよくわかりませんが、『三重から来てます』とか『三重出身です』という方が、結構いらっしゃいました。 これらの方とお話ししていると、やはり『三重県内で活動があるのを知らなかった』とか、『県内でやってるのを知りたかった』という旨のことを多く聞けました。

存在を知ったからと言って、すぐに勉強会・コミュニティに参加するというわけでもないと思いますが、何かときに、『そういえば、三重県内でもなにやらやってたな』と思い出してもらえればと嬉しいです(で、自分の思ったのが無ければ、ぜひ立ち上げましょう!)。

ということで

OSC名古屋の機に、地方の勉強会・コミュニティを紹介させてもらいましたという話でした。 同じようなことは、他のOSCでもできるんじゃないかなと思いますので、地方の方はぜひ検討してみると面白いんじゃないかと思います。

追記

桑名でも勉強会があるそうです。すいません、知りませんでした。来年はぜひご一緒しましょう!

kuwana.connpass.com

Chrome 拡張で、 Google Apps Script をGit管理できるようにする

Google Apps Script の開発だと、ブラウザ上のエディタで作業するのはいいんですが、ソースコード管理が簡単にできないのがちょっと嫌なところです。

と、ずっと思っていたのですが、下記の記事で紹介されているプラグインを使うと、Google Apps Script がGitで管理できるようになるそうです!

こりゃいい! ということで、早速試してみました。

Chrome拡張のインストール

インストール方法は簡単で、Chrome Web Store から Chrome 拡張として、『Google Apps Script GitHub アシスタント』をインストールすれば終わりです。

ちなみに、GitHubのサイトはこちらでした。

github.com

インストール後、Chrome でGASのスクリプトエディタを開くと、メニューが追加されていれば成功です。 詳しい使い方などは、前述の記事などを参照してください。

使ってみた印象

自分で使ってみた印象は、スプレッドシート埋め込みのGASにも対応できている!というのが一番感動でした。 しかも、操作はごく簡単。これであれば、開発に応じて、適宜コミットしていくことが出来そうです。

ただ、何点か注意する点もあるようです。個人的に気になったのは次のような点です。

常に指定したリポジトリ/ブランチの最新版との Pull/Push になる

なので、任意のコミットを反映するのは、一度リポジトリをforkしてからブランチを切って、pullする、などひと工夫必要です。

また、残念ながら現時点ではタグからpullしてくるのもできないので、過去のある時点のコミットを再現したい場合も同様の工夫が必要になります。

個人的には、せめて、タグからのpullできるようになっているとうれしいなと思います。

ファイル名とそこに含まれている同名の関数がある場合、正しくコミットできない

Known Issues としても紹介されています。

特定のスクリプトファイル名の場合、なぜかpushの対象にならない場合があって、気づいたときはあせりました。

私の場合、 Constants.gs というファイルで、内部に

function Constants() {
}

と関数を定義していたら、見事これに該当してコミットできませんでした。 どうも、利用しているサービスの制限のようで、現時点では致し方ないようです。

pullでファイルの追加がある場合に、エラーとなる場合がある

という問題もありました。

どういった場合に再現するのか、まとめ切れていないのですが、スプレッドシートに紐づく形式の場合に起こりました。新規に作成したスプレッドシートで、スクリプトエディタを開いて、何も変更していない状態でリポジトリの内容を pull してこようとすると起きているようでした。

とはいえ、これはGASの開発をするうえで、非常に便利なツールになるので、GAS触る方は一度試す価値あると思います。

その他の方法

ちなみに、GASでソースコードを管理する方法は他にもあるようで、下記記事などにもまとめられていました。

qiita.com

これらも一度試すと面白いかと思います。

Google Apps Script でカスタムダイアログを使った場合の排他処理について

Google Apps Script (以下、GAS)便利ですね。

そりゃ、できないこともいろいろあって、スプレッドシートに紐づく形式の場合、エクスポートができなかったり(なので、GitHubが使いにくい)、いろいろと不満もありますが、サーバーなしにいろいろとできるんで便利です、ハイ。

で、先日ちょっとしたきっかけでスプレッドシートにスクリプトを作ったのですが、その際にユーザーの応答を得るためにカスタムダイアログを使いました。このとき、カスタムダイアログの呼び出し前後を一括して排他制御をしたかったので、ロックをかけようとしたら、見事にはまりました。

せっかくなので、その時の経緯と自分のやった対応策をメモっておきます。たぶん本当はもっといい方法があると思うので、ご存知の方ぜひ教えてください。

構成

基本的な構成はこんな感じです。

  • 独自メニューを追加し、各メニューからスプレッドシートを操作する処理を呼び出す
  • メニューから呼び出された処理で、カスタムダイアログを表示して、ユーザーに選択肢を示す
  • カスタムダイアログで選択された選択肢に基づいて、処理を続行する
  • このスプレッドシートを利用するユーザーは複数おり、同時に独自メニューを使うこともあり得る
  • 独自メニューから呼び出される処理は、排他的に行いたい
  • 一連の処理は1スプレッドシートからのみ使う(GASプロジェクトを複数のスプレッドシート等で共有しない)

まあ、いろいろと書いてもわかりにくいので、サンプル作ってみました。

基本的な動作は、次の通りです。『独自メニュー』から、『追加』を選択します。

f:id:junichim:20180507211705p:plain

すると、追加したいテキストを入力するダイアログが表示され、

f:id:junichim:20180508101409p:plain

適当にテキストを入力して、『OK』を押すと、

f:id:junichim:20180508101418p:plain

のように、スプレッドシートの所定の列の末尾に入力したテキストが追記されるというものです。

まあ、これだけだと、わざわざダイアログで応答求めるようなものでもないのですが、実際にはスプレッドシートの内容を読み取りつつ、ユーザーにいろいろと選択肢を示し、その結果に応じて処理を変えるような処理を行うイメージです。 排他処理を除けば、これでやりたいことができているという状態と仮定します。これに排他処理を追加していくことを考えていきます。

なお、この状態(排他処理のない状態)でのソースコードは下記を参考にしてください。

https://github.com/samples-of-junichim/GAS_custom_dialog_lock_sample/tree/01_no_exclusive_proc

参考

上記サンプルを作成する際に参考にしたサイトです。

なお、この記事中に UiApp のことが触れられていますが、現時点で既に deprecated になってるので HtmlService を使うほうが無難だと思います。

排他処理の追加 (1) : Lock オブジェクト

さて、GAS の場合、排他処理をどう追加すればよいのか?と調べてみると、簡単に利用できることが分かりました。

kakts-tec.hatenablog.com

LockService の getDocumentLock を使って、ロックオブジェクトを取得して、ロックオブジェクトの tryLock を呼び出せばOKです。 ロックが取得できれば、trueが帰り、ロックが取得できなければfalseになります。

そこで、早速、 LockService / Lock を追加してみました。

https://github.com/samples-of-junichim/GAS_custom_dialog_lock_sample/tree/02_lockservice

リファレンスによると、ロックオブジェクトは、明示的に開放しなくても、処理終了時に解放されるとあります。 で、カスタムダイアログを呼び出すと一旦処理が終了して、ダイアログからは非同期でコールバックされます。 このため、ロックオブジェクトをカスタムダイアログ呼び出し前後で保持するために、グローバル変数を使おうとしました(が後述するように使えません)。

試してみると

早速試してみます。

これで動くかな?と思いきや、一つ目のブラウザからダイアログ表示後、別のブラウザで独自メニューを呼び出してみるとロックが取れて、ダイアログが表示されます。 おまけにコールバック呼び出し後、lockオブジェクトのメソッドがないということで、エラーになります。

ひょっとしたらと思い調べてみると、GASの場合、グローバル変数は使えないようです。

でも、カスタムダイアログの表示は非同期に行われるので、 そうなると、カスタムダイアログ呼び出し前にロックオブジェクトを取得したとしても、コールバック関数にそのオブジェクトを渡せないので、どうやってダイアログ表示前後を含む一連の処理が完了するまでを排他処理すればいいんだろうか?というところで、壁にぶち当たりました。

排他処理の追加 (2) : PropertyService

さて、困ったので、いろいろと調べてみると、こういう場合は、 PropertiesService をグローバル変数代わりに使うというのが定番のようです。

stackoverflow.com

まあ、小さなアプリケーションなので、ちょっと大げさな気がしないでもないですが、ここはひとつグローバル変数代わりに Property を頼ってみよう、としました。

そこで、前述の LockService はやめて、メニューから処理を呼び出した際に、PropertiesService に現在時刻を記入するようにします。 カスタムダイアログからのコールバックでは、処理終了時に記入されている時刻を削除します。 独自メニューから呼ばれる各メソッドの先頭(サンプルだと1つですが)では、 PropertiesService の時刻を確認して、記入がなければ、排他状態ではないと判断するようにします。

時刻を使ったのは、一定以上時間が経過している場合は、処理が中断されたと判断したいためです。

ソースコードはこちらになります。

https://github.com/samples-of-junichim/GAS_custom_dialog_lock_sample/tree/03_propertiesservice

にしても、自分であれこれ実装するのいやですねー。排他処理周りって思わぬバグの温床なんで触りたくないんですよね・・・。LockService 使えれば楽なのになー。

ま、さて、これでうまくいくはずです。 2つのブラウザでログインして、一方でカスタムダイアログを表示中に別のブラウザからメニューを呼び出してみると、ちゃんと排他制御できているっぽいです。

f:id:junichim:20180508101516p:plain

排他処理の問題発見と原因の推測

ということで、一件落着と思ったので、適当に遊びながらいろいろと試していると、どうも挙動がおかしい時があります。

具体的には、カスタムダイアログからのコールバックが正しく処理されません。 ただ、毎回おかしいというわけではなく、おかしい場合もある、という感じです。

というのも、ユーザーがカスタムダイアログを表示後、そのまま放置した場合に備えて、記録した時間が一定以上たっていたらキャンセルとみなして中断するような処理を入れています。 その際、PropertiesService から値の読み込みができなければ、記録開始をしていないとしてキャンセルと同じ処理としています。

明らかに、決めた時間(10分)も経っていないのに、カスタムダイアログからのコールバックで、時間が経過した旨のダイアログが表示されたのです(画像撮り損ねました・・・)。

そこで、Logger を使って、Property 設定前後の変数の値などをいろいろとログに出して観察していると、挙動がおかしい時は、 PropertiesService にセットしたはずの時刻が取得できていません!

なんだこれは?と思いつつ、 設定した Property についていろいろとログを出して調べると、どうも PropertyService への書き込みは即座に反映されるというわけではないようです(独自調べなので、根拠なしですよ)。

やられました。 単純な変数のようには使えないようです。

排他処理の追加 (3) : PropertiesService の書き込み確認

そもそも、 PropertiesService は『変数』ではないので、無理もないことなのでしょう。まあ、これを排他制御に流用する筋が悪いのかもしれません。この辺りは、GASに詳しい方にぜひ教えていただければと思います。

なんにせよ、排他制御しないと目的のものが作れず困ってしまうので、 Property が書き込まれたか否かを確認する処理を追記します。

追記&いろいろと修正した形がこちら。

https://github.com/samples-of-junichim/GAS_custom_dialog_lock_sample/tree/04_complate

主な修正としてはカスタムダイアログからのコールバック処理に問題があったので対応しました。 コールバックでは、 Property に設定した時刻を元に時間の経過を判定していたのですが、実際に一定以上の時間が過ぎた場合に、別ユーザーがカスタムダイアログを呼び出し、処理開始時刻を書き換えるとタイムアウトするべきユーザーが処理を継続できてしまうという問題があったので、カスタムダイアログ経由で呼び出し時刻の受け渡しを行うようにしています。

これで試すと、(試した範囲では)問題なく排他制御できていました。

ふー、一件落着

注意点

ちなみに後日、この記事まとめなおすときにいろいろと試したら、Property 設定でほとんどタイムラグがないような振る舞いをしていました。 たまたまなのか、Google Apps Script 側で何か変わったのかちょっとわかりません。

なので、ひょっとしたら最後の Property の書き込み確認は余計な負荷をかけるだけになるので、不要かもしれません。 もうちょっと GAS を使い込まないと見えないところかもしれませんね。

こういうこともあったらしいぐらいにとどめておいてください。

まとめ

GAS 便利ですが、カスタムダイアログを使った場合の排他処理に意外と手間取りました。 とはいえ、GASは頻繁にアップデートされているので、そのうち、これにも対応したロック処理が追加されるのではないかと期待しています。

せっかく無料で使えて、いろいろとできるので、もうちょっとGAS使った仕事を増やしたいところです。

おまけ

冒頭で、Google Apps Script で『スプレッドシートに紐づく形式の場合』Gitで管理しにくい、などと書きましたが、後から、 Chrome 拡張『Google Apps Script GitHub アシスタント』を使えば簡単にリポジトリにpush/pullできることが分かりました! (この記事中のスクリプトは、このプラグインでGitHubのリポジトリにpushしたものを示しています。)

こちらを試した話は、別の記事にまとめていますので、ご興味のある方はそちらもご覧ください。