火曜日, 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が真似しているといわれないようにしないといけないなあとは思う。

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