Previous month:
January 2010
Next month:
March 2010

Google App Engine上のベスト・プラクティス、その1: Datastore

 Google App Engine上でアプリを作りはじめて約二ヶ月。いろいろと分かって来たこともあるので、自分へのメモも含めてまとめてみる。まずは、Datastoreの話から。

なによりも大切なのはデータベースの設計

 あたりまえと言えばあたりまえの話だが、App Engine上でアプリを作る上でもっとも大切なこと(=頭を使うべきところ)は、データベースの設計である。特にリレーショナル・データベース(RDB)上でのアプリ作りに慣れた人には、大きな「発想の転換」が必要なので、ここは注意が必要。

 特に絶対にやっては行けないのは、

  • 将来RDB上へ移行できるようにレイヤーを作って、その上にアプリを作る
  • RDB上に作ったアプリをデータモデルを大幅に変更せずにApp Engine上に移植する
  • RDBを前提に設計されたフレームワークをApp Engine上に載せて、その上にアプリを作る

など。App Engineの利点を活用するためには、その特徴を最大に活かすように(データ・モデルだけでなく)アプリケーションそのもののアーキテクチャを最適化すべき。逆の言い方をすれば、それができない状況であればApp Engine上に載せる意味はあまりない。レイヤーをもうけてポータビリティを高めようとか、RDB上に作られたアプリをアーキテクチャの大幅な変更なしに移植しようとしている人がいるのであれば、そもそも「何でApp Engine上にアプリを載せたいのか」という発想が本当に正しいのかどうかから見直すべき。

Datastoreの特性を理解する

 Datastoreの特性についてはGoogleから提供されているドキュメントに必要なことは書いてあるので、ここではいちいち説明しないが、それを頭に入れた上での私なりのベスト・プラクティスを箇条書きにするとこんな感じになる。

  • ReadとWriteのスピードの違いが桁違いに大きい → 1つのHTTPアクセス中にするputの数はできるだけ少なくしておく。通常は0から1。よほど複雑な場合でも2、3回。5つ以上のputが必要な状況に陥ったとしたらデータ・モデルの設計から見直すべき。何らかの理由でたくさんの数のEntityを更新しなければならない場合(たとえばスキーマ変更のために1000個のEntityを一気に書き換える)などは、TaskQueueを使って順繰りに実行させる。
  • Entity Groupはトランザクションのためにある → Entity Groupはできるだけ小さくしておき、トランザクションが不要なところに親子関係は持たせないようにする。エンド・ユーザーから見て親子関係にあるからと言って、必ずしも同じEntity Groupに入れる必要はないのでそこを間違えないように。たとえば、ブログのエントリーと、それに対するコメントが良い例。まずは、親子関係を一切持たせずにモデルを設計して行き、どうしてもアトミックに複数のEntityを同時に変更する必要が出て来た段階で、親子関係を持たせてEntity Groupを作る、という作り方をおすすめする。
  • データの正規化は基本的にはしない → エンド・ユーザーから見て一つの「もの」(たとえば商品、ブログエントリー)があった場合、それに付随する情報(たとえば、タイトル、値段、更新日時、作者)をEntityそのもののプロパティとしてもたせておき、Queryなしに一回のgetですべて取得できるようにしておく。これは、RDBにおける「ベスト・プラクティス」とは正反対の方向を向いたものなので、RDB/SQLに慣れた人こそ気をつけて設計すべきである。
  • JOINがない → SQLにおけるJOINをApp Engine上で実現しようとすると、queryの結果をもとに複数のqueryをするというnested queryをせざるを得ないが、そもそもJOINが必要となるような状況になったことが、データ・モデルの設計がすでにApp Engine向けのものになっていない証拠なので、「ああ、JOINが使えたら楽なのに」と嘆く前に、今一度データ・モデルの設計から見直すべき。
  • Queryはキーの取得だけだととても高速 →  ReadはWriteと比べて早いとは言え、数百のEntityをQueryで取得するとそれなりの時間(千cpu_ms以上)がかかる。ただし、Queryもキーの取得だけだと圧倒的に早いので、「いかにキーの取得だけで済むように設計するか」という部分で頭を絞るべき。場合によっては、keyそのものに情報を埋め込んでおくことで、Entityを取得せずにEntityの情報を得るということも可能なので、ノウハウの一つとして覚えておくと良い。
  • キーを使ったEntityの取得はQueryよりはるかに早い → なんらかの方法でキーを取得しておけば、そこから一つのEntityを取得するのは非常に早いので、それを利用して一つのHTTP GETを非常に高速に(100cpu_ms以下で)処理をすることが可能なので、これは頭に入れておくと良い。
  • Datastoreへのアクセスは無視できない確率で必ず失敗する(実測値で600回に1回程度)→ それに対応したコードを書いておく。HTMLを直接ブラウザーに返す場合は、サーバー側でretryをするしかないが、AJAXでデータを取得する場合は必ずクライアント側にretryの仕組みを入れておく(3回で十分)。
  • App Engineは高レベルなAPIやGQLを提供して既存のアプリケーションの移植を簡単にしている → GoogleがApp Engineに関して言っていることはおおむね正しいが、ここだけは「うそも方便」だと思った方が良い。App Engineの上でスケーラブルなアプリを作りたいのであれば、低レベルのAPIを直接たたくべき。ちなみに、私はGQLは一切使わず、Pythonでdb.Modelを直接操作しているが、APIそのものはとてもストレートで簡単なので、すぐに慣れる。

 このあたりさえしっかりおさえておけば、Google App Engine上のアプリの作成は決して難しいものではないので、ぜひともチャレンジしていただきたい。

 ちなみに、何か書き忘れたことや私の知らないこともあるかも知れないので、もし何かここに追加すべきものがあると思う方には、ぜひともコメントをいただきたい。ちなみに、「その2」はmemcacheに関して書くことを予定している。


「なぜAppleはiPadにFlashを載せるべきではない」のか

 気がついた人も多いと思うが、iPadのアナウンスメントであっさりと無視されたのがAdobeのFlash。私は意図的(=「Flashなんか重要じゃない」というメッセージ)と読んだが、皆さんはどうだろうか。

 iPhoneがFlashをサポートしていないことに対するAdobeを含めたさまざまな方面からの批判を考えれば、「the best way to experience the web (最高のウェブ環境)」を売り文句のiPadが、これだけ広く使われているFlashをサポートしないというのはおかしな話だ。

 不思議に思う人も多いかもしれないが、自分をAppleの経営陣の立場に置いて良く考えてみれば答えは明確になる。

 Appleという会社は、昔からさまざまなクリエーターたち(アーティスト、ミュージシャン、ウェブ・デザイナー、etc.)を魅力的で便利なパソコンやツールで味方につけ、彼らの作品を消費者に楽しんでもらうための道具としてさまざななデバイスやサービスを提供する、という形で大きくなってきた。

 そう考えると、よりAppleのビジネスを盤石なものにするためには、今後ますます重要になってくる「マルチメディア・ウェブサイト」のプラットフォオームを提供する立場になり、そこでオーサリング・ツールのビジネスをすることは必須である。

 プラットフォームに関しては、すでにWebKitが順調にデファクト・スタンダードの地位を築きつつあり、Appleがリーダシップを取って押し進めるCanvasタグやVideoタグを含めたHTML5が業界標準になろうとしている、というのを見れば、とても順調なことは分かる。

 問題は、オーサリング・ツールだ。ウェブ上のアニメーションというとFlashが相変わらずデファクト・スタンダードだが、その状況を打破しにくくしているのが、Flashの普及率とAdobeが提供するツール(Creative Suites)のクオリティの高さ。

 当然Appleとしては、(公式には認めていないが)HTML5ブラウザー向けのオーサリング・ツールの開発は進めているし、HTML5の普及のためにさまざまなことしている。WebkitがGoogle の Chrome ブラウザーのレンダリングに採用された時点で、Appleのブラウザーの標準化におけるリーダシップ・ポジションは確固たる物となった。

 その状況を考えれば、iPhoneやiPadでFlashをサポートするような「敵に塩をおくる」ようなことをする必要は一切ない、とAppleの経営陣が考えるのは当然だ。

 興味深いのは、このあたりの考えはGoogleも同じだということ。HTML5を押し進めるGoogleとしては、一日も早く、Yutubeも含めた自分たちのサービスでも、Flashを早く捨ててHTML5に乗り換えたいところだが、それにはまだまだ時間がかかる。それであれば、「少なくもYoutubeがFlashなしでも楽しめる様に」と専用アプリをiPhoneやiPadに提供しつつ、徐々にFlashへの依存度を低くして「脱Flash」の日のための準備を着々と進めているのだ。

 そう考えると、これから数年以内に必ず起こるFlashからHTML5へのシフトを考えると、OutputのフォーマットをFlashにでもHTML5にでもできるオーサリング・ツール、というのを作ると良いビジネスになると思うんだがどうだろうか。Adobe自身はもちろん作って来ないし(典型的なイノベーションのジレンマ)、Appleは直接HTML5へ走ると予想できる。そう考えると、「FlashからHTML5へのマイグレーション・ツール」という位置づけでそれなりのオーサリング・ツールを作れば、「まだFlashは捨てられないが、HTML5の時代が来たときには乗り遅れたくない」人たちの心をつかめると思うんだがどうだろうか。

【追記】ちなみに上のエントリーは、「自分をAppleの経営陣の立場においてみれば」という話で、当然だが、「自分をAdobeの経営陣の立場」においてみれば全く別の見方ができるわけで、「どちらが正しい」などということはない。一つだけはっきりしているのは、AppleもGoogleもHTML5ブラウザーの普及を加速して、一日も早くFlashから脱却したいと考えていること。

 じゃあ、ユーザーや業界全体にとって何が良いかというと、これも悩ましい。当面の利便性を考えれば、iPadがFlashをサポートしてくれた方がユーザーにとっては喜ばしいことだし、Flashをすでに採用しているウェブサイト運営側にとっても余計な手間をかけなくても良い。しかし、これはあくまで短期的な利点であり、長期的に考えれば、やはりできるだけ多くのユーザーがHTML5準拠のブラウザーに切り替え、ウェブサイトも積極的にHTML5をサポートした方が業界全体にとってはプラスなので、そこでAppleとGoogleがリーダーシップをとっていろいろな方法で(「FlashをiPadの載せない」という荒技も含めて)HTML5へのシフトを加速してくれることは喜ばしいことだ。

 その意味でも、FlashからHTML5への移行をスムーズにするツールというのは、とても良い触媒となってくれると思う。MicrosoftもそろそろSilverlightに固執するのを辞めて、そんな方向に動いても良いと思うんだが、それもたぶんMicrosoftのDNAが許さなんだろう。

【追記2】少し四面楚歌の状態になって来たAdobeだが、打つ手がないわけではない。Adobe自身が、FlashからHTML5への以降を加速すれば良いのだ。デザイナーの使いなれたCreative Suitesで作ったFlashムービーやFlashアプリケーションが、iPhoneやiPadのように「Flashを搭載していないけどCanvasをサポートしているブラウザー」上できちんと動くようにすれば良いのだ。それも、JavaScriptでswfファイルを解析してを再生、なんていう中途半端ものではなくて、オーサ・リングツールから直接ブラウザー上のCanvasを操作する最適化されたJavaScriptを生成するところまでやって、「これならHTML5ブラウザーさえあればFlashプレイヤーいらないじゃん!」とデザイナーたちに言わせるところまで持って行くのだ。

 普通の考え方をする経営者だと、こんな風に「今の自分の有利さをないがしろにする」ような戦略はなかなか取れないのだが、Adobeの経営者がどう出るか楽しみである。すでに開発レベルでの戦いは「HTML5がスタンダードになった時のオーサリング・ツールの覇者は誰か?」に移っている。いつまでもFlashプレーヤーに固執していると、HTML5に全力を注いでオーサリング・ツールを提供してくるAppleに足下をすくわれる可能性がある。