トップ «前の日(05-26) 最新 次の日(05-28)» 追記

2003-05-27

_ Trusted Computing

と言っても Microsoft のそれではないですが :-)

TrustedDebisn の名称変更に際して何があったのかは知りません :-)

TrustedBSD はたまたま ring の BSD のとこをふらふらしてたら見つけたのですが、なんだかまだよく分かっていません(^^; てゆーか OpenBSD でいいんじゃないの?とか思うのですが…。何が違うの?

Tags: Unix

_ 地上波デジタルラジオ

http://www.zdnet.co.jp/news/0305/26/cjad_kodera.html

ノーマークでした。いや完全に。

地上波デジタルは実は期待しています。なぜって衛星なんて天候に左右されやすいものはダメですよ。表日本に住んでる人は知らんでしょーが、裏日本じゃ衛星なんてダメダメです。冬場はノイズ乗りまくり。もっと声高にこういうこと言ってくれる偉い人はおらんのか。

Tags: TV

_ こんな Web ページはいやだ@/.-j

http://slashdot.jp/pollBooth.pl?qid=124&aid=-1

基本的なことが抜けているので補足。

  • font size="-1" しまくり
  • 全部ボールド

は勘弁してほしい。blink や配色ほど目立たないが、だからこそ凶悪な気がする。font size="-1" はどう考えても IE のデフォルトサイズ向けの対処なんだけど、そんなもん「ユーザーの好きにさせろ」っての。

Tags: Web

2005-05-27

_ for でぶん回して clamscan

恥ずかしながらファイルサーバ内にマクロウィルスを発見。メールはプロバイダがスキャンしているので、これは基本的にリムーバブルメディアを介して入ってきたんだろうなぁ。

さて、ここから先が問題。ファイルサーバは Mac で動いているので Windows では認識できないファイル名などが散在している。運良く手元の機械は OS X だが、とりあえず今回のマクロウィルスに感染する可能性のある Excel のファイルのリストを作成するにはどうしたらよいか?

とりあえず Information List という Classic アプリに頼ったが、今なら Unix 系のアプリと AppleScript でなんとかなるかもしんない。AppleScript はまったく経験がないので今回は Information List でタイプ、クリエータ情報まで含めてリストを生成し、改行コードを lf に変換して awk でそれらに対して検索を掛け、Excel ファイルだけのフルパスのリストを作成する。*1Classic Mac の世界では拡張子は文化として存在しないのでタイプ、クリエータに対して検索を掛ける必要があるのと、リストがタブ区切りで生成されるのが分かっているので、こういう場合は awk がすごい便利。

そうしてできあがったリストに対して今度はスキャンを掛けるのだが、Information List の吐くリストは Classic 流で、フォルダの区切りに : が使われているので

sed -e 'y/\/:/:\//'

で / と : を入れ替えて clam に食わす。しかしここでリストを

for i in `cat list`; do clamscan $i; done

ってやると「半角スペースを含んだ名前が分割されちゃって正しくスキャンできない」。慌てた私はファイルのリストに対してエスケープを書き加えてみたが、これは間違い。正解は

IFS=$'\n'

とシェル変数を設定し、「改行だけを for 文のパラメータの区切りにする」ことで対処するのが簡単。

ログは -l でログファイル名を指定して吐くよりリダイレクトした方がなんだか望みの形になったのでそうした。

で、問題のファイルを特定したら対処開始だ。ここから先は今回のテーマじゃないので割愛。フルスキャン掛けないと意味ないんじゃねーのってゆー正論も今回は無視。*2

★ OS X で作業するときはファイル名は Unicode なので普段の作業の都合上 EUC に設定している人は注意。

Tags: Tool Security

*1 便利だけどまどろっこしい。

*2 NAS に移行完了すればこんな面倒なプロセスは全部省けるのだが。


2007-05-27

_ 個人的によくあること

  • 見知らぬ人にモノを尋ねられる
    • 昔は公園でよく幸せを祈らせてくれと頼まれた
  • 外食産業で注文を忘れられる

南禅寺前の交差点で外国の方に道を尋ねられた。えーとワタシも観光客ですが。まぁ看板はすべて読めるけれども。とりあえず「こっちだと思う。たぶん。maybe.」と答えた。ありがとうと言われなかった。珍しい人だな。こっちの答え方がよくなかったかなぁ?

その後、三条河原で MealMUJI とやらに入る。へー、無印はこんなこともやってるのか。いいなぁ。こういうの、田舎には増えないだろうか。MealMUJI のようなスタイルでは注文忘れが発生しようがないので安心だ。いや、増えてほしいのはそういう理由じゃなくて、「たいがいの定食屋は量が多すぎるので減らして安くしてほしいと思っているから」です。

Tags: 日々

2008-05-27

_ 『インターフェイス指向設計』読了

最初にオススメポイントだけ書いておく。この本には

  • テスト容易性の確保
  • 複雑性保存の法則への対処

へのヒントが詰まっている。


kakutani.com にアサマシセンターがあるのかと思ったけどなかったので自分ので貼っちゃうよ。献本なのに自分のアサマシ貼ってるなんてふてぇやつだよ、オレ。

読み手に推奨される準備

まずはじめに「本書の読者対象」を挙げておくと、

本書は、ある程度のプログラミング経験と、オブジェクト指向設計の基本的な知識を持つ開発者を対象にしています。オブジェクト指向に深い造詣がある読者でも、インターフェイス指向のアプローチを学ぶことで、これまでにはなかった設計の概念を得ることができるようになるでしょう。また、インターフェイスを理解することは、SOA(サービス指向アーキテクチャ)の設計においても有用です。

と書かれている。

正直に告白すると自分はこれをなめていた。普通に UML もデザインパターンも出てくる。もっとも、この本に出てくる図は十分に簡単だし最低限の説明はなされている。またデザインパターンもインターフェイスに注目してごくわずかしか出てこない。なんだけど、覚悟しておくのとしていないのとでは雲泥の差。早めに覚悟しておこう。UML もデザインパターンも普通に出てくるよ。

あと前提知識としては当然 Java 的な意味での interface(PHP 5 以降にもあるね)、あるいは Ruby で言う Module がどういうものか分かっていないとつらい。それに継承の問題について自覚的であった方がよい。継承がいかに扱いにくいかを普段感じていないと、サンプルのコードだけではいたずらに複雑になっただけに感じられてしまう。丁寧に書かれているんだけど、問題意識がなければたぶん通じないんじゃないかな*1

内容

I部、特に3章と4章では本書で扱うインターフェイスに関する用語が怒濤の勢いで出てくる。リファレンス的な部分。その前の2章で契約というキーワードでインターフェイスを考えるための材料が整理されている。

またこの中でさりげなくだけど何度もインターフェイスの変換について触れられている。これはのちのち効いてくる。

5章ではポリモーフィズムを継承ではなくインターフェイスを使って実際に組み立てていく。Role を使ってフットボールチームの話をしているうちはよかったんだけど、Java の InputStream に縁のない自分はちょっとこの辺で意識が飛んでしまった。

II部では開発を進める段取りと実際の作成。7章でインターフェイスに注目しながらユースケースを作り、それをテストしようと試みる、IRI カードなどの話。メソッドが明確になったら実際にテストコードが出てくる。8,9,10章は動くものの話。内容的には Web 系が中心でなじみやすい印象。

最後 11 章でインターフェイス指向からパターンをおさらいして終了。

感想

一言で言うと素晴らしくオライリーらしい。歯ごたえたっぷり。悪く言えばもっと内容を噛み砕いてほしかった。噛み砕く手間と分量で値段は上がってしまうだろうけど、この本は例え1000円高くなっても3600円。十分通用するんじゃないかなぁ。オライリーだし。

実際のところ特別難しいわけじゃないと思うんだけど、個人的な好みはもっと図やサンプルを多くしてほしいんだな。自分は言葉だけでは覚えられないタイプで、何かしら頭の中にビジュアルやアニメーションが思い浮かべないとダメなんで、それを用意しておいてくれるととても嬉しい。いやユースケースやシーケンス図や IRI カードは出てくるんだけど、なんかそういうものじゃないんだなぁ。うまい言葉が見つからない。

なんていうか結構いろんな説明がサラッと出てきていて、もったいないなぁと感じる部分がちらほらあった。ここは重点的に説明しようと感じられたのは「継承とインターフェイス」の部分くらいで、あとは「ま、フツーに知ってるよね?」的な印象。Dependency Injection なんか「あるいは Dependency Injection パターンを用いて実装を設定できます。」とか「おいおい、それだけ?」みたいな。実際のコード間のインターフェイスをどう作り上げていくか、すごく大事な部分のような気がするんだけど、その辺はインターフェイスに注目して分析、設計していく過程としてはあまり重視されていないのかしら。それともやはり使えて当然か*2。そういう意味では経験で補いながら、手を動かしながら読む感じ。例えば DOM と SAX の違いってサンプルコードだけで分かるのかな。自分は幸い両方経験があったからすんなり分かったけど、そうでない場合は一つ一つ噛み砕くのにそれなりに時間掛かるんじゃないかな*3

あと当然なんだけどインターフェイスという言葉がたくさん出てきてその意味が文脈によって変わるので、特に前半の説明の部分でなかなか頭の痛い思いをさせられた。より一般的な常識的な意味でのインターフェイスであったり、ある程度の機能のまとまりを意味していたり、Java用語的な Interface を意味していたりする。その使い方をいくつかに分類して、ここではこういう意味、ここではこういう意味と、例えば type face を変えるなどして明確にできていたらこれはかなり画期的な本になっていたのではないかと思う。

なんだろう、この出だしの滑らかさとは裏腹にいきなり歯ごたえたっぷりな内容に移行する感じ、覚えがある…と思っていたら、読み終える直前に気づいた。

この本、『プレファクタリング』の人が書いてた。

実はわたくしこの『プレファクタリング』、途中で挫折しております*4。いちばんの理由は Java のコードを読むのがたるいというものなんだけど、今回も終盤はその呪いを解くことはできなかった。だいぶ端折ってしまった。疑似コードもあんまり読みやすい気がしなかったけど、これはオレのセンスがないのかなぁ。内容はいいと思うんだ、内容は。

オライリーの本て、なんかそういうとこあるよね。*5

ただ思いっきり自分の言葉で要約すると

  • テスト容易性の確保
  • 複雑性保存の法則への対処

へのヒントは確実に詰まっていると思う。高凝集、疎結合という言葉が帯にはあるんだけど、自分としては上の二つの言葉の方が断然しっくりくる。この視点で振り返ると、インターフェイスの変換の話がいくつも出てくるのは実はこのためかと気づく。

オススメと言えばオススメ。でもコレ読むとすごくよく分かるよ!新しい発見があるよ!という意味ではなく、これは通過しておくべき、という意味なのかなぁ。さらっと読めば読めちゃうと思うんだけど、さらっと読んじゃダメというか。たぶん自分はこの先何回もこの本を開き直すと思う。API を使ってゴニョゴニョとかするときにもそのインターフェイスの意味、機能、他のインターフェイスへの変換などのヒントになると思うから。

とりあえず今度もう一回『プレファクタリング』に挑戦してみる。今見直したらプレファクタリングにもインターフェイスの話出てくる。あー、今読めばイケるかもな、これ。コード全体を変更に強くする、どちらかというと実装のためには『プレファクタリング』を、分析、設計のためには『インターフェイス指向設計』を読むのがいいみたい。まさに合わせて読みたい。

あとちゃんと『リファクタリング』と『達人プログラマー』も読んだ方がやっぱいいんだよね? (実はちゃんと読んだことがない。)


直接関係しないんだけど、PHP 5 で interface が入ったじゃないですか。でも名前空間は相変わらずないんですよ。なんか interface の機能はいいんだろうけど、名前争奪戦が激しくなるだけなんじゃないの?という印象を持ちました。やっぱまだロジックは Ruby で書いてテンプレートを PHP で書くのが最強という印象は変わらないなぁ。

Tags: Book

*1 もちろんこの本に興味を持つ人は当然問題意識も持ってるんだと思うけど。

*2 というよりインターフェイス指向そのものではないから端折られているのか

*3 これくらいサクっと読めて当たり前ですかそうですか。

*4 予備知識なしに店頭で即買いしてた。これもとてもいい本だと思っている。もしかしたら今度は読めるかもしれない。

*5 例えばコード片の部分の見栄えを少しだけ変えるとか、そういう工夫してくれないじゃん。ああいう細かいところが少しずつこちらの頭を疲れさせていって、最後はなんだか難しい本だった的な印象を残すんだよね。この本は正直、値段と分量をどう受け取るか、結構その人次第な部分が大きい気がする。自分としては実りの多い読書体験だったし、この値段は安いと思うけど、みんなにオススメなのかというと、なんかそれも違うような。自分と同じようなモヤモヤを感じている人には絶対オススメなんだけど、自分より上のレベルの人はこんなこと言われなくてもフツーにできてそうだし、逆に自分より下の人にこの本を読んだことでうまく説明できそうか、あるいはこの本を読ませて成長できそうかと言うとそれもちょっと違うような。

本日のツッコミ(全2件) [ツッコミを入れる]

_ かくたに [丁寧な書評ありがとうございます! 献本してよかったw kakutani.comでの対応が遅れていてすみません。]

_ wtnabe [やった! ほめらりた!]


2010-05-27

_ schemeのないURLは相対URL

知らなかった。もしかして Web を支える技術には載ってました?(未読)

問題

  • GoogleAjaxAPI を使って jQuery を読み込んでいた
  • 開発、検証環境では http だが本番では https で動く
  • http での読み込みを決め打ちしてたら IE で怒られた><

要件

  • schemeの変化に自動で追随してほしい

Google Analytics とかどうしてんの? なんか scheme の判別して URL を組み立て直してるよ。あーじゃあこれ真似すればいいか、なんかでも面倒だな。

ここで神降臨!

Twitter / Yosuke HASEGAWA: @wtnabe script src="//exam ...

@wtnabe <script src="//example.jp/foo.js">と書けば現在のschemeで読んでくれます。

……。ほんとだ。

RFC 2396

しかし実はこの根拠が分からなかった。なんか言われればそれでいいような気がするけど、scheme だけ欠けている URL を見たことがなかったから。でもちゃんと定義されていた。

RFC 2396 - Uniform Resource Identifiers (URI): Generic Syntax

     absoluteURI   = scheme ":" ( hier_part | opaque_part )

  URI that are hierarchical in nature use the slash "/" character for
  separating hierarchical components.  For some file systems, a "/"
  character (used to denote the hierarchical structure of a URI) is the
  delimiter used to construct a file name hierarchy, and thus the URI
  path will look similar to a file pathname.  This does NOT imply that
  the resource is a file or that the URI maps to an actual filesystem
  pathname.

     hier_part     = ( net_path | abs_path ) [ "?" query ]

     net_path      = "//" authority [ abs_path ]

     abs_path      = "/"  path_segments

(snip

  The syntax for relative URI takes advantage of the <hier_part> syntax
  of <absoluteURI> (Section 3) in order to express a reference that is
  relative to the namespace of another hierarchical URI.

     relativeURI   = ( net_path | abs_path | rel_path ) [ "?" query ]

  A relative reference beginning with two slash characters is termed a
  network-path reference, as defined by <net_path> in Section 3.  Such
  references are rarely used.

えーと、これで見ると

//example.com/path/to/resource

net_path として定義されていて、net_path だけの URL は relativeURI と定義されていることになる。なるほどー。

※ ちなみにちゃんと読んだら Google Analytics の tracking code が scheme 判別をしているのは scheme によって net_path が異なるからだった。確かにこの場合は判別して書き換えないとダメだね。

Tags: Web

2011-05-27

_ RailsとjQueryでformの必須項目を自動強調してみた

Railsネタいっぱいたまってるんだけど全然吐き出しが追いつかない…。

基本的なアイディア

  • Model.validators を利用する
  • これを HTML に dump
  • jQuery でこれを拾って form の DOM をいじって強調する

ActiveModel には validators というメソッドがあり、これを利用するとどんな validator が定義されているかが分かる。この中でとりあえず ActiveModel::Validations::PresenceValidator がいわゆる not null 制約なので、こいつが定義されていたら

入力フォーム上では必須項目

扱いになる。これをうまいことユーザーに feedback してあげればよい。

※ 実際に動かして確認して書いているけどデモはないので各自手を動かして作ってください。

確認した環境
  • Ruby 1.8.7
  • Rails 3.0.7
  • jQuery 1.4.4

Controller

Controller はとりあえずこんな感じだとする。

def (new|edit)
  @model = Model.new
end

要は新規作成でも編集でも Model の instance を Controller のインスタンス変数に持つ場合が多いよね、ってだけ。もちろんこのまま書いても動きません。

View

template にこんなものを用意。Controller で作ったインスタンス変数の class に validators が定義されているので、そいつを呼び出して、JavaScript で扱いやすい形に整形して吐く。

<div id="model-essentials" data-fields='<%=
  @model.class.validators.select { |e|
    e.is_a? ActiveModel::Validations::PresenceValidator
  }.map { |e| e.attributes }.flatten.to_json %>'>
</div>

id は JavaScript 側から取得しやすいように付けただけで、適宜決めればよい。

JavaScript

var fields = $('#model-essentials').data('fields');
$(form item selector).each( function( i, e ) {
  var self = $(e);
  if ( $.inArray( self.attr('id'), fields ) >= 0 ) {
    self.append($('<span>').text(' ※').css('color', 'red'));
  }
});

form item selector は form の各入力項目をなめるための selector になる。また上のコードでは各入力項目に model の field と同じ id が振ってあるといういちばん簡単な状態を想定している*1

ここでは form の各入力 field のラベルに相当する部分に赤い ※ を付け加えることを意図している。恐らくラベルと input タグは分離していると思うので乱暴に append しているが、構造に合わせて調整してほしい。

気づいたこと

schema や Model, Spec だけを眺めているより実際の form の形になってみた方が

「これ必須になってないけど変じゃね?」と気づきやすい

ことが分かった。仕様の確認にも使いやすいかも。

あと jQuery.data() で JSON 形式のデータを取得したら String じゃなくてちゃんと Array で返ってきた。賢い。

*1 HTML の構造がちゃんとなめやすいものになっていないと面倒くさいので、ちゃんと考えて構造を作りたいですね。まる。


2017-05-27

_ Google Apps Script開発をもうちょっとモダンにしてみる

よりモダンな開発サイクルへ

前回から早くも1年半の月日が流れてしまったが、今回のテーマは

  • CI/CD と組み合わせてモダンなワークフローの完成形を目指す
  • そのために Node.js ベースのテストフレームワークがちゃんと動くようにする
    • Google サービスのオブジェクトを stub/mock する
  • CoffeeScript をやめて ES2015 へ

の辺り。

前回の記事で残った課題

前回調べた手法を使うと Codegs を利用して Node.js で書きながら 1ソースに build できる。このコードを gas upload すれば GAS 上で動くので、

  • コードを手元の好きなエディタで編集し、
  • Git でバージョン管理し、
  • 適切に module 分割しつつ最終的に GAS で動かす状態に持っていく

ことはできた。ただし、build プロセスが GAS 向けに最適化されており、最終的に全自動にするにはあまり向いていなかった。

gasifyの発見

個人的にはモダン Web 開発の文脈では Browserify と組み合わせてみる実験を

Rails + Browserify + Mithril + cmsxで動くもん書いてみた - あーありがち(2015-09-23)

でしてるんだけど、その後、Google Apps Script 開発方面にこれの影響が来ていたことを知る。

なるほどなるほど。gasify がキモらしい。

fossamagna/gasify: Browserify plugin for Google Apps Script

確かにこれを使うとものすごく手軽に lodash を使うことができた*1。これで GAS 用のライブラリになっていない npm の小粒なモジュールも利用可能だ。こりゃーいい。

テスト用ツールチェイン方面の課題

ということで

でいくことにした。

最終的に使ったもの
  • browserify
  • watchify
  • gasify
  • babelify
  • babel
  • babel-preset-es2015
  • babel-core
  • babel-register
  • power-assert
  • intelli-espower-loader
  • mocha
  • sinon
  • gas-manager
  • lodash

こんな感じ。

CI/CDするうえで課題になる認証情報は環境変数で

今回 GAS の開発フローを自動化しようと思ったきっかけは、手離れさせたいのがいちばん強いんだけど、その次は

Google Developers Japan: Apps Script による高度な開発プロセス

だった。Google が公式に紹介するんだから、これまでの課題はいろいろ解消されているに違いないと思ったのだ。

結論から言うと期待は裏切られた。gas-manager でできることとの違いが自分には分からなかった。以前も書いたが、Google Apps Script を使った開発については日本の GAS コミュニティの方が Google 本家より進んでいるんじゃないかと思う。

さて、gas-manager も node-google-apps-script も何が問題かというと、要は認証情報を JSON ファイルで保存する形になってしまっているので、API キーとか ssh の秘密鍵より取り回ししにくいのだ。

Authentication with Google Cloud Platform - CircleCI

を見つけて「おっ」と思ったが、これは gcloud コマンドを使うことが前提の話で、Google Drive API を使う話ではなかった。が、ここにヒントがあった。

自分でやったことは以下の四つ。今回は GitHub + CircleCI で行ったが、考え方は他のツールを使っても変わらない。

  1. gas-manager で credential 情報の JSON を作成、保存する
  2. gas-manager を使って Git + GitHub で開発できる状態に
    • gas-project.json は含む
    • gas-config.json は .gitignore へ
    • npm/yarn run で gas upload / download できるように
  3. CircleCI の project に環境変数を作る GOOGLE_CREDENTIAL とか。これに上の gas-config.json の内容を放り込む
  4. circle.yml で以下のように gas-config.json を生成
dependencies:
  override:
    - echo $GOOGLE_CREDENTIAL > $HOME/$CIRCLE_PROJECT_REPONAME/gas-config.json
    - yarn install

これで gas-manager は -c で生成済み gas-config.json を使うことで、認証情報をリポジトリに保存することなく CI 上で認証を通せる。

gasifyを使ってもimport/exportは使えないのでpresetを調整する

確認したバージョンは gasify 0.1.0

最近 JavaScript復習2017 - importとuse strictとメソッド定義 - - あーありがち(2017-02-19)

で勉強したようにイマドキは import / export だよねーと思って喜んで書き始めたのだが、import / export のところで Script Editor がエラーを出す。*2

Google Apps Script は独自仕様の JavaScript 構文 + 独自の JavaScript オブジェクトによるサーバサイドスクリプトで、Babel を通したものでも動かないものはあるということです。これは今度は Babel 側の import / export の処理方法に原因があるので、

Google Apps ScriptでES Module(Babel)を使うときのTips - Qiita

gasify の作者が babel preset を作り始めようとしているようで、もしかしかたらこっちの方が本命になるかもしれないけど、まだ何も中身はない模様 ;-)

を設定します。これは ES 3 時代の文法に適合するように transpile してくれるので import / export が正しく動くようになる、というもののようです。

fossamagna/babel-preset-gas: Babel preset for all Goolge Apps Script plugins.

ということで 2017-05時点では module.exports と require() を使いましょう。

Mocha + babel-register + intelli-espower-loaderは順番に注意

確認したバージョンは

  • mocha 3.4.1
  • intelli-espower-loader 1.0.1
  • babel-register 6.24.1

intelli-espower-loader を先に食わせろ。

具体的なコマンドは以下のようになった。

mocha --require intelli-espower-loader --require babel-register --recursive test

Googleサービス用オブジェクトをSinonでstub out

分かったこと。

  1. gas-local のメリットはよく分からない
  2. Sinon はちゃんと存在しているメソッドがないと stub out できない

テストのサイクルを速くたくさん回すために CI を利用したい、しかし GAS は Google 上の独自サービスあってこそのもの、Node.js だけではすべての機能を動かすことはできない、だから GAS 独自オブジェクトは stub/mock に差し替えてテストを動かす必要がある。

そこで最近は gas-local を使うという話が

Apps Scriptによるより高度な開発プロセス/More Advanced Development Process with Apps Script // Speaker Deck

にあったのだが、gas-local は mock も使えるテストフレームワークと書かれている割にテストの方法についての記述が見つからない。そこでこっちを追うのはやめて、普通に Node.js 向けの代表的なツールチェインで完結させることにした。

上に挙げた mocha のコマンドで以下のものが揃っている。

  • テストランナーは Mocha
  • アサーションは PowerAssert
  • 構文は Babel を使って ES2015 で

そして JS で test double と言えば Sinon だろう。

Sinon.JS - Standalone test spies, stubs and mocks for JavaScript. Works with any unit testing framework.

こいつで stub out してやれば、まぁなんとかなるだろうと思っていたが、ちょっとハマった。

それは

存在しないオブジェクト、存在しないメソッドは stub out できない

というもの。そらそうか。

確認したバージョンは Sinon 2.3.2

今回試しに作ったコードでは

FetchUrlApp

を使っていたので、

class Sender {
  urlFetcher() {
    return (typeof FetchUrlApp == 'object') ? FetchUrlApp : {fetch: function(){}};
  }
}

として間接的に stub out 可能なオブジェクトを用意することとした。具体的に stub out するコードはこんな感じ。

var sender = new Sender();
sinon.stub(sender, 'urlFetcher').callsFake(function() {
  return {
    fetch: function(uri, params) {
      return params.payload;
    }
  }
});

何をしているかというと、FetchUrlApp.fetch(uri, params) で POST を行う部分を stub out している。

  1. urlFetcher() というメソッドで本物の FetchUrlApp かそれを stub out 可能な構造のオブジェクトを得る
  2. stub out 可能なオブジェクトとは stub out したいメソッドをすでに持っているオブジェクト。ここでは fetch() メソッドを利用する予定なので、Node.js 環境で実行した際には {fetch: function(){}} というオブジェクトを返すようにしている。

てな具合。慣れないとうへぇって感じだし、結局 production 環境で動くことの確認は手動で一度でも動かしてみないとダメなので、本当に全自動というわけにはいかないが、安定して回るようになれば Node.js だけで高速に開発サイクルを回せるので、なかなかよいと思う。

何より、テスト向けに出てきたツールの中に GAS 開発独自のものはないので、GAS 以外のノウハウが活かしやすい。これは大きい。全部見返してみても、セットアップが済んでしまえば、あとは import / export が使えないことに気をつける以外は特別な部分はほぼないはずだ。

これであとは staging と production を切り替えられるような仕組みを用意すれば、普通の Web アプリのように GitHub Workflow でだいたいの開発を回せるはずだ。

よしよし。

*1 これまでは underscoreGS とか使っていた。

*2 Drive API を通じて独自にバージョン管理をし始めるとこういう時に何が起きてるか分からなくて困るのだが、落ち着いて build 済み JS を Script Editor にコピペしてみよう。