火曜日, 8月 25, 2009

【HTML5】 XMLシリアライゼーションの意味 このエントリーを含むはてなブックマーク


続・XMLなのかHTMLなのかそれが問題だ

 久しぶりにHTML5とXMLのネタ。私は1年前のこの記事において、HTML5で作成されたコンテンツが実質的にWelformedでなければ、Web世界の時計が大きく逆戻りすることになる、と主張した。ところが、あらためて最近のWeb事情、特にHTML5の記事を調査してみると、「むしろwelformedでない方がよい」といった感じで書かれているものが多く見つかるようになってきていて大変驚いた。今回は、HTML5のXML対応について、とりわけXHTML5とは何なのかについて述べてみたい。

“Misunderstanding Markup” 日本語訳

(訳:ぼくはXHTML構文が好きだ。なぜなら、そうやって学んだから。小文字で書くこと、引用符で括ること、brやimgにスラッシュを書くことに慣れているんだ。この書き方は、とても気持ちがいい。オバルチンを飲みながら、テレビでEvil Deadを見るような感じさ。でも、君はそうじゃないかもしれない。まるで叫んでるように見える大文字のタグや、スラッシュなしのimg, br要素、属性の省略表記が好きかもしれない。HTML 5だと、これらはぼくらの好きなように書けるんだ。“pave the cowpaths”っていう原則のおかげで、書く人のおまかせになるんだ。「お気に召すまま、お好きなように、好きなだけ、どうにでも」ってね。)



続・セマンティック・ウェブにXMLはいらない?

 セマンティック・ウェブは、ユニバーサルな情報空間を目指したバーナーズ=リーの考えを受けて、強靱で拡張性があり、適応性のある情報の基盤としてウェブを発展させるための目標の一つ。ウェブの目指すもの:W3Cの目標
 これまで、利用者が、ウェブ上のリソースを最大限に活用できるようなソフトウェア環境を構築するためには、XHTML化とRDFaなどのメタデータを使ったウェブの注釈が重要であるとされてきた。しかし、RDFaに代表される厳格なXMLベースのセマンティック・ウェブのアプローチはなかなか広まらず、最近では前述の記事のような「お気に召すまま」が流行っていることもあって、そのきざしすら感じられなくなってきているのが現状のようである。つまり、「貴族になって楽をしよう」で述べたボヘミアンの完全勝利。それは、MicroformatやHTML5のように、Webが実質的にXML以外の様々な表現や実装技術によって成り立っており、そもそもXMLで厳格にすべてを表現すること自体に無理があるのではないかという見方が主流となってきている背景がある。セマンティック・ウェブの目的だけ考えれば、データを取り出せて意味の疎通ができればよいのだから、必ずしもXMLでWelformedでなくてもよい。HTMLでは、どう処理するのかを規定されることに重きを置き、microformatsはXMLさえ前提にしていない。そう考えていくと、welformedかどうかは、結局のところ、XMLという1つの実装規約の範疇にすぎないという狭い議論に落とし込まれていく。関連記事

XHTML5って何?

 一方で、HTMLをデータとして処理したいという要求が大きいのも事実である。Reflex iTextは、テンプレートとしてHTMLを用いるが、これがXMLでなかったらパース処理に大変な苦労を強いられることになる。今後標準となると思われるHTML5についても同様で、テンプレートをHTML5にバージョンアップする際には、できることならXHTML表現を使いたいところである。
 そこで、XHTML5の明確な定義を調べることにしたのだが、これがとても曖昧で気持ち悪いのだ。その原因は、XHTML5のスキーマがないということ、それから、XHTML1.xと同じ名前空間を使っているということの2つである。こうなってくると、モジュール化して他のモジュールを自由に取り込めないのではないかとか、極端な話、XHTML1.xのボキャブラリ以外使えないのではないかとか不安にもなってくる。
 ちなみに、私と同じような疑問をもっている方もいるので抜粋して紹介したい。去年の記事なんでちょっと古いが、開発者の率直な意見をまとめてみた より。


what-wgが「HTML5はモジュールに分割せずモノリシックな規格を作る」って決めてしまったからなぁ…

<video src="video.ogv" xmlns:cc=" http://creativecommons.org/ns#"
rel="cc:license" resource=" http://creativecommons.org/licenses/by/2.1/jp/"/>
XHTML 5でこういうことができたらいいのになあ。video要素とRDFaを両方使うとオレオレXHTMLになってしまう。せっかくスキーマを取り払ったんだから、モジュール化して他のモジュールも自由に取り込めるような仕組みがいいと思う。

validatorにかけると
Error: Attribute rel not allowed on XHTML element video at this point.
などのエラーを返される。@relや@resourceをvideo要素に書くとHTML 5準拠にはならないんだよね。ブラウザでの表示やRDFの抽出はできるだろうから実際あまり問題はなさそうだけど、そのXHTML文書が準拠する仕様はどこにも存在しないってのは、ブラウザの独自拡張時代を思い出させてあまり好きではない。HTML 6あたりで「やっぱりCSSみたくモジュール化しよう」ってことになり、Multimedia ModuleとかMetainformation Attribute Moduleとかが定義されて、制作者はいろいろなモジュールの中から好きなものを選んで組み合わせて使えるようになったりしないかなあ。


HTML5がモジュール化しない理由とXML名前空間の試み

HTML5はモジュール化しないの?で述べられているように、HTML5はモジュール化しない。それは、HTML5から見れば、XMLは単なるシリアライズ表現の一つと位置づけているように、あくまでHTMLがもつ機能だけに焦点をあてた結果であるといえる。XHTML5はXMLに見えてXMLではない、というのは言いすぎかもしれないが、少なくとも、名前空間とスキーマを充実させてモジュール化し、必要に応じて組み合わせて利用するといった、ユニバーサルな情報空間構想の元に作られたものではないことは明らかである。XMLの生みの親である村田さんもこの構想について以下のように述べられている。しかし、2005年の時点ではまだ名前空間の試みがうまくいっていないことを吐露されてもいる。

お仕着せスキーマと誂えスキーマ

今後の方向は、お仕着せスキーマにちょっと手直しをして、従来は誂えスキーマでしか得られなかったような利点を
得ることだろう。名前空間も、もともとそのための試みで
あった(残念ながらうまく行っていない)。
XHTMLがモジュール化されたもの、
RELAX NGがスキーマのモジュール化を重視しているのも、
NVDLが名前空間による分割検証を提供しているのも、すべて
この方向を目指す試みである。あと10年もすれば、
お仕着せスキーマにちょっと手直しをするという方法が
有効かどうか結論が出るのだろう。


XMLシリアライゼーションの意味

XHTML5の疑問を解決すべく、メーリングリストに聞いてみることにした。
回答の要点は以下のとおり。

1) XHTML5の名前空間はXHTML1.1と同じものを使うがXHTML1.xとは区別される。ただし、両者を判別する方法は今のところない
2) HTML syntaxとXHTML syntaxは、HTML5 DOMのrepresentationであり、同じ要素をもつ

詳細は以下のとおり。
議論がずれることを恐れたので深く突っ込まなかったが、名前空間の意味と運用について、これほど解釈が違う人がいるとは思わなかった。


XHTML 2が打ち切りになったのは皆さんご存知だと思うのですが、以下の記事のなかで、XHTMLをHTMLのXMLシリアライゼーションとみなす、といった説明があります。

「W3CはXHTMLをHTMLのXMLシリアライゼーション(XML形式への変換)と見なしている。HTML
5仕様にXMLシリアライゼーションを含め,引き続きHTML WGで検討していく。」

http://itpro.nikkeibp.co.jp/article/NEWS/20090703/333143/

名前空間がXHTML1.xのままだとHTML5のタグを使えないものがあるので、完全なシリアライゼーションはできないと私は思います。

単純に、HTML5のままで、welformedなものをXHTML5と呼ぶと解釈したとしても、welformedかどうかを示すヘッダーなり何かがないと不都合です。(つまりXML宣言なんですけど)
その場合、名前空間はXHTML1.x以外の何かになると思われるのですが、最新のDraftにも新しい名前空間は見当たりません。

この話は以下にも書いているように、去年からずっと気になっているところなんですが、いまだにモヤモヤしています。

http://www.virtual-tech.net/blog/2008/08/html5-htmlxml.html
http://www.virtual-tech.net/blog/2008/09/html5-xml.html

また、弊社のReflex iTextのテンプレートの文法をHTML5にあわせるかどうか考え中なんですが、このテンプレートはXMLが前提なんでどうしたもんかと。
つまり、HTML5のタグを使いたいのだけど、welformedなHTML5であることを知ることができるのか、あるいは、HTMLとしてパースしないといけないのか、という点がはっきりしないのです。

このあたりで何かわかる方がいれば、ご意見を伺いたいのですが。

よろしくお願いします。


回答1


Y氏)
XML宣言が必要であることと、名前空間がこれまでのXHTMLと別になることの関連、またそれが「完全なシリアライゼーションにならない」にどう繋がるのかがよく分からないのですが、そこは置いといて。

HTML5で言うところの「XHTML」は、「well-formedなHTML5文書を、application/xhtml+xml または
application/xml で送出したもの」になります。
これが text/html で送出されている場合、それはXHTML5ではなく、HTML5になります。
「どう書いたか」ではなく「どう扱うのか」によって、HTMLとXHTMLという区別がつけられるわけです。

> また、弊社のReflex iTextのテンプレートの文法をHTML5にあわせるかどうか考え中なんですが、このテンプレートはXMLが前提なんでどうしたもんかと。
> つまり、HTML5のタグを使いたいのだけど、welformedなHTML5であることを知ることができるのか、あるいは、HTMLとしてパースしないといけ ないのか、という点がはっきりしないのです。

XMLのどの機能を利用しているかによって答えが変わるのですが、たとえば「
」のように空要素のXML的表現は、HTML構文でも利用できるように定義されています。

=====
私)

早速のご回答、ありがとうございます。

>具体的に何が利用できないか、教えていただけますか?
などは、XHTML1.0や1.1では使えないと思います。
使うためには別の名前空間が必要ですよね。

> HTML5で言うところの「XHTML」は、「well-formedなHTML5文書を、application/xhtml+xml または
> application/xml で送出したもの」になります。
> これが text/html で送出されている場合、それはXHTML5ではなく、HTML5になります。
> 「どう書いたか」ではなく「どう扱うのか」によって、HTMLとXHTMLという区別がつけられるわけです。
なるほど。たとえ中身がXMLであっても、「どう扱うのか」ということを、content-typeで区別しましょう、という話ですね。わかります。
では、application/xml
で送り出したXHTML5とは具体的には何になるのでしょうか。welformedなHTML5なのか、XHTML1.1なのか、あるいは、両方が可能なのか。それが知りたいのです。

それにこだわっているのは、要は、XMLパーサしかもっていない当方の実装上の都合だけなんですが、HTML5互換のXMLが扱えるか、もし、application/xmlで送り出すことで、welformedなHTML5を縛れるとすれば、簡単に目的を果たせて嬉しいんです。
=======
S氏)

ちょうど仕様を読み返しているところでしたので、ご質問を受けて、XHTMLに関して言及しているところも軽く読み直してみました。
正しく理解できているかどうかはわかりませんが・・・(^^;
もし間違いがあったら、皆さんご指摘お願いします。

で、ご質問の意図は以下のようなものかと捉えたのですが、いかがでしょうか?

1. ファイル形式がXHTML5か、XHTML1.xかを見分ける手段がないように思えるが、その通りか?
2. 名前空間がXHTML1.xと同じく「http://www.w3.org/1999/xhtml」のままでは、HTML5のボキャブラリを扱えないのではないか?

こういった意図のご質問だと仮定して、僕の意見を述べさせて頂きますと、

1に関してはその通りだと思います。名前空間も同じですし、配信時のContent-Typeも特殊なものではありませんし。

2に関しては、ボキャブラリを扱えるかどうかは実行系に依存するのではないでしょうか。XHTML1.0しか扱えないブラウザは新要素を取り扱えないでしょうし、今後出てくる新しいブラウザはそれらを扱えるようになる、と。

なので、僕はXHTML5というのは、竹嵜さんのおっしゃった

> 単純に、HTML5のままで、welformedなものをXHTML5と呼ぶ

と言うことで良いのかな、と思っています。
(もちろん、文字エンコーディングの指定方法とか、細かい部分は違うにせよ)

ちなみに、仕様(http://www.w3.org/TR/html5/introduction.html#relationship-to-xhtml-1.x)では

"This specification is intended to replace XHTML 1.0 as the normative
definition of the XML serialization of the HTML vocabulary"

意訳:この仕様(HTML5)は、HTMLボキャブラリをXMLシリアライゼーションするための標準定義である、XHTML 1.0の置き換えとして意図されている

と述べられてます。

その上で、
> また、弊社のReflex iTextのテンプレートの文法をHTML5にあわせるかどうか考え中なんですが、このテンプレートはXMLが前提なんでどうしたもんかと。

ちょっと、この部分の問題意識がとらえきれていないので、役に立つ意見になっているかどうかはわかりませんが・・・
何かの参考になれば幸いです。

=====
私)
質問の意図をまとめていただきありがとうございます。まったくそのとおりです。
ご回答内容で、だいぶ見えてきたのですが、新たな疑問もうかんでいます。将来的に、XHTML5の名前空間って何になるのだろう?、と。

>> 単純に、HTML5のままで、welformedなものをXHTML5と呼ぶ
> と言うことで良いのかな、と思っています。

> 2. 名前空間がXHTML1.xと同じく「http://www.w3.org/1999/xhtml」のままでは、HTML5のボキャブラリを扱えないのではないか?
>ボキャブラリを扱えるかどうかは実行系に依存するのではないでしょうか。

ということは、XHTML5は実質的に当面はXHTML1.xと同じ名前空間を使うということになりますね。XMLで新たなボキャブラリを追加する際に、名前空間を変えるべきかどうかは設計者によるといわれていますが、HTML5の要素が加わったXHTMLと、これまでのものとを区別できないのは、やはり不便な感があります。ああ、モヤモヤ。

http://www.ibm.com/developerworks/jp/xml/library/x-namcar/

「最終的には、XHTML 1.0のすべての範囲に1つの名前空間を使用する新たな仕様を発行することで、XHTMLワーキング・グループは軌道修正を行ないました。この教訓から多くを学ぶべきです。命名された物の間に本当に違いがある場合にのみ、XML名前空間を区別すべきでしょう。

残念ながら、物事に白黒をはっきりと付けられることは滅多にありません。新しいバージョンのボキャブラリが、新たな要素を追加するのはよくあることです。前のバージョンから持ち越された要素の意味は変更されていないかも知れないので、名前空間の変更は不適切であると思うかも知れません。しかし仮に、元の同じ名前空間を使用するとしたならば、新たなボキャブラリに追加された要素を元の名前空間内に設置するのも不適切であると思うでしょう。また、新たな要素のみに違う名前空間を使用するのは、とても賢明な選択とは言えません。結局、ボキャブラリで名前空間を改変するかどうかを判断する(自分自身の)判断力が必要です。」


回答2
N氏)

> 名前空間がXHTML1.xのままだとHTML5のタグを使えないものがあるので、完全なシリアライゼーションはできないと私は思います。
> また、弊社のReflex iTextのテンプレートの文法をHTML5にあわせるかどうか

誤解です。

おそらく、XMLの「名前空間」というのは要素のコレクションとその意味を規定するものである、とお考えなのではないでしょうか。

「XML名前空間の簡単な説明」で説明されているのですが、
http://www.kanzaki.com/docs/sw/names.html
実際には、「要素の分類・同定」以上の機能はありません。

そして、XHTML 1.xの http://www.w3.org/1999/xhtml という名前空間は、
「XHTML 1.xが主に使ってきた名前空間」であるだけで、
「XHTML 1.x だけの名前空間」ではありません。
実際、そのURLを開いてみると、いくつか規格がリストアップされています。

で、この中にHTML5が加わることが何を意味するかというと、例えば、
「XHTML1.0のp要素と、HTML5のp要素が、XMLとして同じ意味を持つ」
ということになります。
また、ご指摘のXHTML1.0になくて、HTML5にはあるsection要素等ですと、
名前空間を考えるまでもなく、XHTML1.0にはないので、ここでは問題ありません。

XHTML 2.0の場合は、XHTML 1.0から要素の意味を変更しようとしました。
その場合は同じ名前空間にあると区別ができないので、別の空間を用意することになります。
つまり、XHTML 1.0のp要素と、XHTML 2.0のp要素は別物、ということになります。

XMLだとちょっと考えづらくなってしまいますが、
CのAPIを想像するとわかりやすいのではないでしょうか。

XHTML 1.0にxhtml_foo(int a)という関数がありました。
XHTML 5.0では互換性を保つように作ったので名前はそのままにしました。
XHTML 2.0では引数aをlong型に変えました。
これをそのまま既存のライブラリと強引にリンクさせようとすると落っこちます。
なので、xhtml2_foo(long a)という名前に変えるわけです。

そんなわけなので、
> HTML5のボキャブラリをXHTML1.xに追加するという明確な定義ってありますかね?
「追加」する必要はありません、そのような機能は名前空間は持っていないんですよ。

> 考え中なんですが、このテンプレートはXMLが前提なんでどうしたもんかと。
> つまり、HTML5のタグを使いたいのだけど、welformedなHTML5であることを知ることができるのか、
> あるいは、HTMLとしてパースしないといけないのか、という点がはっきりしないのです。

これはConformance Requestにあるんですが、
http://dev.w3.org/html5/spec/Overview.html#conformance-requirements
XHTML syntaxのみという選択肢があります。
なので「XHTML syntaxしかサポートしない」と言ってしまえばそれでおしまいです。
HTML syntaxの文書はtext/htmlで送られることになっていますから、
これは非サポート、ということですね。
text/html以外は全てXHTML syntaxです。

さて、懸案のXHTML 1.xとの区別ですが、区別する必要はありません。
全てHTML5として処理してください、名前空間が同じというのはそういうことです。
もしもこれで問題が生じるならばそれはHTML5のバグですから、報告なさるのがよろしいかと思います。
=========
私)
ご丁寧なご指摘ありがとうございます。

>> 名前空間がXHTML1.xのままだとHTML5のタグを使えないものがあるので、完全なシリアライゼーションはできないと私は思います。

これはたしかに誤解ですね。XHTML1.x上位互換のXHTML5が定義されていて、名前空間がhttp://www.w3.org/1999/xhtml
であるという考え方をすれば、シリアライゼーションは可能だと思います。ただ、AtomにしてもRSSにしても、大きなバージョン変化があった際には、名前空間も変わるのが一般的だと思うので、下位互換性という理由があるにせよ、名前空間とはそういうものですというのは言いすぎのような気もしています。機能的な議論はあるのですが、実際の運用のところは、先ほどのメールの添付(http://www.ibm.com/developerworks/jp/xml/library/x-namcar/)のように、ケースに応じていろいろなんだと思います。
また、先ほどのメールにも書きましたが、そもそもXHTML5の定義って何なの?という根本的なところが私のなかで曖昧のまま残っていて、ドキュメントのなかにXHTML1.x以上の定義が見つけられなかったので、それ以上も以下もないという発想が元になったのも事実です。
新しいボキャブラリを含むXHTML5を定義したうえで同じ名前空間を使うのか、単なるXHTML1.1なのか、そこが知りたいポイントなのですが、まだしっくりきていません。

>そんなわけなので、
>> HTML5のボキャブラリをXHTML1.xに追加するという明確な定義ってありますかね?
>「追加」する必要はありません、そのような機能は名前空間は持っていないんですよ。

これは、名前空間の機能というより、XHTML5の定義というふうに解釈していただきたいですね。繰り返し恐縮ですが、XHTML5は、HTML5のボキャブラリをXHTML1.xに追加するような定義になっていますかね。(名前空間の話はもう忘れてください。純粋な定義の確認です。)
もしそうだとしたら、ドキュメントの具体的な箇所を教えていただけないでしょうか。白石さんからいただいた参照を見て、私もそうなんだろうなとは思っていますが、念のため。

>ちなみに、仕様(http://www.w3.org/TR/html5/introduction.html#relationship-to-xhtml-1.x)では

>"This specification is intended to replace XHTML 1.0 as the normative
>definition of the XML serialization of the HTML vocabulary"

>意訳:この仕様(HTML5)は、HTMLボキャブラリをXMLシリアライゼーションするための標準定義で>ある、XHTML 1.0の置き換えとして意図されている

>と述べられてます。
=======
> >> 名前空間がXHTML1.xのままだとHTML5のタグを使えないものがあるので、完全なシリアライゼーションはできないと私は思います。
>
> これはたしかに誤解ですね。XHTML1.x上位互換のXHTML5が定義されていて、名前空間がhttp://www.w3.org/1999/xhtml
> であるという考え方をすれば、シリアライゼーションは可能だと思います。

> ただ、AtomにしてもRSSにしても、大きなバージョン変化があった際には、

これらはHTMLとは事情が違うように思います。
RSSは0.9, 0.91, 1.0, 2.0, 0.92 全て互換性がありませんでした。
なので、名前空間が異なるのは当然でしょう。

Atomも上記のRSS達とは違うので名前空間が異なるのは必然です。
また、Atom 0.3 から 1.0 へもdraftから正式版への変更なので、変えるのは当然でしょう。
が、Atomの改定版が出た時にはHTML5と同じ悩みを持つことになるでしょう。
Atomの事情はよく知らないので想像になりますが、Atomは関連規格が多く、
それらの多くがAtomのnamespaceを指定している以上、変えられないのではないかとは想像しています。

> 下位互換性という理由があるにせよ、名前空間とはそういうものですというのは言いすぎのような気もしています。

下位互換性は名前空間を同じにするかどうか考える際の材料の一つになりますが、
実際にXMLの名前空間を見るときには考慮されません。

XMLの名前空間が持っているのは、
* 名前空間が同じ→同じ名前の要素は同じもの
* 名前空間が違う→全ての要素は全くの別物
ということだけだということです。
そして、ここで同じものならばXMLのレイヤーにおいては区別する手段を持たないということです。
(もちろんversion属性を追加してそこでもっと上のレイヤーで区別することは可能ですが)

これをふまえたうえで、名前空間を同じにするか別にするかは仕様策定者に委ねられているわけです。

> 機能的な議論はあるのですが、実際の運用のところは、先ほどのメールの添付
> (http://www.ibm.com/developerworks/jp/xml/library/x-namcar/)
> のように、ケースに応じていろいろなんだと思います。

うーん、ちょっとこの記事、もっといえば特に
> XHTMLワーキング・グループは、それぞれのXHTML DTDに対応する3つの別々の名前空間を
> 使用することを決定しました
のXHTML WGの人々はちょっと神経質すぎるように感じます。

名前空間はXMLのレイヤーにおいて同じ名前の要素を別物扱いさせる、ただそれだけの効果しかありません。
もっと具体的にいえば、XMLパーサが同じ名前の要素なのに別物扱いしてしまう、という意味になります。
XMLの上に構築された多くの仕様では、ここで別物扱いされると上のレイヤーで同一視することはなかなか困難な作業になります。

実際にその仕様が勧告され、その仕様に沿った文書が、過去の当該仕様に沿った文書や他の関連仕様とそれに沿った文書、
その仕様に沿ったアプリケーションや過去の仕様、関連仕様に沿ったアプリケーション、などなど、と協調して動こうという時にどう振舞ってほしいかを考えれば、おのずと答えは見えてくるのではないでしょうか。

Atomの方が例としてシンプルなのでこちらで話しますと、例えばAtom 2.0で名前区間を変えたとすると、既存のアプリケーションや関連仕様は全てバージョンアップしない限りAtom 2.0の文書を無視するわけです。
この壁を乗り越えるにはよっぽど派手な花火がないと難しいように思えます。

> また、先ほどのメールにも書きましたが、そもそもXHTML5の定義って何なの?という根本的なところが私のなかで曖昧のまま残っていて、

HTML5は今までのようにタグの寄り集まった文法ではなく、DOM (Document Object Model) で定義されています。
つまり、ある構造をもった文書を、ブラウザやその他のアプリケーションがどう表示・処理するかと、
そのの構造の文書どうシリアライズ―ありていにいえば文字列にダンプするかを定めているわけです。
で、ダンプの仕方はHTML syntaxとXHTML syntaxがある。
この点において、「HTML5」とは言いつつも、今までのSGMLの子孫であったHTMLやXML一族のXHTMLとは一線を画しています。

> ドキュメントのなかにXHTML1.x以上の定義が見つけられなかったので、
> それ以上も以下もないという発想が元になったのも事実です。

仕様上は以上でも以下でもありませんね。
同じ名前空間の中にいる兄弟と言ったところでしょうか。
で、たまたま(実際はもちろん意図的なんですが) (X)HTML5 は XHTML 1.x の要素集合をおおむね包含しているだけです。

> 新しいボキャブラリを含むXHTML5を定義したうえで同じ名前空間を使うのか、

「新しいボキャブラリ」をここでどのような意味で使っているのかが問題ではありますが、
推測するに、この認識が正解であるように思います。
で、
Q: 別物のはずなのになぜ同じ空間を用いるの?
A: 互換性のため
Q: 互換性のためなら同じ空間を使ってもいいの?
A: よい、だって別にしたからXHTML 2 は死んじゃったんだもの
Q: 同じ空間だと何か問題が起きるんじゃない?
A: 何も問題が起きないように頑張る
と、こうなるわけです。

どうも HTML 5 WG はそれなりに迷った末に同じ空間を用いることを決定したようですが、
現状の膨大なHTML/XHTMLの資産や、HTML5以前に行われた数々の試みがどうなったかを考えると、同じ空間をもちいるか、黙殺されるか、の二択でしかなかったと思います。

> 単なるXHTML1.1なのか、そこが知りたいポイントなのですが、まだしっくりきていません。

XHTML 1.1 は DOCTYPE 等一定の要件を定義していますが、XHTML5 はそれから外れています。
よって、XHTML5 は XHTML 1.1 ではありません。

> >そんなわけなので、
> >> HTML5のボキャブラリをXHTML1.xに追加するという明確な定義ってありますかね?
> >「追加」する必要はありません、そのような機能は名前空間は持っていないんですよ。
>
> これは、名前空間の機能というより、XHTML5の定義というふうに解釈していただきたいですね。繰り返し恐縮ですが、XHTML5は、HTML5のボキャブラリをXHTML1.xに追加するような定義になっていますかね。(名前空間の話はもう忘れてください。純粋な定義の確認です。)

XHTML 1.x と XHTML 5 は別の規格ですね。
XHTML 5 に沿ったアプリケーションが XHTML 1.1 の文書を解釈できるのは「たまたま」です。
もちろん、その「たまたま」を実現するために、名前空間を同じにするだけでなく、
各種の注釈で既存UAの動作を解説したりと、HTML 5 の策定者達が努力していることは言うまでもありません。
(もちろん、XML的には同じ名前空間の同じ要素を扱っているのだから互換性が期待されるわけですが)

=======
1.7 HTML vs XHTML
http://dev.w3.org/html5/spec/Overview.html#html-vs-xhtml
が直接の参照先かと思います.正確にはDOMもrepresentationの一つです.

また,根底部分の知識として,Architecture of the World Wide Webも一読の価値があるかと思います.
http://www.w3.org/TR/webarch/

======
> 1.7 HTML vs XHTML
> http://dev.w3.org/html5/spec/Overview.html#html-vs-xhtml
> が直接の参照先かと思います.

HTML syntax と XHTML syntax が the DOM に対して用意されている、というのはそこですね。

2.2.1 Dependencies
「The DOM is not just an API; the conformance criteria of HTML
implementations are defined, in this specification, in terms of
operations on the DOM.」
http://www.whatwg.org/specs/web-apps/current-work/#dependencies
で、「DOMで定義されている」というのはこの辺の話です。


月曜日, 8月 24, 2009

【Google App Engine】 Entityとトランザクション3 このエントリーを含むはてなブックマーク


 Scaleするかどうか、それが問題だで主張したとおり、クラウドではスケールしなければ意味がない。以下は、GAEで大規模な処理をやって、特にトランザクション処理で悪戦苦闘した際のメモである。本日の発表資料=>ココにも含まれている。

大量データをINSERTできない件について

 先日、Entityとトランザクション2において、Ownedな関連を使ったUpdateサンプルを紹介したわけだが、実はこれ、大量データをINSERTすると急激に遅くなるという問題を含んでいることがわかった。実際にテストしてみたところ、15000件を超えた時点でタイムアウトが頻発、15300件からはとうとう1件も登録できなくなってしまった。

com.google.apphosting.runtime.HardDeadlineExceededError: This request (c1fe232d20adabba) started at 2009/08/11 07:12:31.975 UTC and was still executing at 2009/08/11 07:13:05.802 UTC.


 原因としては、1)インデックス作成における負荷、2)所有関係を作成する負荷、が考えられるが、3)JDOのトランザクション処理自体に問題がある可能性もあるので、その場合はLow Level APIの利用も視野に入れなければならないと考えた。

トランザクション処理の必要性

 トランザクション処理でここまで嵌ってしまうと、ACIDじゃなくて別のよい方法はないものかという考えに傾いていく。最近よくBASEという考え方が紹介されていて、ACIDが大変なんで、BASEでいいんじゃないかと思うこともある。あるいは、エラー忘却型コンピューティングとか、BASEの1種になるかもしれないが、Saga(ロングトランザクション)モデルといった補正トランザクションなどを利用しようという考え方もある。Sagaは、Webサービスが密に結合しているようなシステムにおいて過去多く見られた。最近のRESTfulなシステムへの導入では、ステートレスになじまないことでやや否定的だが、やろうと思えば可能だろう。(参考:RESTとトランザクション?
 しかし、ロングトランザクションなどのACIDではない仕組みに関しては、補正失敗のケースも考慮しておかないと運用面で支障をきたすことになるので要注意である。
 私は以前作ったWebサービス連携のエラーリカバリーで酷い目にあった経験があるので、この手のものをACIDで組まないことに、ものすごく悲観的である。ACIDによる一貫性保証がないカウンタの実装などは特に嵌る。そして、すぐに不具合を見つけることができないことが問題を大きくする。単体テストでは成功して、本番運用に入っても数日は成功するので一見うまくいくように思うかもしれないが、失敗の失敗、つまり、リカバリーの失敗までを考慮していないと、破綻は必ず訪れることになる。(マーフィーの法則「起きる可能性のあるものは必ず起きる」)(関連:信頼性とジレンマ

調査結果および対応策

 話は戻り、パフォーマンス劣化の原因について調べてみた。そして、なんとかACIDでやる方法はないものか、もう一度考えることにした。

一度に100件登録した場合

<所有関係の負荷>
  * 所有関係あり: 15秒くらいから。件数が増えるとだんだん遅くなる。
  * 非所有: 3秒くらい。件数が増えても変わらない。

<Index作成の負荷>
  * インデックスなしと、インデックスありの、どちらも100件登録で3秒くらい。
  * インデックスありのテーブルで、100000件弱登録できた。
  * 登録にかかる時間も100件約3秒と変わりなし。


 以上の結果のとおり、Indexの数というより、所有関係の方がパフォーマンスへの影響が大きいということがわかった。所有関係については、それを解消しなければ、ほとんど使い物にならないような感じであった。

所有関係とEntityGroupについて

 実はEntityGroupと関連に直接的な関係はない。そもそも親子関係をしているのは、JDOのowned関係がEntityGroupとみなされることを利用してトランザクションを実行したいからであった。しかし、そうしなくても、明示的なKeyの生成、つまり、子のキーを親のエンティティのキーを使って生成することでEntityGroupは作成できるのだ。パフォーマンスを出すには、Owendな関連を解除して、Keyの親子関係で関連付けたEntityGroupを使って、トランザクションを実行すればよいことがわかった。



以上の結果を踏まえてコードを修正した。




金曜日, 8月 21, 2009

【Google App Engine】 大量のPDFを生成してわかったGAEの真の実力 このエントリーを含むはてなブックマーク


クラウドPDFサービスのパフォーマンス測定について

 先日公開したScalable PDFのパフォーマンステストと同様に、クラウドPDFサービス(GAEのReflex iTextサービス)についてもパフォーマンステストを行ったので公開したいと思う。
 クラウドPDFサービスは、AmazonEC2のかわりにGAEを使っており、負荷分散機能はGAEまかせとなるが、Reflex iTextのサービスを使っている点はScalable PDFサービスと同じである。ただ、GAEの場合は実行時間など、いろいろな制約があり、リクエストが失敗する前提で設計しなければならないといった考慮が必要となる。今回のテストにおいては、エラー時に時間間隔を置いてリトライする仕組みを取り入れている。
 結果としては、以下のように、GAEでも約8千ページを4~5分で処理できたということで、まずまずであったのだが、これがいっぱいいっぱいであったことも事実であった。1リクエストが80ページ生成で30秒かかることを考えると、少なくとも数十のアプリケーションが並列処理していたのではないかと思われる。(1アプリに複数リクエストを与えると30秒以内で返せなくなりタイムアウトエラーになるため、成功リクエストのほとんどが単独で処理されていたと考えられる)しかし、さらに多くのリクエストを処理させたい場合には、アプリケーションを分けるなどの工夫が必要となってくるだろう。ただ、一回目より二回目の方が明らかにエラー件数が減ったため、徐々にリクエストを増やしていくのであれば、そのままでもスケールしていくかもしれないという期待はある。
 ちなみに、EC2を使って作成する場合には、8000ページを約1分で処理できるが、400プロバイダ/20インスタンス(c1.xlarge)の起動が必要となる。また、レイテンシーの問題があるので実際の処理時間は2~3分といったところだと思われる。
 c1.xlargeは、Opeteron 1.0-1.2GHz相当*20Unitで7GB Memあり、Celelon2.2Ghz、512MBのマシンの10倍程度の処理能力が確認されたが、GAEの場合はCelelonの2~3倍、c1.xlargeの1/4程度の能力であった。

 * エラーがあれば時間間隔を置いてリトライする仕組み(時間間隔=100msec*リトライ回数*10msec)
 * 1リクエストで生成できるページ数の限界は80ページ(処理時間は30秒でこれ以上はタイムアウト)
 * リクエストを100並列で実行するとエラー数が膨大となった(失敗)
 * リクエストを1回目より減らして95並列で実行すると4~5分かかった(成功だがリトライが多いもので8~10回程度発生した)
 * 一回目より二回目の方が明らかにエラーの数は減っている(GAE側でスケールしている?)
 



クラウドPDFサービスとScalablePDFサービスのすみわけ

 クラウドPDFサービスは、当初は、Morph AppSpaceで動作する無償のサービスとして発表したが、GAE上で動作する現在においては、Googleサービスの特長である、素早いレスポンス、自動的にスケールする機能といったものが追加されて素晴らしく進化した。一方、EC2を動作環境とするScalablePDFサービスでは、AutoScale機能+自前の負荷分散プログラムによってクラスタリングを行い、スケーラビリティを実現しているが、複雑になってしまった分、管理コストが重くなってきている。
 これら2つのサービスは現時点において機能的に大きな差はない。強いて言えば、スケーラビリティに関してEC2の方が瞬間的に大きなトラフィックが発生した場合に対応しやすいということぐらいである。ただし、EC2にはレイテンシーの問題が依然として存在している。
 したがって、リトライ処理などを含めた時間的なばらつきや応答時間が許容範囲であれば、現時点でのおすすめは、当然、GAEによるクラウドPDFサービスである。どうしても厳密な応答時間が要求されるのであれば、ScalablePDFサービスをおすすめすることになる。
 利用料は、クラウドPDFサービスは大企業だろうと個人だろうと月額固定の3000円であるが、ScalablePDFサービスは月額数万円程度とさせていただいている。運用管理コストが料金の差となって反映されていると考えていただければと思う。

木曜日, 8月 20, 2009

【おしらせ】 8/24次世代Web活用部会でGAEについて話します このエントリーを含むはてなブックマーク


第2回XMLコンソーシアム 次世代Web活用部会にて、『GAE使いこなしのディープな世界』というテーマで話します。単なるアプリの作り方ではなく、大量データ処理を実際にやってみて、うまくいったこと、いかなかったことを中心に、実践的な内容を話す予定です。

 * 大量のPDFを生成してわかったGAEの真の実力(Scalability、パフォーマンス)
 * 大規模データを問題なく処理するためのテクニック(トランザクション、EntityGroupとRelationなど)

【Reflex】 JSONにおける属性表現、List表現 このエントリーを含むはてなブックマーク


JSONにおけるXMLの属性表現

 JSONではXMLの属性といったものを表現できないため、これまでReflex JSONでも属性を無視していたのだが、AtomをJSON化したくて、Link要素の属性を扱う必要が出てきたので、Reflexでもムリクリ表現できるようにしてみた。Reflex Core に詳細を記述してあるが、V1.2.1から使えるようになっている。(同時に要素名のハイフン変換もサポートした)


* JSONでは、要素名の"-"が"__"に変換されるため"type_str-ing"は、"type_str__ing"となります。
* また、XMLの属性は、JSONでは"要素名___属性名"プロパティとなり、"attr1"は、JSONでは"type_str__ing___attr1"プロパティとして表現されます。


ListをJSONに変換する

 JavaのListをJSONに変換する際に、両者の関係だけにとらわれてしまうと、なかなか思うように作れないので、一旦、JSONとListのことは忘れて、XMLに変換するイメージをもちながら構造化していくといった方法で設計するのがよいと思われる。以下にQ/Aの抜粋を添付する。


List をJSON に変換するのは基本的に構造化が必要です。
以下のサンプルがわかりやすいかと思います。
http://reflex.sourceforge.jp/reflexitextsample_function4.html

EntityはStockInfo.javaで、StockList.javaで値を詰めています。
構造化をイメージしやすいのはstocklist.xmlですが、stocklist.jsonも同じentityから生成したものですので、同じ構造をしているといえます。

Reflexでは構造を意識しないといけない仕様になっていますので慣れるまでちょっと不便ですが、そういうものと思っていただくしかないでしょうね。

ただ、JSONの配列の便利さも損ないたくないので、以下のサンプルのような、配列の要素数
を与えてムリクリ変換できるような方法も用意しています。

http://reflex.sourceforge.jp/reflexjsonsample.html




日曜日, 8月 16, 2009

【Reflex iText】 Publicクラウドはサブスクリプションモデルがいい このエントリーを含むはてなブックマーク



publicクラウドのビジネスモデルは「XX放題」

 Reflex iTextは、先日、月額3000円で利用できるサービスとして発表させてもらった。Reflex iText


Morph AppSpaceやGoogle App Engineなどのクラウドサービスにデプロイして使用する場合は、1インスタンスにつき1ライセンス料が発生します。1ライセンスはトランザクションの量に関係なく固定で月額¥3,000となります。warファイルの提供はありません。基本的に弊社にて導入支援を行います。サービスレベルはMorph AppSpaceやGoogle App Engineに依存します。また、利用料は別途お客様負担となります。


 Reflex iTextがこのような定額の利用料を徴収するサブスクリプションモデルとしたのは次のような理由による。

 7/23に開催された、アカマイ・カスタマ・カンファレンスの「ビジネスを伸ばす次世代Webとは何か?」というパネルディスカッションで知ったのだが、アテインさんの動学.tvという教育サービスは月額2800円で受講し放題である。これが割と繁盛されていて、現在も会員さんをどんどん増やしているらしい。月額固定で借り放題といえば、TSUTAYAのDISCASなんてのがあるが、これとよく似たサービスだ。モデレータの佐々木さんは、次世代Webのビジネスモデルは、サブスクリプションモデルと広告モデルが中心になるだろうとおっしゃっていたが、たしかに、月額定額利用料で「XXし放題」というのはとても魅力的なモデルである。これまでクラウドもユーティリティーコンピューティングというキーワードで電気やガスのように利用するモデルが吹聴されてきたが、要するに、サブスクリプションモデルのことである。どんなに使われても非常に安く提供できるクラウドがあればこそサブスクリプションモデルも生きる。

受託開発でGAEを利用することは可能か


 publicクラウドは、大企業から請負で開発するというビジネスモデルより、コンシューマをターゲットに小売的な商売を行って、使ってもらってナンボといった感じのビジネスモデル方が合うような気がしている。クラウドが請負になじまないのは、最大の壁であるセキュリティ問題があるからだ。セキュリティは最後の難問題でも触れているが、クラウドでセキュリティを確保することは一筋縄ではいかない。メーリングリストで以下のような議論が行われていたので、SLAと担保の2つをどう解決するかという自分なりの意見を述べてみた。


受託開発でGAEを利用することは規約的に可能でしょうか?
またデメリットとしてどのようなことが考えられるのでしょうか?


>情報漏えいやシステムダウンは、どんなに注意を払っていてもおきるときはおきます。

私もそう思います。
ただ、実際には、Googleは免責されている(事故が起こっても損害金額などを払ってくれない)ので、発注者側がリスクを負うことになってしまいます。

少ない確率であっても、実際に情報漏えいやシステムダウンが起きる可能性があるため、発注者は導入の際に、事故が起きたときに誰がリスクを負うのかということを、会社に説明できなければなりません。(私も数年前までは発注者側にいたので、少なくとも会社はリスクを負わないということを、役員会などで説明する必要がありました。私に限らず皆そうなんだと思います)

その点、アウトソーサが管理しているシステムであれば、サービスレベルの質はどうであれ、彼ら自身が担保してくれている(個人情報漏洩であればほぼ無限責任)ので、発注者側はとても楽です。ただ、この形態は、ものすごく高くつくので、本当に会社の利益になっているかどうかは、経営者自身がよく考える必要があると思っています。Googleのシステムだからとか、彼らは優秀だからといった形容詞を使ってリスクをいかに少なく示したところで、担当者による説明はとても難しいと思いますので、結局は経営者判断になるんじゃないかと。

最近、私は逆の立場になり、GAEを提案しています。

お客様の意見としては、安さが会社の競争力になるという評価をしていただいている一方で、やはり、セキュリティの課題をクリアーできずに導入できないというところが多いようです。
また、抵抗を示している多くがIT部門なのもおもしろいと感じています。彼らは、個人的には導入にものすごく意欲的なんですけど、大企業だと会社ルールの壁を突破できないというか、政治的に動く必要があって、それがなかなかできないみたいです。事例もない現時点では無理もないことだとも思います。

結局のところ、大企業に浸透するまでには時間がかかりそうだから、中小企業か個人をターゲットに数多くのユーザを獲得する以外なさそうかな、と私は感じています。コンシューマをターゲットに小売的な商売を行って、請負でいくらというより、使ってもらってナンボといった感じの方が合うような気がしています。


水曜日, 8月 12, 2009

【雑記】 イケメンとチョイワルの喧嘩 このエントリーを含むはてなブックマーク


 今回の喧嘩ネタはちょっとレベルが高い。(見方によっては低い)

 福岡の夜 (shi3zさんとの喧嘩)
 そりゃブログを書くだけで平和が来るなんて甘い夢など見ちゃいねえさ

 リーダシップを論じるお二人の主張が異なるのはさておき、shi3zさんがid:mkusunokさんに最も伝えたかったことは「ブログの無力さ」であり、1個人がブログに書くということが、いかに微々たる力であるかを認識すべきであるということだった。それを、「お前みたいなクズのような存在」と相手に直接いうことでわからせようとした。(たぶん、この表現自体に問題があると思われるが、ストレートに表現することを信条としているshi3zさんにとっては普通のことらしい)

 一方、普段からshi3zの言動が気になっていた小野さんはこれにブチキレ。以前、「嘘を平気でつける人間」であり、それ故に「欺瞞に満ちた人間」であると言われていることもあって、「お前はいままで、いったい何をしたんだ。何もしてないクズだろ」となった。

 shi3zさんは本当のことを伝えることが「善」であり「手段」を選ばないこともある。一方の小野さんは「手段」を選ばないと損するよ、と伝えたい。

 どちらも正しいことをしているように思えるが、ぜんぜん会話になっていない。コミュニケーションを阻んでいる原因は「妬み」と「欺瞞」なのだろう。面白いのは、自分は妬んでいるといっているshi3zさんがいる一方で、自分は欺瞞であるとはいえない小野さんがいること。

 また、今回の件で相当な決意とやる気をだしたshi3zさんの未来は明るいかもと思った次第。

木曜日, 8月 06, 2009

【Google App Engine】 Entityとトランザクション2 このエントリーを含むはてなブックマーク


 今回は親子関係をもったEntityのUpdateを中心に解説する。例によって、請求書アプリを題材にしている。ソースは=>ココで、使用しているReflexGaeライブラリは=>ココ

親子関係をもつEntityのUpdate

 請求書アプリでは、請求書1枚がEntity1インスタンスとなるように設計されている。1つの請求書(Invoice)が複数の明細レコード(Order)をもち、さらには、Invoiceを親であるInvoiceBaseがListとして複数保持している。また、InvoiceBaseはInvoiceのレコード数、および、Orderのレコード数も保持している。このような関係をownedというが、このような構造をしているのは、EntityGroupとして定義しているからで、1トランザクションで実行する必要があるからである。
 これらを更新するには、下図のように、まず、クライアントから受け取ったJSONのInvoiceをオブジェクトに変換したものとDatastoreとの差分を取り、その差分を反映させたオブジェクトをあらためてPersistentにすればよい。



DatastoreをUpdateする際の注意点


* 更新でmakePersistentは必要なし

 Datastoreから取得したオブジェクトはPersistentな状態である。Persistentな状態とは、Datastoreへのアクセサを保持している状態で、setterを使って値をセットするだけで、(makePersistentを呼び出さなくても)永続化されることになる。
 また、所有関係にあるオブジェクトがデータストアに保存されると、そのオブジェクトと関係があるすべてのオブジェクトの内、保存する必要のあるもの(新しいオブジェクト、または最後に読み込まれてから変更されたもの)は自動的に保存される。つまり、Persistentなオブジェクトにaddすることで、親のオブジェクトは子を含めてPersistentになる。

* lazyな読み込み

Datastoreから取得したオブジェクトの子は eager loadされない(アクセサを使って参照したときのみ値を取得できる)ので、別途、子を取得して親にセットする必要がある。

 * propertyの更新は1トランザクションで1回のみ許される

2回以上更新すると、「can't update the same entity twice in a transaction or operation」というエラーが起きる。

* オブジェクトの親子関係とKind(≒Table)の親子関係に関係はない

親オブジェクトに子をaddしたからといってKindの親子関係になるわけではない。Kindの親子関係を紐付けるのはKeyであり、子のKeyに親のKeyをAddすることで関係付けることができる。Keyを明示的にセットしない場合(nullの場合)はシステムが勝手にKeyをセットする。

サンプルプログラム

 
 以下のように動作するサンプルプログラムを示す。
1.でそれぞれ取得しているのは、InvoiceBaseからInvoiceを直接取り出すのができないから。(forループでまわさないと取れない)また、lazyな読み込みなので、3.の処理が必要となる。
2.でdetachCopyしているのは、Persistentオブジェクトを直接操作するのを避けるため。Persistent直接だと、setterを1回しか呼べないという制約にもひっかかる。


1.InvoiceとInvoiceBaseのPersistentオブジェクトをそれぞれ取得する
2.invoicePersistentから、いったんdetachCopy
3.コピーしたものに子要素のorderを追記補完
4.invoiceからinvoiceSource(1品一葉)を取得する。
5.クライアントからのリクエストデータで更新があったものだけをinvoiceTargetにコピーする
6.Revisionを更新
7.InvoiceBaseにaddすることでInvoice以下子要素のorderなどもpersistentになる





AJAX CRUDサンプルとJDO代替ライブラリ
RESTfulアプリのCRUDサンプル -Modeling編-
RESTfulアプリのCRUDサンプル -Servlet編-
Entityとトランザクション

水曜日, 8月 05, 2009

【iPhone】 AppleのiPhone向けのアプリビジネスはなぜ魅力的ではないか? このエントリーを含むはてなブックマーク


GoogleのAndroid向けのアプリビジネスはなぜ魅力的ではないか?をちょっと書き換えてみた。


Android向けの開発意向表明を行って数ヶ月になるが、もっとも良く投げかけられる質問は「iPhoneへのプラットフォームでは開発しないの?」というものだ。
少し前までは、ObjectiveCの開発スキルやリソースに目処がつけばやってもいいけど、学習コストが重いよねえ、などと答えていたが、最近は少し見方が変わってきた。

今の勢いでHTML5が進化・浸透してくれるのであれば、わざわざ移植コストをかけてiPhoneやWindows Mobile向けにネーティブ・アプリを開発するよりは、少なくともUIの部分をすべてHTML+Javascriptにまかせたアーキテクチャでのインタラクティブなアプリの開発というのも十分に可能性があるように思えてきたのだ。

この「HTML+Javascriptですべて出来るじゃん」という発想は、そもそもマイクロソフト時代のInternet Explorer 4.0やNetDocs(90年代の終わりに開発していたマイクロソフト版Google Docs)のころから持ち合わせて来たもの。パソコン向けではWindowsの成功が故に日の目を見なかった発想が、数多くのプラットフォームが混在・競合しているスマートフォンの時代になって大きな意味を持ってきたというところが興味深い。

 そもそも、「AppleがiPhone」を発表する、と聞いた時には、「ついに超高速・超小型のJavascriptエンジンの開発に成功したか」と過大な期待を抱いてしまった私にとって、ObjectiveCでNativeコードを書かなければならないiPhoneははっきり言って期待はずれの拍子抜け。明らかにGoogleの「ウェブアプリケーション中心」というの基本路線から外れており、せっかくiPhone向けのアプリを作った開発者がAppleに途中ではしごを外されて途方にくれる可能性は大きいと私は見ている。

現時点で、最新のハードウェア向けのアプリを作りたければAndroidがiPhoneよりも魅力的なプラットフォームなことは火を見るよりも明らかだし、どうしても「Googleに縛られたくない」のであれば、標準になりつつある、HTML5上でJavascriptを駆使した本気のインタラクティブなアプリを作るノウハウを蓄積しておく方がよほど魅力的に思える。もちろん、現時点でもっともすぐれたHTML5の実装を持つモバイル端末は iPhoneだし、ちゃんと作っておけば、Android端末でもPalm Preでも動くはずなので、投資効率は高い。

 ということで結論から言ってしまえば、「移植性を無視して最新のハード向けにばりばりのネーティブコードを書きたかったらiPhone向けのアプリを Objective Cで作るか、Android用にJavaで作り、さまざまなデバイスへの移植性が重要ならHTML5+Javascriptでインタラクティブなアプリを作ってiPhone上のSafariでテストしておく」というのが現時点でのスマートフォン向けの開発投資の仕方としては、最も賢い選択肢だと考えている私である。

ちなみに、JavaとかFlashとかはどうなの、という質問が来そうなので答えておくと、「スマートフォン向けではなく、現状の端末向けのアプリの開発であればまだまだJava、BREW、Flash liteは健在。ただし、3〜5年後にそれらのプラットフォームがHTML5によって駆逐されてしまう可能性は大」というのが私の見方。もちろん、「ガラパゴス携帯」とか「Windows Mobile」という局所的な抵抗勢力はそれなりに残るだろうけど、WebKitがモバイル端末でさくさく動くことをAppleが証明してしまった今、世界の流れはHTML5に一気に向かっている。

日曜日, 8月 02, 2009

【Google App Engine】 RESTfulアプリのCRUDサンプル -Modeling編- このエントリーを含むはてなブックマーク


 前回に引き続き、RESTfulアプリの解説をおこなう。今回はModeling編。本当は最初に説明すべきところ。

Entity設計

 外部設計において基本となるのはBCEモデル。3分で分かる設計の話 にもあるように、Entity設計とは項目の整理をすること。項目の抽出は画面設計を行ってからじゃないとできないので、実際には、Boundary=>Entity=>Controlの順番で設計を進めていくことになる。Entityの設計では、基本的には名前と型と多重度の定義を行うだけでよいのだが、もう少しがんばって、具体的にXMLのインスタンス(項目とデータを含むもの)まで作成するとよいと思う。ちなみに、請求書アプリのXMLインスタンスはこんな感じになった=>XML

 ReflexではModel設計のことを敢えてEntity設計と言うようにしている。Modelは型で、Entityはその型から作ったインスタンスであるから、Entityは金太郎飴の一粒のようなもの。Reflexでは、Entityのインスタンスイメージの方が具体的で好都合なので、なるべくそう呼ぶようにしているが、設計フェーズを意識しないときは、Model設計とEntity設計はよく同じ意味で使ったりもするので、実際にはそれほどこだわっているわけでもない。ただ、Modelを強調してしまうと、「Model=抽象的な器+ロジック」のロジック部分が強調されることになって、データ構造を中心に考えるReflexの設計に合わなくなってしまうので、やっぱりEntity設計と呼ぶのがいいような気がしている。
 
Modelの設計とサービス化
 
 Entityの設計ができたら内部設計をすすめてModelを設計していく。Modelには、データ構造を表現する部分と、ロジック(ビジネスロジック、または、ドメインロジック)を表現する部分から成るが、Reflexではこれを2つに分離させることを推奨している。具体的には、データ構造を表現したModelに実際のデータの管理をまかせてCRUDのAPIを持たせることが一つと、ドメインロジックには、専らビジネスロジックの実行処理をまかせるのが二つ目。ビジネスロジックの実行では、例えば、Entityから別のEntityへの変換や、HTMLやPDFなどへの変換、メール送信などが考えられる。前者はDatastoreへの登録があるから不揮発性なのに対し、後者は揮発性であるのが特徴である。ドメインロジック内で許されるのは参照のみで、登録や更新は絶対に許されないとものする。ただし、Datastoreからの参照は可能であり、必ずしもWebサービス経由で参照する必要はない。
 また、Modelのこれら2つの機能をREST化したものをサービスと呼んでいる。例えば、EntityをCRUDで操作するデータ管理用のサービスと、PDF変換などのロジック実行用のサービスなどがある。これらはModelの2つの性質をサービス化したものと考えることができる。

サービスにおけるEntityの扱い方と具体例

 RESTfulな新3層アーキテクチャでも説明しているとおり、すべての操作はパラメータにentityを与えることにより実行する、というポリシーで設計する。こうすることで、entityという一貫したI/Fが扱えるようになり、その結果、外部設計の目的が明確になる。外部設計とは、つまり、entity設計を意味することになる。


 entity = create(entity);
 entity = retrieve(entity);
 entity = update(entity);
 entity = delete(entity);


 請求書アプリで具体的に説明してみよう。まず、create(entity)に対応するのは、invoiceのXMLをPOSTメソッドで実行する部分である。Servlet内部では、reflexgaeライブラリを使ってXMLをrequestオブジェクトから取り出してinvoiceオブジェクトに変換、それを直接datastoreに挿入している。非常にシンプルな実装である。<参考>RESTfulアプリのCRUDサンプル -Servlet編-


 Invoice invoice = (Invoice) getEntity(req, MODEL_PACKAGE);
 jdoUtils.insert(invoice);


 retrieve(entity)に対応するのは、以下の部分で、requestオブジェクトのクエリパラメータの内容を、一旦、Invoice paramに詰めて、それを条件にjdoUtils.getEntriesByParam()で検索を実行している。


 Invoice param = new Invoice();
 (new RequestMapper()).setValue(req, param);
 ・・
 jdoUtils.getEntriesByParam(param, pagesize, nextid);


 update(entity)も基本的に同様であり、PUTされてきたXMLをInvoiceに変換して、jdoUtils.update(invoice)を実行するだけである。delete(entity)も同様である。


 Invoice invoice = (Invoice) getEntity(req, MODEL_PACKAGE);
 JdoUtils jdoUtils = new JdoUtils();
 jdoUtils.update(invoice);


 jdoUtilsの内部では、reflexgaeの FieldMapperを使って、targetのinvoice(persistant)に対して、sourceのinvoiceの更新があるプロパティだけをセットするようにしている。つまり、sourceのinvoiceのプロパティのうち、nullでなく、かつ、targetと異なる内容のものを、setterを介してセットするという処理をfieldMapper内で行っている。わざわざsetterを介すのは、JDOに更新であることを認識させるためである。(フィールドを直接書き換えると更新されないので注意)
 また、invoiceのように、1:nの子要素を持つ場合でも、この操作1回ですべての子要素を更新することができる。ただし、子要素のKeyはしっかりsourceの方にセットしておく必要がある。(私が試したのは2階層までであり、3階層の孫要素も更新されるかどうかはわからないので注意。)


fieldMapper.setValue(invoice,target);


 

Control

 Controlは、簡単に言うとサービスを呼ぶ機能のことである。他のサービスを呼びつつ、一連のフローを実行して、別の新たな結果を返すような機能、といった感じだろうか。いわゆる、マッシュアップがそうだし、先日公開した、Google Spread SheetからPDF生成するBookmarkletもControlの一種である。ドメインロジックをサービス化したものはControlになることができるが、すべてがControlと呼べるかというとそうではない。

Boundary

 いわゆる画面のことである。本当はこれを最初に説明すべきところだが最後になってしまった。ここでいいたいのは一つだけ。レンダリングのために必要な処理はBoundary内に記述すべきということ。EntityをサービスからXMLやJSONで受け取ってレンダリングしたり、あるいは、GEARなどに一時的に保存したり、サービスに登録内容を送信したりする処理は、Boundaryとして実装すべきであり、決してControlなどに押し付けてはいけない。画面内に閉じることで疎結合のメリットを最大限に享受できるようになるからだ。

まとめ

 ここまで、主に外部設計の話とBCEモデルについて説明してきたが、あらためて強調したいのは、Entity設計をクローズアップするということ。つまり、Entityの設計をしっかりやって、それを一貫したI/Fとして扱うべし、ということにつきる。サービスについても、EntityをパラメータとしたCRUDや、Entityを与えてEntityを返すという単純なものにすべきである。そう考えていくと、Entityさえできれば、それをもとに自動的にscaffoldを作成するなんてことは簡単にできる。ちなみに、Reflexでは、reflexentityeditorというものを用意しており、Reflex表現からEntityを自動作成するツールも用意している。将来的には、CRUDができるServletや、HTMLページなどを生成するscaffold生成機能も用意したいと考えている。しかし、今現時点では、まだ他に優先してやるべきことがたくさんあるので取り掛かることはまだしない。

 最近知ったのだが、これに非常によく似たものに、Simple Modelerというものがある。モデル駆動開発を掲げ、Scalaで作成したメタデータを元にモデルを自動生成できる。

 Reflexは割と古くて2005年ぐらいから存在しているが、そのコンセプトは黙殺されてきた感がある。(別に流行らなくても結構なのだが)
 最近、同じようなことを考えている方が世の中にもいるということで、ちょっと安心した感もある。だが、Simple Modelerが大流行りして、Reflexが真似しているといわれないようにしないといけないなあとは思う。

木曜日, 7月 30, 2009

【Google App Engine】 RESTfulアプリのCRUDサンプル -Servlet編- このエントリーを含むはてなブックマーク


 今回は、RESTfulアプリのServlet部分について説明する。例によって、請求書アプリを題材にしている。使用しているReflexGaeライブラリは=>ココ

検索(GET)

 検索ではRequestパラメータを受け取り、それを条件にdatastoreを検索して、結果をJSONもしくはXMLで返す。

 1. ReflexServletをextendsしてRESTful機能をもたせる
 2. RequestパラメータをEntity(Invoice)にセットする
 3. パラメータInvoiceを与えてdatastoreを検索
 4. 結果をJSONもしくはXMLにして返す
 5. エラー発生時はエラー内容をJSONもしくはXMLにして返す




登録(POST)

 登録では、クライアントからPOSTで受け取ったXMLもしくはJSONをEntityオブジェクトに変換した後、datastoreへのINSERTを実行する。クライアントには登録成功でHTTPStatus201(created)を返す。


 1. クライアントから受け取ったXML(JSON)をEntityオブジェクトに変換
 2. すでに登録されている場合エラー
 3. 登録されていなければinsert
 4. エラー発生時はエラー内容をJSONもしくはXMLにして返す




更新(PUT)

 更新では登録と同様に、クライアントからPOSTで受け取ったXML、JSONをEntityオブジェクトに変換してUpdateを実行する。更新オブジェクトのRevision番号が同一であれば更新実行、異なれば楽観的ロック失敗とする。



削除(delete)

 削除では、リクエストパラメータをもとに削除したいオブジェクトを取得し、deleteを実行する。該当するオブジェクトが存在しない場合に、HTTPStatus 204(no content)を返すようにしているが、これは特になくてもよい処理かもしれない。



嵌りどころと注意点

 1. POSTの場合、Requestに対し、getInputStreamを実行する前に、getParameterを実行してしまうとInputStreamの値が読み取れない。(PUTの場合はなぜかうまく動作する)
 2. HTTP Status 200,201以外をセットする場合、ResponseのOutputStreamに内容が出力されない。具体的には以下のような現象となる。


(HTTP Status) : (現象)
* 204 : 内容なし
* 409 : java.io.IOException
* 404 : java.io.FileNotFoundException


 最後に一言。GAEにおけるアプリケーション開発で特に重要だと思うのはテストである。テストコードを書けとか、TDDをやれとかいう意味ではなく、実際にテストして動作を確認することが重要である。(私は自分が作ったアプリのテストコードはほとんど書かないが、他人が作ったものは実際に検証しないと何も信じないタチである。)実際に現象を確認しないで、SPECやDocumentを見て判断してはいけないし、やみくもに信じてはいけない。ある程度予想できる結果であったとしても、必ずテストして確認すること。GAEは特にそうしないと危ない。石橋を叩いて渡るぐらいの心構えでちょうどよいと感じている。

<関連>
AJAX CRUDサンプルとJDO代替ライブラリ
RESTfulアプリのCRUDサンプル -Modeling編-

火曜日, 7月 28, 2009

【Google App Engine】 Pagingをどうやって実現するか このエントリーを含むはてなブックマーク


 JDOをそのまま使うとPagingができないことは前記事で述べたとおりだが、DatastoreAPIを使えば可能なので、今回はその方法について述べたいと思う。前記事と同様、請求書アプリを元に説明する。

KeyとCounter


 まず、基本となるEntityのInvoiceBaseとInvoiceの構造から。



 InvoiceBaseは、Invoiceレコードを保持するする親のEntityだ。InvoiceBase(親)に紐づくInvoice(子)は1:nのOwnedな関連である。また、Invoiceレコードの件数を格納するcounterプロパティをもつ。InvoiceのKeyは、トランザクションで括る必要があってKeyを連結させているが、拙作ライブラリReflex GAEのAPI、keyUtils.getChildKey()を使って、連結されたInvoiceのKeyを取得している。(ReflexGaeライブラリは=>ココ
 レコードの件数counterは、Pagingのために必要な連番を振るためにも使用される。Datastoreは自動で連番を付けられないため、InvoiceBaseの自身でもつより他ない。

 一応、JDOのドキュメントで以下のようなものがあったので試してみたが案の定できなかった。(追記:最新版SDK1.2.6では、Statics APIで件数が取れるようになっている。こちらの記事の参考に=>Keyとカウンタは別々に考えるといいかも


【コード】
 @PrimaryKey
 @Persistent(valueStrategy = IdGeneratorStrategy.INCREMENT)
 private Long uid;

【エラー内容】
 Message : There is no available value generator for strategy "increment" for this datastore. Please consult the documentation for details of which generators are available.


 そもそも、親子関係をもつようなEntityを扱うには、Long型ではなくKey型を使わなくてはならない。Googleのドキュメントにも記述されているが、Keyの中身が以下のようなツリー構造をしていることからもその理由は想像できる。


子要素までaddしたときのキー(実際はBase64でエンコードされている)

 j reflexworksr,  InvoiceBase" InvoiceBase Invoice"ID2
 j reflexworksr,  InvoiceBase" InvoiceBase Invoice"ID1


 よく、KeyをStringとしてもたせるような記述、「@Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")」を見かけるが、階層型の場合、連結させたDatastoreのKeyがそのままStringに変換されてしまうのでおもしろくない。例えば、先のEntityのKeyをStringにするとその中身は、「j reflexworksr,  InvoiceBase" InvoiceBase Invoice"ID1 」となってしまう。業務アプリで意識すべきは、業務アプリのKeyであって、DatastoreのKeyではない。DatastoreのKeyはむしろ隠蔽させて、ID1という業務アプリのキーだけを意識させる方がわかりやすいだろう。なので、Reflexでは、JDO KeyをStringとしてもたせる記述はせず、アプリのPKをKeyに変換するという方法をとっている。以下はアプリのPKであるinvoiceNoをJDOのKeyに変換する例である。(keyUtilsはReflexGaeのAPI)


 Key childKey = keyUtils.getChildKey(Invoice.class, param.invoiceNo);


Keyによる検索

 このPKを使った検索の例は次のとおり。pm.detachCopy()をすることで、Persistentではない、自由に扱えるEntityのコピーを得ることができる。Persistentなものは、まだDatastoreにAttachされていて、コネクションが張られている状態のような感じ。実際に値を書き換えるだけでDatastoreの中身も変更される。



Paging検索

 Paging検索では、以下のように、idで開始点を与えて、かつ、withLimitで範囲を絞るといった感じになる。JDOでは6千件でフリーズしてしまったが、DatastoreAPIを使っているため理論的には無限で、このサンプルではcounterの最大値(longの2147483647件)までは扱えることになる。とりあえず1万件でテストしてみたが非常に高速にレスポンスが返ってきたので問題なく使えると思う。

 1) filterで開始点となるidの値をセットして、それ以上のものを検索対象とする

query.addFilter("id", Query.FilterOperator.GREATER_THAN , Long.parseLong(nextId));

 2) FetchOptionsでwithLimit()をつけることで、検索結果の件数を絞る

FetchOptions fetchOptions = FetchOptions.Builder.withLimit(limit);




指定可能なfilter条件

 DataStoreAPIでは、GREATER_THANなどのinequality filter(<,>など)が1つと、equality filter(=)を複数指定できる。連番でinequality filterを使ってしまっているため、あとはequality filterだけが使えることになる。Reflex Gaeライブラリでは、QueryUtilsというものを用意していて、検索条件を格納したParameterBeanからequality filterを自動的に追加できるようにしている。

 // 検索項目(Indexがあるもの) を指定してnewする
 QueryUtils queryUtils = new QueryUtils(new String[]{"invoiceNo","companyName","job","issuedDate"});

// paramの検索項目がnullでなければaddFiler(FilterOperator.EQUAL)される
queryUtils.setParam(param, query);


EntityConverterによる変換

 DatastoreAPIで検索すると、MAPで返ってくるのでEntityのPropertiesからListに変換する必要がある。DatastoreAPIには、DataTypeTranslatorというのがあったが、使い方がよくわからなかったので自前で作成した。それがEntityConverterである。

List result = entityConverter.convert(Invoice.class, resultIterable,null,condition);


 filterで指定できる条件はequality filterだけなので、Like検索など複雑なことをやりたい場合には、Entityを取得した後で別途Java側で処理しなければならない。EntityConverterにソート機能や条件抽出機能をもたせたているのはこういった理由からだ。
 comparatorをEntityConverterの第三パラメータに与えることでEntityをソートして返すことができる。また、EntityConverterの第4パラメータにconditionを与えることで、conditionに合致するものだけを変換対象にするといったことができる。
 
Indexについて

 上記ソースのQueryはDatastoreAPIのものであってJDOQLではないので注意が必要だ。JDOQLでは自動的にIndexが作成されるが、DatastoreAPIではindexがないとエラーになるので自分で作成する必要がある。(これはむしろ好都合)
 作成するには、すべての検索パターン分のindexを定義した、datastore-indexes-auto.xmlを所定の位置(WEB-INF/appengine-generated)の下に置いてDeployするだけだ。(datastore-indexes.xmlではダメだった。また、index作成には結構時間がかかるので辛抱づよく待つ必要がある。管理画面のDatastore=>Indexesで、StatusがServingになればOKだ。とにかく待とう)
 すべての検索パターン分のindexとは、検索条件の組み合わせをすべて定義しなければならないという意味である。例えば、請求書アプリでは、"id"と"companyName"の2つの条件で検索したい場合もあれば、"invoiceNo","companyName","invoiceNo","issuedDate"の4つで検索したい場合もある。検索する可能性の組み合わせすべてを定義しなければならない。



登録処理 

 登録では次のような感じになる。



大規模なデータをもつ子要素に対してInsertして問題ないか

 まず、pm.getObjectById()でinvoiceBaseを取得する。存在しなかったら新規作成して、pm.makePersistent(invoiceBase)を実行する。これは更新時には必要ないため新規作成時のみ実行するようにする。Invoiceレコードを追加するたびに、InvoiceBaseのcounterをインクリメントする。
 InvoiceレコードはinvoiceBaseの子要素であるが、いわゆる、eager loadではないため、pm.getObjectById()しただけでは、Invoiceの全レコードがメモリに乗ることはない。getter/setterでアクセスしたものだけが実際のDatastoreへのアクセス対象となるので、膨大なレコード数が対象であってもこれでOKだ。(実際に1万件に対して実行しても大丈夫だった)

パフォーマンス

 パフォーマンスへの影響を考えた場合、EntityGroupは最小化すべきとよく言われる。実際、この例はテーブルロックのイメージに近いため、RDB設計に携わってこられた方は、どうしても気になるところだろう。counterとレコードの関係を考えると、トランザクションは切り離せない部分であるため、どうしてもこのような実装になってしまうが、それでも、コンテンションが起きた場合は、JDOCanRetryExceptionを拾ってリトライできるので、スループットは出せるのではないかと思う。実際に測定してみたところ、遅くなる要因としては、EntityGroupの大きさというより、トランザクション処理の件数の方がインパクトが大きかったので、TaskQueueとMemcacheを駆使して、複数のトランザクションを1つにまとめて非同期に一括処理するようなものを介すことでパフォーマンスを改善できると思われる。このあたりの話は深いのでまた別の機会に詳しく述べたいと思う。
 ちなみに、上記コード中で、JDOCanRetryException内で都度rollbackしているのは、そうしないとうまく動作しなかったからだ。(Documentどおりだと動作しないと思われるので注意)

楽観的ロック

 同一レコードの書き換えでコンテンションが起きてしまう場合は楽観的ロックが有効である。@Version(strategy = VersionStrategy.VERSION_NUMBER)を使用する方法があるようだが、この程度のものは潰しがきくので自前で実装する方がよい。具体的には、Updateの際にrevisionを比較して同じであれば更新実行してrevisionを+1するだけ。比較して違う場合にエラーとすればよい。

<関連>
Entityとトランザクション
JDOから直接JSON、XML
JDOから直接SOAP、ATOM。それからDeep Copy
AJAX CRUDサンプルとJDO代替ライブラリ
RESTfulアプリのCRUDサンプル -Servlet編-
RESTfulアプリのCRUDサンプル -Modeling編-

土曜日, 7月 25, 2009

【Google App Engine】 AJAX CRUDサンプルとJDO代替ライブラリ このエントリーを含むはてなブックマーク

RESTfulなWebサービスとワンソースマルチビュー

 先日行ったプレゼンの請求書DEMOでは、以下のように、HTMLの請求書を直接編集後、PDFを表示させるというところをお見せした。(以下のHTMLを表示させて右クリック、Searchで何かを選択してデータを読み込む、さらに右クリックでPDFを選択して生成)

 請求書デモ








 これは一見、統合されたアプリのように思えるかもしれないが、単なる疎結合なサービスの組み合わせであるにすぎない。つまり、JSONやXMLでCRUDできる機能だけが実装されたRESTfulなGAE上のサービスと、そのサービスに対してAJAXでアクセスするHTMLとJavaScript。そして、GAEのサービスからXMLを取得してPDFを生成するReflex iTextサービスの3つの組み合わせで成り立っているものである。特筆させていただきたいのは、ブラウザで表示させたHTMLとPDF生成で使ったテンプレートHTMLは全く同じものを使用しているという点。GAEのサービスから取得したものであるから、データはもちろん同じものである。このように、Reflexは、ブラウザやPDFなど様々なViewに対して、同じEntityを与えさえすれば、同じように表示させることができる。これをワンソース・マルチビューという。(そもそも、1つのEntityから複数の写像をとれるという意味で、名前をReflex(写像)としている)
 このように、ブラウザ以外にも、携帯やiPhone、Android、Flex2などの異なるメディアや端末に対象を広げられれば、コミュニケーションの幅を簡単に広げることができるため、ワンソース・マルチビューは今非常に重要視されている概念となっている。また、 Chrome OS戦略とIT世界の対立軸 でも述べているとおり、Googleは、RESTfulなWebサービスを基本とすることで、コミュニケーションに革命をもたらすとまでいいきっている。

Entityをそのまま表示させる

 これまで説明したように、Reflexではサーバで画面を作ることはしない。JSPも使わない。こうしてしまうと、どうしても密結合なアプリになってしまう。これは非常に大きなデメリットである。Reflexでは、JSONやXMLのCRUDだけが行えるサービスを基本とするが、JSPも使わないとなると具体的にどのようにブラウザで表示させればよいかが問題となる。この点について説明しよう。そんなに難しく考えないことがポイントである。

 まず、HTMLでモックを作り、表示させたいタグにIDを振る。画面が出来たら、IDを全部抽出して並べてルートタグで括る。これが表示用エンティティ。あとはそのエンティティをJavaでも実装して、AJAXを使って受け取れるようにする。JSONだとeval()できるので楽である。あとは、evalした個々のデータをHTMLのidに対してJavaScriptで挿入すればよい。具体的には、DEMOのinvoice.htmlとdisplay.jsを見ていただくのがよいと思う。ちなみに、Reflex iTextのデータ挿入もほぼ同じやりかたで行っている。また、高速化プロジェクト その1で述べたように、パフォーマンスも特に心配することはない。

 ただ、何でもかんでもこのスタイルがよいわけではないことも付け加えておく。SEO対策などで、サーバが出力する最初の段階から完全なHTMLでないとまずい場合などがあるからだ。そういう場合は、Reflex iTextのように、テンプレートとXMLから完全なHTMLを生成するようなサービスを介すとよいと思われる。いずれにしても、画面をベタ書きして疎結合を損なう設計になることだけは避けたいところである。

JDOとスケーラビリティ

 ここからが本当に言いたいところ。

 我々が検証した限り、JDOは大規模データを処理できないことがわかっている。正確には、JDOQLであるが、たった6千件のデータでさえ検索することができないのである。Indexが勝手に作成されてIndex爆発が起きる問題など、いくつか致命的なものもあるが、最も酷いのは、検索対象を絞るページングなどの範囲指定ができないことである。実は、JDOQLは5千件ぐらいまでは何とか検索できる。あれ?上限は千件までじゃなかったっけ?と不思議に思う方はGAEをよく知っている方。そう、一度にFetchできるのは千件までなのだが、それはDatastoreAPIの話。上位実装であるJDOではなんと5千件一括検索ができてしまうのだ。余計なことに、そんなことができる反面、6千件だともうフリーズしたように無反応になる。setRange()を指定してもダメ。getObjectById()やequalの検索条件を指定してやっと1件取得できるのみ。keyの複数件検索も未サポートなので、もう、これは使い物になりません。(※ただし、トランザクションや更新系はJDOのPMで問題なく使えている)
 そこで、私たちはJDOQLを諦め、低レベルのDatastoreAPIだけを使った検索ユーティリティを作成することにした。これを使えばPagingもできて大規模データの操作も問題ない。先の請求書DEMOも使用している。次回はこの中身について説明していきたいと思う。

<関連>
Reflex GAE
Entityとトランザクション
JDOから直接JSON、XML
AXIS2のデータバインディング能力
JDOから直接SOAP、ATOM。それからDeep Copy
Pagingをどうやって実現するか
RESTfulアプリのCRUDサンプル -Servlet編-

金曜日, 7月 17, 2009

【Google App Engine】 TaskQueue API for Javaが数週間以内にリリース!? このエントリーを含むはてなブックマーク


AppEngine SDK1.2.2にTaskQueue APIが含まれていなかったことで残念に思っている方も多かっただろう。MLではgoogleにかなり圧力がかけられていたようで、今朝、ようやくリリースの見通しについて口を割ってくれた。それによると、数週間以内にリリースされるだろうとのこと。やったー!\(^o^)/

TaskQueue API for Java ETA

Marcel,

ASAP means that it is one of our top priorities. Rather than give you a specific date and disappoint you if we don't meet it, we're working hard to release it as soon as we feel it has reached a quality level people can be happy with it. We typically provide new SDK releases on the order of weeks, so you can do some extrapolation from there.


火曜日, 7月 14, 2009

【Reflex iText】 Google Spread SheetからPDF生成するBookmarklet このエントリーを含むはてなブックマーク


 マイクロソフトがネット版オフィスを発売するそうだ。ネット化により、軽量化され、どこからでもアクセスできるという利便性もあるが、それ以上に、他のサービスやアプリと協調できるメリットの方が大きいと私は思う。例えば、Reflex iTextは、ネット上の様々なデータを元にPDF化できるが、GoogleのSpread Sheetと連携することもできる。ネット上でデータを作成してPDF帳票を出力する、といったBIツールのようなことが個々のサービスをマッシュアップさせることで可能になるのである。


* GoogleSpreadSheetCsvParser
http://csv2xml.latest.reflex-itext.appspot.com/

* GoogleSpreadSheet > Shre > Get the link to share
1. Allow anyone with the link to view (no sign-in required) にチェック
2. Also allow them to edit にチェック
3. Save&Close
4. スプレッドシート共有URLをコピー
5. http://csv2xml.latest.reflex-itext.appspot.com/csvparserservlet のGETパラメータとして
row=record
url=スプレッドシート共有URL
を指定


詳細については以下にまとめてあるのでぜひ参照いただきたい。

Google Spread Sheetから帳票作成

木曜日, 7月 09, 2009

【雑記】 Chrome OS戦略とIT世界の対立軸 このエントリーを含むはてなブックマーク

Chrome OS戦略


 昨日、Google Chrome OSの発表があった。Google Chrome OS のご紹介

Google Chrome OS の重要な要素は、スピードと使いやすさ、安全性です。
ユーザーが数秒でコンピューターを立ち上げてウェブにアクセスできるように、非常に高速で軽量の OS を設計中です。ユーザーインターフェイスはユーザーの妨げにならないよう最小限に抑えられ、ユーザーエクスペリエンスのほとんどはウェブ上で提供されます。


 Chrome OSは、「Webがすべて」という、これまでのGoogle戦略の延長線上にあるのは間違いない。これは、要は、クラウドとシンクライアントだけの世界をめざすものである。また、オープンソースの軽量オペレーティング・システムでLinuxを使うとしていることから、実際にはChrome(メッキ)のような薄いものを被せるだけのようだ。WindowsのようなファットなOSを開発するつもりは毛頭ないのだろう。というわけで、Chrome OSの上に高速なレンダリング機能をもつブラウザを載せてアプリを動かすことが中心となる。クライアントが入力したデータは、タイムスタンプのタグがつけられて、サーバに蓄えられる。そして、それがそのままクライアントに送り返される。あとは、それを受け取ったクライアントが自由にレンダリングする、といった感じのアプリケーションになっていくだろう。これはRESTfulなWebサービスを基本とするものである。RESTfulなWebサービスによる疎結合がスケーラビリティをもたらし、また、コミュニケーションにも革命をもたらすということだ。

携帯とのすみわけ

 ただ、Androidでも、そこで開発されているアプリのほとんどは、ブラウザを利用したWebアプリではない点には注意が必要だ。携帯とPCとは、異なるメディアである。そもそも画面サイズという根本的な違いがある。RIA的に進化したブラウザもアリかもしれないが、今の段階では、RIA的な濃さがPCと携帯では違うという認識は重要だろう。ネットブックには、Androidも搭載可能といわれてきたが、GoogleはAndroidに統一するのではなく、Chrome OSを登場させてきた。その大きな理由は、携帯とPCとでレンダリング方法の根本的な違いがあるのかもしれない。
 ただ、携帯アプリがブラウザではないにせよ、先に述べたRESTfulなWebサービスを解釈し、レンダリングするアプリという位置づけであることは変わらない。PCを含め、今後のブラウザはデータを処理できるビジネスロジックを備えたRIA化の方向で進化していくから、ブラウザとRIAとの違いの差はなくなっていくと思われる。なので、携帯がブラウザ中心でないことをそれほど気にするする必要はないと私は感じている。

IT世界の対立軸

 インターネットビジネスにおける「オセロの四隅」は、PC、Enterprise、Cloud、Mobileである。(と、私が勝手に妄想している)
 現在、これらを抑えているのが、Microsoft、IBM、Oracle、Apple、Google、Amazonなど。今一番元気なのがGoogleで、それに対抗しようとしているのがMicrosoft。ディフェンディングチャンピオンに立ち向かう挑戦者の構図は、一昔前であれば、IBM vs Microsoftであった。もちろん、今もIBMは健在なのだが、なにぶんGoogleからは遠すぎる。当然、Googleもエンタープライズにいきたいと思っているけれどもIBMやMicrosoftのように顧客をもっていない。これらは営業が汗水流して長年培ってきた財産であり、そんなに簡単には手に入らない。Googleがすぐにエンタープライズにいけない理由は、Webでしか商売をしない「Webがすべて」という戦略の裏返しでもある。なので、Googleの戦略からいくと、まずはコンシューマで、次にエンタープライズという順番なのだろう。コンシューマですぐ隣にいるのがMicrosoftなのだから当然ガチンコになるというわけだ。









 

水曜日, 7月 08, 2009

【おしらせ】 7/22(日食の日)次世代Web活用部会 セミナーでReflex iTextについて話します このエントリーを含むはてなブックマーク


2009年7月22日(水)日食の日、第1回次世代Web活用部会(XMLコンソーシアム) にて、Reflex iTextの概要を話します。

・『Reflex iTextサービスについて』
~クラウドならではの無限のスケーラビリティを簡単に体験

デモ中心であんまり濃い話はしないつもり。

受講参加するには事務局にメールすればいいじゃないかなあ。たぶん。

土曜日, 7月 04, 2009

【Amazon EC2】 GAEからEC2を管理するツール、CloudWatchなど このエントリーを含むはてなブックマーク




 Scalable PDFでは、EC2インスタンスの起動/終了やCloudWatchを使ったリソースのモニターなどを、Google App Engineからできるようになっている。わざわざGAEを使っているのは、利用料削減とレイテンシーの改善のためである。EC2インスタンスをずっと起動しているとチャージされてもったいないので、必要なときに必要な分だけのインスタンスを起動する、というオンデマンド的な利用がおすすめだ。インスタンス起動は数十秒で可能であり、また、Reflex iTextが揮発性で疎結合であるため、このような経済的なシステム利用(グリーンIT?)が可能になっている。レイテンシーについては、前記事にも書いたとおり、GAEを介す方が50%も改善できるという結果もある。

 さて今回は、このScalable PDFでも採用しているテクニックをいくつかご紹介したいと思う。まずはCloudWatchから。

GAEでCloudWatch

【Amazon CloudWatchとは】
 ・Amazon EC2のインスタンス(仮想サーバ)の状態を監視するサービス。
 ・インスタンスのCPU使用率やネットワークI/O、ディスクI/Oをチェックすることができる。
 ・$0.015 per Amazon EC2 instance hour
 ・インスタンスを落としても2週間は参照可能。
 ・AWS Management Consoleからは2009-07-02現在使用できないため、利用開始時にはEC2コマンドラインツールの「ec2-monitor-instances」を実行する必要がある。
 ・モニターしたインスタンスの情報はCloudWatchコマンドラインツールの「mon-get-stats」で参照できる。

【リンク】
Amazon CloudWatch on GAE/J (beta)デモ
ソース

【このツールの内容】
 ・CloudWatchの監視対象としたインスタンスの情報をGAE/J上から閲覧する。
 ・公開版は過去に使用したインスタンスの情報のみ参照できるようにしている
 ・Firefox3.0とIE6では動作確認済み。

【このツールの仕組み】
 基本的に、CloudWatchAPIの実行結果XMLをReflexを使って一旦パースし、それをJSONに変換してブラウザに渡して、JavaScriptを使って表示している。

 1.GAE/J→CloudWatch
  CloudWatchAPIのListMetricsを叩いて、参照可能な監視情報一覧を取得(json)。
 2.GAE/J
  参照する情報を指定。
 3.GAE/J→CloudWatch
  CloudWatchAPIのGetMetricStatisticsを叩いてインスタンスの情報を取得(json)。
 4.GAE/J
  取得した情報を表示。

【項目の説明】
  MeasureName
  参照する監視内容。
    CPU使用率、ネットワークI/O、ディスクI/O。
  DimensionName
    監視対象の分類。
    インスタンスIDごと、イメージIDごと、インスタンス種別ごと。
  DimensionValue
    監視対象の詳細。
    インスタンスID、イメージID、インスタンス種別。
  From
    参照開始日時。
  To
    参照終了日時。
  Period
    抽出する間隔(秒)。
    60なら1分ごとのデータ。
    3600なら60分ごとのデータ。

【使用例】
  1.Amazon CloudWatch on GAE/J (beta) > Menu > CloudWatch > Control
  2.-MeasureNameでCPUUtilizationを選択。
  3.-DimensionNameでInstanceIdを選択。
  4.-DimensionValueでi-b3ac89daを選択。
  5.Fromを2009-06-22T00:00にセット。
  6.Toを2009-06-24T00:00にセット。
  7.Periodを3600にセット。
  8.GetStatisticsMetricsボタンをクリック。
  9.結果テーブルのタイトル行をクリックするとソート可能(TinyTable JavaScript Table Sorterを利用)

  ※参照可能なデータが無い場合や表示データ上限数を超えている場合などは「Error!」と表示される。

【リンク】
  Amazon CloudWatch
  AWS Management Console(EC2)
  TinyTable JavaScript Table Sorter - 2.5KB

GAEでEC2インスタンスを管理する

 
 次に、EC2インスタンスの起動や終了をGAEに通知する方法について説明したいと思う。まずは、EC2インスタンス作成から。

【EC2インスタンスを作成】

 【初期操作】
  AWS Management Console等からAWSのデフォルトAMIを指定して新規インスタンスを作成。
    ↓
   インスタンスに接続してカスタマイズ。
    ↓
   AMIをS3に登録・保存
    S3に保存することで次回からも同じ設定のインスタンスを使用できる。

 【Amazon EC2のAMIをS3に登録する】
    インスタンスへsshして保存用イメージファイル(AMI)を作成→S3へアップロード→AMI登録

   * 保存イメージファイル(AMI)作成
     /mntディレクトリに移動して「ec2-bundle-vol」を実行。

    #cd /mnt/
    #ec2-bundle-vol -d /mnt --privatekey /path/to/pk-XXXX.pem --cert /path/to/cert-xxxx.pem --user YOUR-ACCOUNT-NUMBER --fstab /etc/fstab

    ** pk-XXXX.pem: Secret Access Key File
    ** cert-xxxx.pem: X.509 Certificate File
    ** YOUR-ACCOUNT-NUMBER: Account Number

    * S3へアップロード
    「ec2-upload-bundle」コマンドをバケット名を指定して実行。

    #ec2-upload-bundle --bucket /path/to/BUCKET_DIRECTORY_NAME --manifest image.manifest.xml --access-key XXXX --secret-key xxxx

    ** BUCKET_DIRECTORY_NAME: S3側のBucket Directory
    ** XXXX: Access Key ID
    ** xxxx: Secret Access Key

    * AMI登録
     インスタンスからログアウトして、「ec2-register」を実行。

     C:\>ec2-register /path/to/BUCKET_DIRECTORY_NAME/image.manifest.xml

【起動時にGAEに伝える仕組み】

 EC2インスタンスの起動終了時に、GAEのWebサービスプロバイダに対してステータスを通知することで、GAE上で利用可能なEC2インスタンスを管理することができるようになる。

  【仕組み】
   インスタンス起動時のnetworkが立ち上がる箇所で、自身のエンドポイント(ホスト名、インスタンスID)をec2nodeに登録するスクリプト(post_endpoint_to_gae.sh)を実行。
   インスタンス終了時にec2nodeから登録を削除するスクリプト(delete_endpoint_from_gae.sh)を実行。削除キーはインスタンスID。

  【/etc/rc.d/ini.d/networkの変更】
   インスタンス起動・終了時にエンドポイントの登録・削除を行うための設定。

    startコマンド最終行に以下を追加。(エンドポイント登録用)
     /bin/sleep 5
     /path/to/post_endpoint_to_gae.sh

     stopコマンド先頭行に以下を追加(エンドポイント削除用)
      /path/to/delete_endpoint_from_gae.sh
      /bin/sleep 20
      ※sleepをかけないとdelete_endpoint_from_gae.shの実行前にネットワークが切断されてしまい削除できない。

【エンドポイント登録・削除用スクリプト】

    登録(post_endpoint_to_gae.sh)
     エンドポイント情報を取得し、ec2nodeへPOSTする。
     「http://169.254.169.254/latest/」はAWS側で用意されているインスタンスID等の問い合わせ先。



     #!/usr/bin/php
      <?php
        $publicHostname = trim(file_get_contents("http://169.254.169.254/latest/meta-data/public-hostname"));
        $instanceId = trim(file_get_contents("http://169.254.169.254/latest/meta-data/instance-id"));
        $status = "IDLE";

        $data = array(
            "ec2record" =<
                  array(
                      "ec2node" => "{$instanceId}",
                      "endpoint_url" => "{$publicHostname}",
                      "status" => "{$status}"
                  )
            );

        $json = json_encode($data);

        $url = "http://www.example.com/ec2node";
        $options = array(
          "http" => array(
               "method" => "POST",
               "header" => "Content-type: text/plain",
               "content" => $json
            )
        );

        $context = stream_context_create($options);
        $fp = fopen($url, "r", false, $context);
        fpassthru($fp);
        fclose($fp);
        exit("\n");
       ?>


     削除(delete_endpoint_from_gae.sh)
      インスタンスID(削除キー)を取得し、ec2nodeへDELETEする。

      #!/usr/bin/php
      <?php
        $instanceId = trim(file_get_contents("http://169.254.169.254/latest/meta-data/instance-id"));
        $url = "http://www.example.com/ec2node?ec2node={$instanceId}";
        $options = array(
          "http" => array(
               "method" => "DELETE",
               "header" => "Content-type: text/plain"
            )
        );

        $context = stream_context_create($options);
        $fp = fopen($url, "r", false, $context);
        fpassthru($fp);
        fclose($fp);

        exit("\n");
      ?>


火曜日, 6月 30, 2009

【Reflex iText】 Google App Engineで動く無償PDFサービス このエントリーを含むはてなブックマーク



Reflex iTextがGAEで動いたのでご報告。

Reflex iText/GAE DEMO

DEMOのURLを見ていただくとわかるが、templateに、http://dl.getdropbox.com/u/200214/qrcodesample.htmlを、entityに、http://dl.getdropbox.com/u/200214/qrcode.xmlを指定することで、ダイナミックにPDFを生成している。

templateは、こちら(機能概要)に作成方法をまとめてある。これは、htmlとCSSを作成する通常のWebページと同じ要領で作成できるのがウリである。ただし、GAEバージョンではまだグラフ出力だけができないのでご容赦願いたい。(近日中に対応予定)

xmlは、普通にデータを要素タグで括ればよい。要素は自由に定義できるが、Reflex iTextは、htmlのid属性にXMLのデータを差し込むイメージで合成するので、htmlのidに要素名が対応していなければ意味がない。

templateとxmlの準備ができたら、適当なWebサーバかDropboxなどに置いて、以下のようにURLを呼び出せばよい。PDFサービスはリクエストを受け取ると、コールバックしてtemplateとxmlを読みにいき、それらの情報をもとにPDFを生成する。

http://pdf.latest.reflex-itext.appspot.com/pdfservicegae?template=hoge.html&entity=fuga.xml

GAEはクオータはあるものの理論的には無限にスケールできるので、このサービスは使える限り、誰でもいくらでも自由に利用して構わないこととする。ただし、これを使用して生じた損失などの責任は負いかねるのでご容赦願いたい。

なお、テンプレートの作成依頼や商用サービスとして提供したいなど、相談があれば遠慮なくご連絡いただきたい。

support@virtual-tech.net



金曜日, 6月 26, 2009

【Reflex iText】 パフォーマンス測定でわかったAmazon EC2の真の実力とレイテンシー このエントリーを含むはてなブックマーク


 Amazon EC2の高スペックなマシン(c1.xlarge)にReflex iTextのインスタンスを載せてパフォーマンスを測定してみた。c1.xlargeは、Opteron 1.0-1.2GHz相当20Unit分、Memoryは7Gあり、Celelon 2.2Ghz、512Mの約10倍のパフォーマンスだった。
 Reflex iTextのスループットは、(予想通り)20個のJettyを起動して並列実行させたときに最大を示し、1Jettyあたり20ページ作成で133ページ/秒を出した。

 PDF生成パフォーマンステスト


* 20プロバイダ*20ページだと133ページ/s
* Total 3秒
* テンプレートHTMLは51Kb*20回取得
* エンティティXMLを300Kb*20個分割して取得
* 20プロバイダ*5ページで1秒なのでHTMLとXMLの転送コストはほとんどないと考えられる

* 1プロバイダ*400Pだと10ページ/s
* Total 40秒
* テンプレートHTMLは51Kb*1回取得
* エンティティXML 6Mbを1個取得




 また、Google App Engineを間に置くことでレイテンシーを50%も改善できることがわかった。100件のPDF(1.5Mb)の生成10秒、転送12秒の合計22秒かかるが、GAEを介した場合、なんと16秒で取得できる。これは転送時間を半分にする計算である。
 もともとGAEは近くのサーバが選択されるため①、④は高速であることはわかっていた。また、EC2とGAE間も非常に高速であることから、このようなレイテンシー改善になったのである。(CloudFrontはいらない?)




木曜日, 6月 25, 2009

【Reflex iText】 QRコード生成サービス このエントリーを含むはてなブックマーク

QRコードを作成してpngとして返すサービスをMorph AppSpaceのテストサーバに置いている。Reflex iTextの一機能なので、例によって、テンプレートとエンティティは外部から与えることで生成する。テンプレートなどはDropboxに置いている。

http://pdfservice.morphexchange.com/image/qrcode.png?template=http://dl.getdropbox.com/u/200214/qrcodepngsample.html&entity=http://dl.getdropbox.com/u/200214/qrcode.xml

使い方は以下のとおり。


  • QRコードのPNG出力機能

  • 属性
    • value: QRコードに表示する値
    • height: 高さ
    • width: 幅
    • version: 型番(シンボルの大きさ)。0~10を指定。
    • errorcorrectionlevel: 誤り訂正レベル。L, M, Q, Hのいずれかを指定。
      • レベルL - コード語の約7%が復元可能
      • レベルM - コード語の約15%が復元可能
      • レベルQ - コード語の約25%が復元可能
      • レベルH - コード語の約30%が復元可能
    • cellsize: セルのサイズ(pixel)。1~4を指定。
    • margin: 余白(pixel) 。0~32を指定。
  • HTMLテンプレートとXMLエンティティ
  • 水曜日, 6月 24, 2009

    【Google App Engine】 PDF出力ができたっぽい このエントリーを含むはてなブックマーク


     こちらに書いたとおり、Reflex itextをGAE上で構築することを考えていたが、java.awt.*パッケージが使えないことで断念していた。
     ところが、昨日出たパッチを当てるとちゃんと動くではないか。これでGAEでもPDF出せるようになる。なんとすばらしい!ただ、グラフや図形などはちゃんと試していないのでReflex iTextがそのまま動くかどうかはまだなんともいえない。これから調査して報告したい。

     既存の2つのPDFをマージするデモ (GAE上でグラフやバーコードを作成しているわけではないので注意)
     

    火曜日, 6月 23, 2009

    【クラウドコンピューティング】 ビジネスを変える8つの方法 このエントリーを含むはてなブックマーク



    クラウドコンピューティングがビジネスを変える8つの方法

    という記事で特に1番と2番と6番がすばらしいと思ったので抜粋する。

    1.新世代の製品とサービスを作り上げる。


    クラウドコンピューティングの経済は、革新的な企業がこれまでは不可能だった製品を作り出すことや、競合相手よりもずっと安い製品(あるいは単にずっと収益性の高い製品)を作り出すことを可能にする。クラウドコンピューティングのこの側面は軍拡競争であり、このチャンスが得られるのは短期間に過ぎない。これは、一度その利点が効果的であることが証明されれば、競合相手がクラウドコンピューティングの経済的な利点を自社の製品に組み込むことは、比較的短期間でできるためだ。興味深いのは、手が出せないほど大量のコンピューティングパワーや規模、あるいはまったく新しいビジネスモデル(前述のオープンサプライチェーンやグローバルSOAなど)を必要としたり、既存の技術的な制約やコストパフォーマンスの制約によって実装不可能だったビジネス上のアイデアが、実現可能になったことだ。ストレージ、処理能力、テクノロジーの進歩は、これまで不可能だったイノベーションを可能にするが(たとえば高速インターネットはYouTubeを可能にした)、クラウドコンピューティングはそれらのチャンスを非常に手が届きやすいものにしてくれる。賢い企業は、すぐにこれに気づくだろう。


    2.ITサービス提供者との間での、新しい軽い形のリアルタイムな協力関係やアウトソーシングが可能になる。
    従来の形によるITサービスのアウトソースを経験している企業ならば、これがどういったものかをすでに理解しているだろう。アウトソーシングを行うと、これまで社内にあったものの大部分が、他のどこかに置かれ、何かを変えるのは困難になる。しかし、従来のITのアウトソーシングとは違い、クラウドコンピューティングは、これまでのアウトソースではほとんどの場合不可能だった敏捷性と管理可能性を与えてくれる。クラウドサービスベンダーが気に食わなければ、長期契約を結んでいるのでない限り、ITアウトソース事業者よりはずっと簡単にベンダーを変えることができる。実際、多くのクラウドコンピューティングの関係は、単なる月末にキャンセルが可能な契約と、法人宛ての請求書だけのものだ。多くの企業にとっては、この条件は今よりもいいものであり、すべてを社内でまかなう場合や、アウトソース事業者との関係を結んでいる場合よりも、はるかに多くの選択肢を与えてくれる。


    6.事業部門によるITのセルフサービス。
    多くのクラウドソリューションは、特にSaaSに関連している場合は、IT部門が関与する必要が少なくなってきている。今後出てくる多くのクラウドコンピューティングソリューションは、ビジネスユーザーが完全にセルフサービスで導入することができるようになるだろう。McKendrick氏が述べているように、これは多くのシナリオがより小さいものになり、数も増えて、IT需要のロングテールをカバーするものになるだろうことの前触れでもある。



    もちろん、いいところもあれば悪いところもある。以下はそれを示した図である。

    いいところと悪いところ(Pros and Cons)


     はっきりさせておくが、マイナーなアプリケーションのいわゆる「先端的」なコンピューティングや、必要不可欠ではないビジネスシステムに関してさえ、クラウドコンピューティングの導入には、まだ答えの分かっていない問題や、特有の課題があることが分かっている。その中でも目立った問題には、クラウドに保存される企業データのセキュリティ、クラウドプラットフォームベンダーへのロックインのリスク、他人が運営・管理しているクラウド資源にはコントロールができないこと、信頼性の問題などがある。




    実際の議論


     先日のクラウド研究会のMLで、まず、S氏が上記1.に関連する意見を述べてくれた。


     小さな会社のポジションが、一番Amazonなどを利用して、日本で伸びるべきだと思っています。
    日本で、クラウドだけをやるためにマシンを1000台購入し、ユーザーを募る、なんて例えば無理な話で、やはり他の主業務で投入したマシンを生かしてクラウドを、というスタイルでないと無理でしょう、
    という意味でXXXクラウドなどというのが日本で成功するとは思っていないわけです。

    例えば、日本の中小企業を生かす意味では、Amazon EC2の上でEDIを行うとかが一番ですね。


     また、ビジネスを提供する立場としての私の意見は次のとおり。


    私が強調したいのは、なんというか、クラウドでビジネスするというより、 ビジネスするならクラウド?という感じです。つまり、サービスを作ってGAEでプロバイドするけれども、Powerd by GAE を知らしめることより、サービス自身のスケーラビリティやアベイラビリティを強調することの方が大事なんじゃないかと。


     これに対して、F氏は、信頼性について指摘する。


     確かにクラウドのスケーラビリティやアベイラビリティは商用サービスを運営する上では大きなメリットだと思いますし、これに低コストが加われば「ビジネスするならクラウド?」は説得力はあるでしょう。

    でも、パブリック・クラウド上で商用サービスを運営するリスクも存在するわけで、特にサービス事業者を規制する国内法との整合性といった点が僕は気になってます。Above the Clouds でも10の課題のうちの Data Confidentiality and Auditabilityでこの問題に言及していますが、その記述はヨーロッパの各国がアメリカのクラウド・サービスを利用する場合の話しか書いてない。その対策も「EU域内にもデータセンタがあるから、そこだけで運営すればいい」という日本人には「え?」と思うような内容だったりします。

    つまり現時点では日本国内からのパブリック・クラウド利用にはこの手のリスクがどれくらい存在するのか、まだあまり明らかになってない。そういう状態で「小規模な事業者はクラウドがお勧め!」って言っちゃうのはどうなのかな?というのが僕の懸念です。小規模事業者は当然資金力もないので商用サービスのシステム構築した後に「国内法に違反するのでサービスできない」てなことになると、すぐさま倒産しかねないですもんね。


     これに対して私の回答。


    > 特にサービス事業者を規制する国内法との整合性といった点が僕は気になってます。

    おっしゃるとおりだと思います。
    今まで使っていた海外のホスティングもクラウドも同じようなもんだと考えていました。
    国内法についてはよく調べないといけないですね。

    > 商用サービスのシステム構築した後に「国内法に違反するのでサービスできない」
    > てなことになると、すぐさま倒産しかねないですもんね。

     国内法以外でも弊社が潰れてサービスできなくなる可能性はたしかにありますね。
    お客様が既に弊社のサービスを利用されていて、弊社がサービス運営できなくなった場合には、ちょっと言いにくいのですが、サービスそのものをお客様にお譲りすることになると思います。(;^_^A
     これで少なくとも、AmazonやGoogleが潰れないかぎりサービス継続できます、と回答するようにしています。お譲りするといっても、インスタンスのコピーを渡すのと、クレジットカード名義が変わるぐらいですかね。私たちが所有、管理するものは本当に少ないんです。また、引き続き運用管理をお願いといわれた場合には個々に対応していくつもりです。まあ、ちょっとあぶなっかしいかもしれませんが、そのあたりのリスクも含めて低料金でご提供させていただくことにしています。最終的にはお客様にご判断いただくしかないですね。


    S氏にもフォローいただく。


     >> サービス事業者を規制する国内法

    なんて今存在しないですよね。変な規制法は作らないように我々も動くべきだと思います。
    日本として鎖国したいなら違いますが。
    サーバーの場所が日本以外にある会社なんて一杯あるわけですし、インターネット経由での情報交換のセキュリティー確保以上の問題は、利用者の自己責任が大きいというのが、基本原則なのでしょう。 いずれにしても、SSLの使用以上に、クラウド内に格納されるデータの安全性(つまりクラウド運営会社も知ることの出来ないKeyで暗号化)を確保したいという思いが強いのは事実でしょう。


     とにかく、ビジネスは今はじまったばかりだ。利用契約の形態も含めて試行錯誤的に進んでいるのが現状である。AmazonEC2やGoogle App Engineの利用契約などは、必ずしも弊社を通すという必要もなく、お客様が直接契約するなど、やり方はいろいろあるとは思っている。

    月曜日, 6月 22, 2009

    【雑記】 ギークとスーツの喧嘩 このエントリーを含むはてなブックマーク


     梅田望夫がオープンソースを語っても残念でない理由

     私にはギークとスーツ(というより文化人)の喧嘩に見える。いかに正論をふりかざしても、変なのは我々ギークなんだから、そこんとこもっと踏まえて挑まないと、イタいめに合うことになる。文化人との議論は子供と大人の喧嘩より話にならん。「いやいや、そういう話じゃなくて」と反論したいのは梅田さんの方だと思う。そこをぐっと我慢してるのはさすが文化人。
     naoyaさんも指摘してるけど、梅田さんはオープンソースの技術的な話をしてるんじゃないよね。バザール的協業という話が本質であって、ずれてしまったのは、どうみてもギークのせいだね。むしろオープンソースを実践しているギークこそ、バザール的協業の意味を声を大にしていうべきとろだと思うけど、残念なことに、それがなかなか世の中に伝わらない。ギークは不幸にも、普通の人に伝えるのは下手だから、梅田さんのような方はとても大切になってくる。梅田さんはコードは書かないけど、自分たちが実践している行動とその意味を代弁してくれている。元々変である存在のギークをまっとうなものとして扱い、世間に通訳してくれる、これほどすごい代弁者は他にいないって、絶対。

     一方のひがさんは、これまたガツンといえるところ。いいよねえ。これまでの実績からいって日本のOSSの第一人者であるのは間違いない。だから、これだけ大きな反応があったのだろうよ。私なんかがいったところで相手にもされないのは明らかだしね。

     でもやっぱり世間の広さでいえば梅田さんの方に軍配があがると思う。ギーク以外の普通の人たちは98%の大多数を占めるから、たとえギークが2万人の支持を得られたとしても、98万人の普通の人たちは( ゚д゚)ポカーン 状態なわけですよ。だから、もっと普通の人の支持を得るためには、梅田さんのような通訳が必要になってくるわけ。その通訳された結果に対して、若干不備というか、意訳があったとしても、目くじらたてて怒ったりする必要はない。また、本当に理解してないだろコイツとか思って、いちいち反応する必要もない。なぜなら全く違う人種の人なんだから。

     ところで、最近の梅田さんは日本のギークに対して失望しているようだけど、私もこの閉塞感を、なんとかしたいなあと思っている。また、はてなに対してものすごくポテンシャルを感じているけど、最近はちょっと物足りないなあとも感じている。
     例えば、OSSで大規模システムを作れる技術があるんだから、サービスだけじゃなくて、真剣にクラウド事業をやるべきだと思う。日本発クラウド事業は富士通さんが真剣に取り組み始めたけど、はてなさんも頑張れるだけのポジションにいるのは明らかだ。クラウド事業はサーバだけじゃなくて、インフラ技術が一番大事で、そのあたりが得意なところは限られている。
     もしやるんだったら日本のギーク全員がはてなを支持すると思うし、トップの一人である梅田さんをリスペクトするだろうよ。今回の件は、閉塞感もあって相対的にお二人の影響力が低下してのも一因じゃないかな。もっと建設的な議論ができるといいのになあ。

    日曜日, 6月 21, 2009

    【クラウドコンピューティング】 IT輪廻とイノベーション このエントリーを含むはてなブックマーク


    集中、分散を繰り返すITの輪廻

     Azureに代表されるようなクラウドOSにおいては、P2PやGridといった主要な技術要素はクラウドOSの中に隠蔽されていてユーザには見えない。これは、サービスを提供するだけというクラウドOSの結実により、もっと大きな視点での集中がおきたことになる。
     クラウドOSに代表される現在の大きな集中への動きは、中島丈夫氏のIT輪廻の話にあてはめると納得がいく。IT輪廻に関しては、IBMerであれば耳タコ状態ではあるが、知らない方も多いと思うので、ここであらためて紹介したいと思う。(中島氏は尊敬するIBMきっての慧眼の持ち主。現在は退職されている。)
     ただし、この記事は2006年10月16日のもので多少古い。また当時のIBMはSOAを推進する立場であったことも付け加えておく。話の本質を理解しないまま、SOAに大失敗している今の現状だけをとらえて、これだめじゃんとかって思わないでもらいたい。

    新しい時代を迎えるITインフラ技術 -Web2.0を中心として-

    (2006年10月16日)

    これまでのシステム(コンピュータ・ネットワーク技術と社会・経済的文脈から創り出される情報システム)の歴史は、集中から分散へという流れの中で発展してきたこと、そしてそれぞれの極においては、「メーンフレーム中心」、「パソコン中心」、「インターネット中心」、「ビジネス中心」という特性が見られてきたことを指摘されました。
    そして、現在の「ビジネス中心」の特性においては、SOA(Service Oriented Architeture)を構築することによって、ビジネスとITを統合する形の発展が重要とされることを強調されました。
    こうした文脈において、これまで重要とされてきた「作る」、「買う」、「使う」といったDimensionに付け加えて、新たに「組合わす」という側面が加わるというご指摘は、サービス提供者と利用者の間に立つ仲介者(Mediator)の役割が重要になるというご指摘と合わせて、Web2.0へとつながるものであることを 示唆されました。

    社会進化の文脈の中で、オープンソースで皆がつながるという意義の重大性や、POA(Participate Oriented Architecture)というネットワークの開放性・外部性をもたらす概念の重要性を指摘された



    (関連)IT進化の軌跡



    SOAの反省とクラウドのイノベーション


     イノベーションとは、発明、発見、ビジネス、社会価値が合わさって展開されていくものである。前置きでいったように、結局、エンドユーザにSOAやGridを吹聴するだけでは、イノベーションが起きることはなかった。エンドユーザの方としては、ITベンダーには騙されないぞというよりかは、多くはわけわからんという感じだったと思う。SkypeなどP2Pの利用は一部であったものの、ことSOAに関しては、( ゚д゚)ポカーン 状態であり、それでいったい何ができるのか、理解されないまま終わったような感じだ。ITベンダーの方は、SOA!SOA!という掛け声をかけるのに一生懸命で、結局踊らされたのはITベンダー自身だったかもしれないとさえ思える。つまるところ、SOAに関しては、ビジネス、社会価値のポテンシャルはあるものの、活用という難問をエンドユーザに押し付ける形となっているのが問題であったと私は思う。

    一方、クラウドでは、利用者から見れば、サービスの提供という具体的な結果だけがもたらされる。クラウド内部では、ScalabilityやAvailabilityをもたらす技術、Fabricを形成する能力といった技術要素は隠蔽されているが、これは開発者から見ても同様で、単にRESTFulなAPIが用意されているのみで非常に易しい環境が提供されている。こういったことからも、クラウドが「サービス提供者と利用者の間に立つ仲介者(Mediator)の役割」として十分に機能することは容易に想像できる。そして、難しいところはすべて雲の上にお任せして、必要なものを必要なときに利用すればいいというような、シンプルなモデルへと変えることができるようになった。これはクラウドのイノベーションといえるだろう。

    クラウドは破壊的なイノベーションか

     クラウドが破壊的なイノベーションであるという話をちらほら耳にする。以下のつぶやきにはそれが端的に現れている。


    yusukef ・・ BASEトランザクションやCAP定理とかのファンダメンタル理解しないまま、フレームワークがあるからといってGAE/Jのアプリを設計&実装して大失敗して、クラウドだめじゃんとかって言わないでね


     これまでの手法が全く通用しないからという理由で破壊的であると決め付けるのは短絡的である。エンティティとURIが大事という、Reflexの設計思想は、RESTfulな設計に触発されたものだが、そのベースはWebサービスに遡る2004年頃の着想である。Reflexは流行っていないし、フレームワークが多くの人に利用されているわけではないが、RESTfulな設計という意味では共通するものがある。例えば、この頃、世界中の多くの開発者が同じようにインスピレーションを得て、2006年頃にはよく似たプロダクトが登場することになった。まず、IBMのsMashがReflexに非常によく似たものだったし、(関連記事)また、ReflexがGAEのJDOと親和性が高いのは設計思想が同じだからである。そして、Azureも同様の思想のもとでRESTfulなデータストレージを提供している。これは本当にビューティフルだなあと思う。Windows Azure ストレージサービス

     ここで、少々苦言をいいたい。

     クラウドが破壊的であると感じている人は、2004年頃に何を考えていたかを思い出すといいだろう。RDBが君臨している時代に、オブジェクト指向やRESTfulな設計に思いを馳せることは難しかったかもしれない。なので、あまり強くはいえないけれども、2006年になってもなお盲目的にEoDに邁進するコミュニティを見て、私なりに危機感を感じていたことは事実であった。

    楽をするために苦労を厭わない人たち - Seasarカンファレンス(秋)

    思考停止に陥っていたJavaに対して、一方のXML開発者はまだましだった。

    XML開発者の日


    まあ、過去のことは過去のこと。大切なのは現在、そして未来である。ほれいわんこっちゃないと私からいわれないよう、めげずに頑張りましょう!

    金曜日, 6月 19, 2009

    【雑記】 個の力、チームの力。私が会社をやって思うこと このエントリーを含むはてなブックマーク



     今回もクラウド研究会MLの私の発言から。

    江島さんのところのLingrも、発想はすばらしいものでしたが、コスト構造に問題あって閉じられるそうです。
     http://japan.cnet.com/blog/kenn/2009/05/01/entry_27022150/
    はてなさんがOSSだけで大規模システムを構築されて、おおっ!と思いましたけど、多分、これからはOSSだけでも厳しい時代になるんだと思います。

    こうなってくると必然的に私のような立場はGAEを「絶対的なもの」として妄信することになります。
    Lingrもクラウドであれば、もう少し延命していたかもしれません。わかりませんけど。



    これに対して、首藤さんは、人件費など別の指摘をされるとともに、これからの組織、個人について触れられた。

    数打ちゃ当たる、というか、数打たないと当たらない種類の取り組みなので。

    LUNARR も同様で、
    高須賀さんが 5/27 に IPAX2009 で御講演の中で
    「(ある種の) 事業をやるのに会社は要らない」
    とおっしゃってたというのは、そういうことだと理解してます。

    世界目指すベンチャー、既存のフレームを崩壊させよ--IPAXでLUNARR高須賀氏が講演
    http://v.japan.cnet.com/news/article/story/0,2000067548,20393976,00.htm

    「これまでスタートアップというと、会社を作って、優秀な人材をフルタイ
    ムで雇って立ち上げてきたが、現状では『事務所なんてスターバックスで
    いい』という動きになっている」(高須賀氏)


    同日午後のパネルで、僕は、
    知識産業というか何というか、ある種の領域では、
    個人のネットワークで動く部分が今後もどんどん広がっていく、っていう
    主張というか観測を述べました。

    個人ネットワークの時代へ
    http://www.shudo.net/publications/IPAX2009-panel/

    僕が「個人がすごく empower されてる」と言ったことに対して、
    ある方が「高須賀さんも午前中同じことを言ってた」と教えてくれました。



     たしかに、首藤さんのおっしゃるように、「個人がすごく empower されてる」のは、まちがいない。これを踏まえつつ、私はこう発言した。

     東大なのに「だって、プログラミングすきなんだもーん」といって、大手に就職しないOさんみたいな人、他にいるかもしれないでしょ。(安い給料ではきてくれないとは思いますけど、そこをなんとかしようよ。)

    私は敢えて、ワーキングプアな環境に身を置くことで自由を得て、好きかってなことをやっているわけなんです。(社員も同じですが、なにか?)

    私の場合、実は、サラリーマン時代も今とあまり変わらなかったりします。昔のIBMは懐が深かったなあ。

    それから、丸山宏さんの記事、http://japan.cnet.com/blog/maruyama/2009/06/08/entry_27022885/
    「スコットランドの歌姫」はいいですね。

    個人の力は増してきているかもしれませんが、それをどうやって社会と結び付けていくか。
    今のWebだけだと、ちょっと心もとない感じはしています。


     これをちょっと補足する。

     経済的にも精神的にも、個人は元来、弱いものである。理屈上は無限の可能性があるが、実際には出来ることは限られている。江島さんは、「今から思えば1人でできた仕事であった。4人は多すぎた」とおっしゃっているが、たぶん、1人では無理だろう。

     私も一人で会社を始めたものの、すぐに滅入ってしまうことが多かった。その一番の原因は不安からくるものだった。やはり、少なくとも2人、理想的には3~4人のチームで会社をやるのがいいと私は思う。それから、1+1=2ではなく、まちがいなく3以上の力になる。組織の力とはそういうものだ。
     ということで、3~4人が必要と考えると人件費が問題となるが、ここが一番努力すべきところ。そもそも、5000万/年は払いすぎだし、もらいすぎ。私から言わせれば、誰かに投資してもらったお金で人を雇おうという根性がまず甘い。自己資本でやると本当に雇うべき人が誰なのか、よくわかるものだ。

     また、ベンチャーは、「夢と自由」をひきかえに、敢えてワーキングプアーを選択する覚悟が必要であって、それは代表である自分自身も例外ではないはずである。そんな条件に合う人はなかなかいないかもしれない。でも見つけなければ何も始まらない。

     弊社は幸いにもスタッフに恵まれている。私以外に、プログラマー2名、デザイナー1名、経理1名と、決して高給ではないが皆非常に優秀である。

     狭いマンションを事務所としているが、ここにいるのは常時2名ぐらいで、あとはリモート環境でボイスチャットとGoogle Appsを使って仕事をしている。いわゆる、バーチャルオフィス。
    リモート環境で仕事しているのは、デザイナーとプログラマーの2人。デザイナーは私の甥っ子でまだ20才である。会社のホームページを作ってもらったが全部彼の手作りである。
     
     もう一人はプログラマーで主婦だ。生まれたての赤ちゃんを抱きながらボイスチャットに応対している。彼女はReflex iTextの担当。そして、週に一回毎月曜日にMTGをもち、全員が集まるようにしている。
     こんな感じで、極力コストを抑えて仕事をする努力をしている。

     それでも、今回のような不況がくると厳しい。

     今後は、クラウドの特性を最大限に生かしたサービスを開発して、多くのものを早く提供しなければならない。また、インターネット環境を最大限に活用して極力自動化することで、どこまでビジネスを完結できるか、これが一番のポイントになると考えている。

    木曜日, 6月 18, 2009

    【Google App Engine】 1アプリでもスケールするか このエントリーを含むはてなブックマーク



     負荷分散や高可用性のためにクラスタを構築する苦労がまったく不要なのがGAEのすごいところ。本当にそうなのか、モヤモヤしていたのでMLに聞いてみた。


    もしわかる方がいれば教えていただきたいのですが、1つのアプリケーションに対してリクエストが増えてきたときに、AppMasterから新たにデプロイされて、複数のAppServerによって並列に処理されるようになっているんでしょうか、それとも、1つのアプリケーションは1AppServerのキャパまでしか対応できないんでしょうか。

    「多数のアプリを同時に収容し、アプリ間の隔離性を確保する」

    ところまでは理解しているのですが、1アプリのスケーラビリティについて確認したかったもので、質問させていただきました。


    いろいろな方の回答があったのだが、そのなかでも実際の挙動に触れていて、一番信憑性がありそうなのは以下のポストだった。まあ、実際に確認するのはちょと難しそうだが、GAEでプロバイドすることでスケーラビリティが確保されることは確かなようである。

    メーリングリストより

    このあたりの話は

    http://groups.google.com/group/google-appengine/browse_thread/thread/2e65d8bc50f6bfd9/e6187c2f6052d6aa?show_docid=e6187c2f6052d6aa&pli=1

    が参考になると思います。

    簡単にまとめると、自分が作ったGAEアプリケーションに高負荷試験を仕掛けたけど、全然スケールしないじゃないか、と言っている人に対して、「GAEは通常の利用のされ方に関してスケールするようにできている」として、少しずつ負荷を上げていかないとだめだよーんという説明が書かれています。

    また、

    On 6月18日, 午後12:19, Atusi Nakamura wrote:
    > ある時点で、アクセスの急増が予想されるのであれば、1時間以上
    > 前から自分で負荷を与え続けて処理能力を増やしておくと良いかもしれな
    > いと言われました。

    に関してですが、ひとつのソースから負荷を与えつづけても、DOSアタックとして認識されてしまい、処理能力は増えないのではないかという話も書かれています。実際このスレッドの最後の記事は、「ゆっくり負荷を上げているけど、やっぱりだめだよー」という内容になっています。

    # これに関して誰もコメントを付けていませんが。

    --
    toh


    【Google App Engine】 Google App Engineのtips集 このエントリーを含むはてなブックマーク


     すばらしいサイトを発見。一から勉強したい方におすすめ。
     Google App Engineのtips集

    【クラウドコンピューティング】 エンタープライズへの移行シナリオ このエントリーを含むはてなブックマーク


    M先生がメーリングリストで、クラウドの「楽観的」シナリオを述べられている。
    全文いい内容なので転記します。


    議論が、収束しそうですので、問題提起。

    >> ですからエンタープライズ分野の情報サービスの
    >> クラウドへの移行はなかなか進まないんじゃありませんかね?
    >
    > ええ、進まないと思います。エンタープライズは無理でしょう。

    本当でしょうか?

    僕は、クラウドの本当のインパクトは、エンタープライズがパブリック・クラウ
    ドを使い始めたときに起きると思っています。もちろん、今すぐに、それが起き
    るとは思っていません。来年から、変化が始まるのではないかと。始まりの始ま
    りです。それは、同時に、従来型のシステムの終わりの始まりです。

    もっとも、一気に勝負がつくとも思っていなくて、散発的な前哨戦からはじまっ
    て、いくつかの激しい局地戦があって、戦線が拡大していくというようなイメー
    ジです。基本的には、設備更新のサイクルが一巡する4-5年先、二巡する8-10年
    先が、勝負の節目になるはずです。あるいは、次の15年が必要かもしれません。

    僕らは、実は、同じような経験をしていています。メイン・フレームとUNIXを中
    心としたオープン系のシステムの対抗の歴史が、まさにそうだったと思います。

    今回は、パブリック・クラウドとプライベート・サーバの対抗が、UNIXとメイン
    フレームの対抗と、同じような「タイムスケール」で進むのではという話をして
    みたいと思います。今年の話でも、来年の話でもなく、一定の時間をかけて、し
    かし確実に変化が進むだろうという、「長めの時間軸」での予測です。

    この前「UNIXの思い出とCloud OS」(タイトル勝手に変えられましたが)という
    原稿を書いていたのですが、僕らがUNIXを始めた30年前には、それがエンタープ
    ライズで使えるようになるとは、誰も考えていませんでした。

    それが、約20年前に、Sunが起業し、SybaseやOracleがUNIX上のデータベースを
    商品化します。その少し前に、PCが生まれ、マイクロソフトがPC上のOSで成功を
    収めます。現在のIT業界のメインプレーヤは、この時期に生まれています。彼ら
    の成功の過程は、基本的には、それまでのメインフレームの牙城が崩れる過程と
    表裏一体です。

    もちろんメインフレームは生き残っていますし、COBOLだっていまだに元気で
    す。ただ、それは、残存としてですね。(社会経済的には、こうした残存物を
    「ウクラード」と呼びます) ウクラードは残っているものの、この対抗は、基
    本的には、「一定」の勝負がついたように、僕は思っています。

    エンタープライズのコンピュータといえば、メインフレームしかなかった時代は
    終わりました。といって、メインフレームの旗手だったIBMがいなくなったかと
    いうとそうじゃないですね。それは、IBMが賢明にも、オープンシステムへのレ
    ンジを意識的に広げたからです。もっとも、UNIVACとかHoneywellとか、ちょっ
    と記憶があいまいなのですが)いくつかのメインフレーマは、姿を消しました。
    業界二位だったDECも、なぜか事業に失敗します。大変動があったんです。

    僕は、現在のパブリック・クラウド vs プライベート・サーバの対抗も、同じよ
    うな推移をたどると思っています。20年前のSunやOracleやマイクロソフトに、
    メインフレーマは脅威を感じたでしょうか? 多分、ノーです。15年前はどうで
    しょう? まだ、現在のような流れは明確ではなかったと思います。10年前は、
    前哨戦の時期が終わり、局所的な激戦が戦われます。Internet、Javaが登場し、
    サーバーサイドの流れが強まります。

    大事なことは、攻める側・守る側の立場は、会社レベルで言えば、固定的なもの
    ではないし、当初の戦力の違いは、技術革新によって、新しい兵器が投入される
    ことで、大きく変わります。10年-20年のスパンで考えれば、クラウドでも、同
    じことが、きっと起こります。

    あまり正しい比較ではないのですが、GoogleやAmazonやSalesforceは、当時の新
    興勢力としての、Sun,Oracle,Microsoftに対応するし、従来の立場を転換するこ
    とで、オープン系の勝利に貢献したIBMの役割を、今のマイクロソフトが果たそ
    うとしているように見えます。

    基本的には、システムの変化は、産業循環の長い周期の中で議論しないといけな
    いと思っています。「エンタープライズ分野の情報サービスのクラウドへの移行
    はなかなか進まない」「エンタープライズは無理でしょう。」というのは、現状
    の認識としては、正しいでしょう。でも、それはショート・レンジの認識です。
    この現状が、この先も続くとは、僕は思っていません。

    むしろ、技術論よりは、営業の立場に立つと、両者の戦いが、どう進んでいくの
    かがよく見えてくると思います。

    現時点では、Amazonを除いては、パブリックなクラウドを利用したシステムの提
    案は、難しいです。売るものがないのですから。ここでは、「エンタープライズ
    は無理」というのは、正しいのです。

    来年は、どうでしょう。ちらほら、商用化されたパブリック・クラウドを部分的
    に利用した提案が、出てくるでしょうね。対抗陣営としては、営業レベルでは、
    「エンタープライズでは無理」というセールス・トークが、重要になります。ク
    ラウドに懐疑的なイデオローグは、今より、重用されるでしょう。多分、大勢と
    しては、そちらが優勢でしょう。

    さ来年は、どうでしょう。きっと、二年もあれば、模様眺めしていたり、パブ
    リック・クラウドを批判していた人たちの一部は、クラウドでもプレゼンスを示
    さなければと考え始めるでしょう。でも、大勢としては、現状維持勢力が強いで
    しょうね。ただ、営業での激しい戦いを反映して、セールスとしては、不安をあ
    おるだけでは営業が出来ないと、価格でも対抗しようとするでしょう。でも、そ
    れは、ボディ・ブロウのように、自分のビジネスにきいてくるはずです。クラウ
    ド側では、その時点での最適な、組み合わせを提案の中心にするようになるで
    しょう。

    まあ、このあたりでやめておきましょう。これぐらいが、僕の一番、「楽観的」
    なシナリオです。

    水曜日, 6月 17, 2009

    【雑記】 JavaがGAEで復権しそうだけどLLの方がいい このエントリーを含むはてなブックマーク


     嬉しいことに、連想配列からXMLに変換するJavaScriptが海外のQ/Aサイトで参照されている。

    www.experts-exchange.com
    abel:
    But this is perhaps simpler: http://www.virtual-tech.net/resources/json2xml.html. It contains a small JavaScript snippet (yes, I know you use Java), that shows how to parse the JSON code into XML. See the source of that page (the popup shows only the output).

    avernet:
    2) http://www.virtual-tech.net/resources/json2xml.html

    This is some very simple (= good!) code that uses Prototype. I don't fancy Prototype, but maybe will run with the idea. (I would have preferred a more robust, server-side solution to this.)


     日本語なのによく見つけたなあ、というのはさておき、これがJavaだったら、こんなふうに海外で見つけられることもなかっただろうとも思う。そもそもシンプルに書けないしね。まあ、気持ちの問題が大だけど。

    以下は下請けでいやな思いをしたときの愚痴メモ。


     Javaには、短く、エレガントに書く発想というか、そういう文化はないよね。単純に書くとチープだと思われてバカにされるし、むしろ不必要なスレッド処理とかやって無駄に長い方がすげーと思われるでしょ。だって、このプロジェクトなんてステップ単価ですよ。正規表現で書いた部分まで書き直させられたら、心折れるっつーの。


     一方、LLの代表であるRubyはというと、(ThoughtWorksでのRuby あおうさ@日記より)

     我々の強みは、典型的なIT企業では引き込めないような非常に有能な人たちを雇用しているという点だ。 Rubyには、あまり有能ではない開発者をエラーから守るよりも、 有能な開発者がさらにうまく物事を成し遂げられる環境のほうがよいという哲学がある。 Rubyのような環境を使うことで、我々の開発者たちは真の価値を生み出す能力を与えられているのである。


     これ、すっごくわかる。

     私の感覚では、アセンブラ<<C<Java<<LL、の順で、生産性は断然LLの勝ちです。それから生産性以上に大事なのは、rubyのような「真の価値を生み出す」こと。先の私のJavaSciptコードは、たった14行しかないんですよ。たぶん、rubyも同じように書けると思うし、そう書きたくなるような文化なわけでしょ。こないだの、Tokyo Cloud Developers Meetup で「何でJavaなんか使うんですか」と聞いていた方がおられたけど、それは、とても正しい質問。私もああ、GAEはやっぱりPythonがいいかもね、と思うときがある。

     Javaは昔から悪運が強くて、AppletでダメになりかけたときにServletで復活した。元々生産性が低かったんだけど、Eclipseのおかげでなんとか開発できるようになった。StrutsやDIで辟易してWeb2.0全盛期にLLに走った人も多かった。Javaは言語仕様的にダメダメで、もう寿命は尽きているんだけど、今はGAEとAndroidで延命しそうな感じになっている。

     え?何で私がJavaやってるかって?そりゃ、ビジネスのためですよ。ビジネス。というのは冗談で、強いて言えば、パフォーマンスとセキュリティだね。少なくとも開発生産性ではない、絶対に。そのあたりはGoogleも同じ考えだと思うよ。



    <関連>
    最も初心者向けの言語はJava or PHP?
    Javaが本領を発揮する場面とは
    僕とTAKE-DOS、ちょっとだけJava批判

    火曜日, 6月 16, 2009

    【クラウドコンピューティング】 パブリッククラウドとビジネスモデル このエントリーを含むはてなブックマーク


     昨日、クラウド研究会のメーリングリストのなかで面白い議論を見つけた。これは、public cloudとprivate cloudの違いという感じの話から始まった。私は、クラウドのバズワード化に拍車をかけている現状、つまり、ITベンダー各社がこぞってクラウド対応を発表していて、何が本質で、何をクラウドと呼べばいいのか分からなくなってきた状態を整理するという意味で面白いと思った。(でも最後は不都合があって、もうしないと宣言されてしまったのだが・・)

    技術要素について:M先生

     パブリック・クラウドには、これまでのサーバ技術にはなかった、次のような新しい技術的な内実があります。

    ・Scalability
    ・Availability
    ・Databaseとの一体化
    ・BASE Transaction
    ・Fabricを形成する能力

    ビジネスモデル、ユーティリティーコンピューティングについて:Sさん


     元IBMのS氏は、「H/Wベンダー、S/Wベンダーそして色々な思惑のある連中が共通する利益追求目的で唱えたのがプライベート・クラウドでしょう」と言い切る。

     BlueWorksの発表も、結局は高価なソフトウェアを購入してもらうためのBaitでしか有り得ないわけですが、OSSで広がった安価なソフトウェア(でも大丈夫なんだという)の現実は、クラウドの登場によって、ハードもソフトも買わなくていいんだという、さらに過激な世界が、ユーザーに受け入れられていくというインパクトです。
     ミドルウェア・ベンダーのビジネス・モデルは、高機能なミドルを開発し、高価な値付けで売って開発費を回収し、利益も出すというものですが、そのライセンス販売の仕組みに大きな影響を与えていくのがAmazonであり、Googleです。この二つを、AmazonやGoogleはIntegrateして、別の解決策があるよ、と示したわけです。

    ビジネスモデル、コストについて:私


     publicクラウドを見たときに、敢えて技術要素には触れないで強調すべきことがあるとしたら、次の2点になるんじゃないかと。

    1) ネット上でビジネスが完結している点。クレジットカードさえあれば、誰でもすぐにでも利用できる。

     これは私たちも目指すところなんですが、すべて自動化するという、ネットをこれほど活用するビジネスのやりかたには、ほんと驚かされます。営業がいるわけでもなく、SEが使い方をコーチするわけでもなく、エンドユーザ(今のところ開発者主体ではあるけれども)が勝手に申し込んで自由に使えるような環境を提供している。ネットのもつポテンシャルの大きさという意味で、私自身、まだ認識が甘いのかなあと、思い知らされますね。

    2) べらぼうに安い点

     宣伝で申し訳ありません。先日、弊社のホームページ(http://www.virtual-tech.net/)をGAEに立てたのですが、その際にかかった費用は、独自ドメイン代の950円/年だけでした。Blogの広告収入が少なく見積もって3000円/年はありますから、なんと黒字になっちゃうんです。
     もちろん、制作費はかかりますよ。でも、全部手作りなので人件費で換算して数万円ぐらいです。安いレンタルサーバに置くより速いし、なんといってもタダなのはいいですね。零細企業の私たちにピッタリのモデルです。なんでこんなに安くできるのか不思議なんですが、一番大きな理由が、たぶん、本業で余ったリソースを提供しているからなんだろうと私は考えています。Googleの本業は検索エンジンでAmazonはECですよね。Googleはコンテナ型データセンターでPUEが1.21なんていう話もクラウド大全にはありましたけど、電力効率なども含めた低い運用コスト以上に、余ったリソースの貸し出しは大きい要素なんだろうと。こんな真似ができるところって限られていますよね。


     実は、1)については、私自身、重要性に気づいたのは、つい最近のことである。きっかけは、先週の金曜日に、Androidをもって、ある社長(ブログ)を尋ねていったときのこと。今後のビジネスモデルについて提案させていただいたのだが、一言で「甘い」と一蹴されてしまったのだ。たしかになんとなく自分でも他力本願というか、ライセンシーをお願いされた方も、ビジネスが付いてこなきゃ意味がないわけで、普通に営業をやって、仕事を請け負う従来のビジネスモデルとなんら変わりのない。営業やサポートの人数も限られている。そもそも、「どうやって売っていくんだ」ということである。

     ところが、もし、ネット上でビジネスが完結できれば、この問題は解決する。アフィリエイトだってあるし、PayPalだってある。PayPal は、個人(サービス提供者)でも契約や長期間のコミットを必要とせず、利用した分だけ支払う手頃な額の取引手数料を支払うだけでクレジットカード支払を受け入れることができる。自分自身、Blogをやって、ネットのもつポテンシャルの大きさを感じているにもかかわらず、このビジネスモデルを何でやろうとしないのか・・・・、いろいろ反省しなきゃと思った次第である。まあ、AmazonやGoogleのようにやれると思い込んでいる自分に、今度は「信用」という厚い壁に潰されることになるだろうと、思わんでもないが。

    <追記> Fさんが紹介してくれた翻訳版、これいいですね。=>Above the Clouds: A Berkeley View of Cloud Computing

    土曜日, 6月 13, 2009

    【お知らせ】 バーチャルテクノロジーはお蔭様で6周年 このエントリーを含むはてなブックマーク


     2003年6月13日に生まれた弊社は今年で6周年を迎えました。これまでなんとかやってこられたのも、お客様、パートナー様、社員の皆さんが支えてくれたおかげです。心から感謝申し上げます。
     さて、6周年を記念して、ホームページとBlogをリニューアルをいたしました。今後とも、バーチャルテクノロジーをよろしくお願い致します。

    月曜日, 6月 01, 2009

    【Google App Engine】 JDOから直接SOAP、ATOM。それからDeep Copy このエントリーを含むはてなブックマーク


     Reflexを使ってJDOからSOAPに変換するサンプルとATOMに変換するサンプルを作ってみた。これらは Reflex Core Samples(2005年作成)をGAEに移植したものだ。

    reflexworks




     O/Rマッパに慣れている方は不思議に思うかもしれないが、ReflexではEntityの構造がXMLの構造になるため、DXOのような詰め替えが必要なく、またマッピング用定義ファイル等も必要ない。
     下図は実際の保存イメージである。SOAPやATOMのデータはReflexによりJDO Entityに変換され、1Entityが1TableのようなイメージでDatastoreに保存される。Entityはオブジェクトの形で保存されるが、各Entityは別々に管理されており、Tableのようにカラムとバリューによる表のイメージとなっていることがわかる。Entityどうしの関係は別途Keyによって紐ずけられているので別々に管理されていても大丈夫なのである。



    Reflex Core Samplesを移植するにあたって、Reflex Core本体にも手を入れたので補足したいと思う。

    com.google.appengine.api.datastore.Text型をサポート


     Datastoreに保存する際に、String型では500文字以上扱えないため、大きなサイズのものを扱う場合はText型を使用する必要がある。JDOにStringで定義していたプロパティをTextにすると大きなサイズでも保存できるようになる。ただしIndexは付かないので注意が必要である。サンプルではAtomのContentでTextを使用している。

    同じスキーマのEntityを異なるものとして扱う

     実際に、ATOM Sampleを見ていただくとわかるが、Feed要素の子要素にはAuthorとEntryがあり、かつ、Entryの子要素にも同じスキーマのAuthorがある。AuthorはFeed要素の子要素、つまり、「1対多」の関係が既に定義されているので、Entry要素の子要素としては定義することができない。そこで、複数のパッケージ名を同じ名前空間に指定できるようにして、同じクラス名であってもパッケージ名が異なれば違う要素として扱えるようにした。例えば、List<foo>.SampleとList<bar>.Sampleは異なるEntityとして区別される。こうすることで、Datastoreには異なるEntityとして保存されるようになる。これは同じスキーマのテーブルを2つ持つことと同じような意味である。
     
    EntityのDeep Copy

    上記のように同じスキーマの複数のEntityがあると、すべてのプロパティをコピーできるようなDeep Copy機能が欲しくなる。
     同じスキーマであれば以下のようにすることでDeep Copyが簡単にできる。


    // entryのAuthorをfeedのAuthorにDeepCopy
    IResourceMapper mapper = new ResourceMapper("jp.reflexworks.atom.entry");
    IResourceMapper mapper2 = new ResourceMapper("jp.reflexworks.atom.feed");
    jp.reflexworks.atom.feed.Author author3 = (jp.reflexworks.atom.feed.Author) mapper2.fromXML(mapper.toXML(author));



    <関連>

    Entityとトランザクション
    JDOから直接JSON、XML
    AXIS2のデータバインディング能力
    AJAX CRUDサンプルとJDO代替ライブラリ
    Pagingをどうやって実現するか
    RESTfulアプリのCRUDサンプル -Servlet編-
    RESTfulアプリのCRUDサンプル -Modeling編-

     
    © 2006-2015 Virtual Technology
    当サイトではGoogle Analyticsを使ってウェブサイトのトラフィック情報を収集しています。詳しくは、プライバシーポリシーを参照してください。