[2008 年 7 月号] |
[技術講座]
Happy Squeaking!! 以来、およそ 10 年ぶりの登場となります。 梅澤です。 この連載では Web アプリケーションフレームワーク Seaside を扱っていきます。 メジャーな Web アプリフレームワークには Struts や Ruby on Rails などがありますが、Seaside はそうしたものとはかなり異なる考え方で作られています。 もう Web アプリフレームワークは見飽きたという人にとっても、きっと新鮮な驚きを与えてくれるものと思います。
連載は 6 回になる予定です。 少し長丁場になりますが、おつきあい下さい。
Seaside のオリジナルの開発者 Avi Bryant はこんな事を言っています(抄訳1)。
長年にわたって Web の世界では開発のためのベストプラクティスが蓄積されてきた。出来る限り状態を保持しない注意深く吟味された意味のある URL を使うモデルと表示を分離するためにテンプレートを用いる等である。
Seaside はこうしたルールを全て破った Web アプリケーションフレームワークだ。 Web 開発でこれまで叡智とされてきたことを放棄してみると何が得られるのか? 実に多くのことが、得られたのだ。--Avi Bryant
つまり、Seaside では今まで Web 系でお約束とされてきたことに反する以下のような特徴を持ちます。
なんだかめちゃくちゃのようですが、意味もなく反逆しているわけではありません。 これにより、隅から隅まで、徹底してオブジェクト指向の Web アプリフレームワークを実現しています。
一般的な Web アプリフレームワークは、だいぶ洗練されてきているものの、まだまだ手続き指向であるものが多いと言えます。 オブジェクト指向でプログラミングというよりは、フレームワークが用意する複雑な設定ファイルをいろいろといじるというものが大半です。 Hello, World! と出したいだけなのに、何個も設定ファイルを書かされた経験が皆さんにもきっとあることでしょう。
また、Web アプリフレームワークでよく言われる「MVC アーキテクチャ」というものも、なかなかのくせ者です。 MVC などといって聞こえは良いものの、単に様々なファイルがモデルとビューとコントローラのディレクトリに分かれているのみで、それぞれの連携は今ひとつというものがほとんどだからです。 モデル・ビュー・コントローラのそれぞれが、インテリジェントな存在(オブジェクト)として相互作用するのが本来の MVC です。 しかし Web での MVC は、手続きコード(コントローラと呼ばれています)が、データ構造(モデルと呼ばれています)を取り出して、出力テンプレート(ビューと呼ばれています)に流し込むものというものにあふれています。 この場合アクティブな存在はコントローラという手続きコードだけです。
この Web 系の MVC で開発するには、文字列の名前を間違えないようにすることが重要です。 互いを連携させるためには、テンプレートやモデルのフィールド名や、それぞれのファイル名などを注意深く合わせる必要があります。 ちょっとした変更においても、たくさんのファイルを編集しなければならない仕組みというのは、本当に便利なのでしょうか。
Seaside は、Web でゆがめられてしまった MVC ではなく、本物のオブジェクト指向による MVC を実現しています。 開発者は通常ファイルや HTML ページといったものを意識しません。 もっと上位のコンポーネントという単位を扱います。 通常のオブジェクト指向プログラミング (Smalltalk) で Web アプリの開発を行えるようになっており、当然ながら継承や委譲も行えます。 あたかもオブジェクト指向の GUI プログラミングをしているかのように、サーバサイドの Web プログラミングができる、それが Seaside です。
*1 OSCON 2006にて
コンセプトの紹介はこのくらいにします。 何はともあれ、実際に入手して試してみることにしましょう。 非常に導入がしやすいということも Seaside の長所の一つです。
Seaside の本家サイトは https://www.seaside.st になります。 ここから入手することももちろん可能ですが、日本語パッチ適用の作業を行わなければなりません。 もっとも簡単なのは SeasideJOnePlus を使うことです。 これは、日本人有志(私です)の手で行われた All-in-one パッケージで、上記の対応に加え、日本語の説明資料やサンプルコードなども同梱されたものとなっています。
サイトは下記になります。
SeasideJOnePlus
執筆時点では 2008/06/20 版が最新になっています。 Zip ファイルになっているのでダウンロードして展開しましょう。 インストールはこれで終わりです。
SeasideJOnePlus には、Windows、Macintosh、Linux 用の起動用のスクリプトがそれぞれ用意されています。 Windows であれば win_seaside.bat をダブルクリックすれば Seaside がスタートします。
起動すると以下のような画面が立ち上がります。
右の方に出ている小さな窓が Seaside のサーバオブジェクトの「インスペクタ」です。 Seaside がポート番号 9090 で動いているということがわかります。
Seaside は Smalltalk で動いています2ので、開発環境と実行環境が一体になっています。 別途 IDE などを入手・インストールしなくとも、開発のためのパワフルなツールを最初から使うことができます。
開発に使う言語は Smalltalk です。 Seaside では、ページの飾り付けなどで部分的に CSS を使うことはありますが、基本的には隅から隅まで一つの言語で書いていくことができます。
Smalltalk の解説そのものについては、本連載では行いません。 かいつまんで言うと Ruby のようなダイナミックな特徴を持つオブジェクト指向言語です。 文法は非常に簡潔で、すぐに習得することができます。 まずは「早わかり Smalltalk」を見てみるのが良いでしょう。 その他、より詳しい参考資料については末尾に載せておきました。
*2 Seaside はさまざまな Smalltalk で動作します。本連載では Squeak Smalltalk 版の Seaside を扱っています。
では、早速 Seaside のサンプルアプリケーションにアクセスしてみましょう。 URLは下記のようになります。
https://localhost:9090/seaside/
アプリケーションのリストが表示されます。
examples というリンクがありますので、それをクリックし、更に counter というリンクをたどってみましょう。
以下のような画面になります。
非常に殺風景なアプリケーションですが、Seaside の特徴をよく表したものにもなっています。 ++ のリンクを 5 回ほどクリックしてみましょう。
ここであえて -- のリンクでなく、ブラウザの Back ボタンを使って戻ってみましょう。 3 まで戻ります。
さて、このときに、Web ブラウザ側とサーバ (Seaside) 側で何が起こっているでしょうか。 Back ボタンで戻った場合、単にブラウザのキャッシュを見ることになるので、HTTP による通信は発生しません。 よって、サーバ側は 3 に戻されたということを知らず、カウンタの値は 5 のままのはずです。 ここでもう一度 ++ をクリックすると、はたしてカウンタはどうなるでしょう。
6 になると思いきや、問題なく 4 になります。 不思議ですね。 これが Seaside の大きな特徴の一つ「状態の保持」になります。
もともと Web アプリケーションは、CGI から始まっています。 つまりブラウザからのリクエストに応じて、何らかの小さなスクリプトを起動し、結果を HTML にして返すという動きが基本です。 プログラムは一つのリクエストのたびに起動してすぐに終了することになるため、状態を持ちません。
検索結果を返すだけといった、一過性の処理の場合は、こうした動きでかまわないのですが、最近は Web アプリケーションもかなり複雑になってきています。 ショッピングカートに見られるように、ユーザが複数のページを行き来することもあります。 このような場合にも、あくまでユーザからは一つのアプリケーションを立ち上げているように見えなければなりません。
こうした同一ユーザからの複数アクセスをまとめるために、セッション ID というものがよく使われます。 プログラムの状態はリクエストの度に破棄されますが、ID をキーにして、DB にユーザごとの状態を保存しておきます。 ID を URL や Cookie に埋め込んでおくことで、直前のリクエストの状態を DB から復元し、バラバラのリクエストを一連のものとして扱うことができるのです。
Java の Servlet のように、サーバ側でプロセスを常時立ち上げておく形を取る場合には、DB を使わずとも、オンメモリで状態をとっておくことができます。 DB をいちいち参照するよりも、速度的に有利な方式と言えます。 Seaside もオンメモリでセッション情報を保持しています。 セッションの情報は URL に埋め込まれます3。
もういちど、Counter の URL を見てみましょう。
https://localhost:9090/seaside/examples/counter?_s=dprpbMsJoWWmwokI&_k=VatUOsrJ
上記の URL のパラメータとして _s=dprpbMsJoWWmwokI の部分がセッション ID を表しています。 これにより Seaside はユーザを特定しているのです。 ++ や -- をクリックしてもこの ID は変わることがありません。 ブラウザ(やタブ)を閉じるなどして Counter アプリケーションを終了するまで同じ値が使われます。
ブラウザを新規に開き、https://localhost:9090/seaside/examples/counter という具合に URL を指定すると、先ほどとは別のセッション ID が振られるということがわかるでしょう。 (筆者の場合は _s=abDvKApYFhiepEyc となりました)。
ここまでは、極めて普通です。 Seaside でなくともこのような仕組みを持つ Web アプリケーションフレームワークは多くあります。
しかし URL を改めて見ると、_k=VatUOsrJ という箇所があることに気づきます。 ++ や -- をクリックするたびにこの値は変わります。 実はこの ID は「継続 ID」と呼ばれ、ユーザの「動作(アクション)」を特定するために使われています。
例えばユーザが 3 から 4 に移るために ++ を押すという動作があります。 また 4 から 5 に移るという動作もあるでしょう。 これらに ID をつけて管理しているのです。
セッション ID のみの情報では、サーバはユーザの直近のリクエストの値しか保持することができません。 このためブラウザの Back ボタンを押したりすると、ブラウザとサーバ側とでずれが生じることになります。
しかし Seaside ではさらに細かい単位でユーザの状態を管理できます。 Back ボタンで戻ったとしても、ユーザが「3 から 4 へ移る」ための ++ リンクを押せば、その ID によって、Seaside は 3 から 4 へ移るアクションを(直近の状態と関係なく)、もう一度実行することができます。 「ブラウザの Back ボタンで戻らないで下さい」「注文ボタンは一回だけクリックしてください」などいう注意書きは、 Seaside では不要です。 アプリケーションの状態を、ユーザの動作という単位で、逐一管理できるからです。
Seaside は「継続」という仕組みによって、この優れた機能を実現しています。 継続を用いる Web アプリケーションフレームワークには、Seaside だけでなく、Kahua などがあります。 継続そのものの説明は、本連載の範囲を超えてしまいますので、興味のある方は末尾の参考資料をじっくり読んでみると良いでしょう。
もっとも作者の Avi Bryant さんは、Seaside における「継続」の利用をそれほど重要視しているわけではありません。 AJAX など、別の方法によっても、実行段階に基づいてアプリケーションの状態を管理するということは可能だからです。 むしろ Seaside で重要なのは、Web アプリケーションにおいても「できるだけ状態を保持する」というスタンスに立ったことだとしています。 これによって、Web アプリケーションならではの妙な慣例をユーザに押しつけず、普通のアプリケーションのように見せることに成功しています。
*3 設定で Cookie に移すこともできます。
「継続」という仕組みを使うことで、Seaside はユーザから見て自然な姿の Web アプリケーションを提供するということがわかりました。 それでは開発者にとってはどうなのでしょうか。
Seaside のもう一つの魅力は、開発環境が非常に充実しているということです。 Web アプリケーション開発というと、とかく細かなテキストファイルを編集するというファイルベースのものが連想されますが、Seaside の場合は「そこにあるオブジェクトを直接つかむ」タイプの、直感的な開発が可能です。
Counter アプリのページを改めて見ると、下のほうに "New Session" や "Configure" などのリンクがあることがわかります。 これは開発時にのみ表示されるようになっており、Web ブラウザから、開発に便利な各種の機能を使えるようになっています。
新たなセッションでアプリケーションを起動するために使われます。
アプリケーションの設定のために使用します。 アプリケーションが使うライブラリや、モードの設定(開発モードかデプロイモードか)を行うことができます。 詳しくは後の回で扱います。
ハローと呼ばれる枠をコンポーネントの周りに表示します。 コンポーネントがページのどの部分を表示しているかの把握に役立ちます。 またコンポーネントをデバッグするためのツールを呼び出すことができます。(後述)
ページを表示するために行われた処理のプロファイリングをします。 どのメソッドが呼ばれ、どれだけの時間がかかっているかを知ることができます。
サーバ内でどのオブジェクトがどれだけのメモリを占有しているかの確認ができます。
セッションを破棄し、アプリケーションを終了させます。
現在表示しているアプリケーションのページが正しい XHTML であるかどうかを検査します。
では、この中で最もよく使う 3 番目の "Toggle Halos" で、Web ブラウザからどのような開発が行えるのかを確かめることにしましょう。
ハローとは、「後光」のことで、Squeak の Morphic による GUI プログラミングでおなじみの UI です。 オブジェクトの周りに、そのオブジェクトを操作するためのハンドルが取り囲むように表示されるので、このように呼ばれています。
Seaside のハローも Morphic にインスパイアされたものです。 "Toggle Halo" をクリックすると、アイコンつきの枠が表示されるようになります。 (トグルなので再びクリックすると元に戻ります)。
このハローにより、現在のページをどういったコンポーネントが表示しているのかが視覚的にわかります。 カウンタの例では、ハローの左上に WACounter とあります。 これは WACounter (というクラスのインスタンス)が表示を行っているということを示しています。
右上にある "R" と "S" のリンクで、コンポーネントの表示の仕方を変えることができます。 R(endering) がデフォルトとなっており、コンポーネントをそのまま表示している状態です4。 S(tring) をクリックすると、XHTML を直接見ることができます。
*4 R はレンダリングの略です。コンポーネントの表示を Seaside ではレンダリングと呼びます。
ハローの左上部分にあるアイコンは、個々のコンポーネントの状態を見たり編集したりするものになっています。 まずは一番右のスタイルシートエディタを起動してみましょう。
下記のような画面となります。
ここに CSS を書いて "Save" することで、コンポーネントが使うスタイルを設定できます5。
さきほど XHTML を確認したときにカウンタの数字が H1 タグで書かれていたことがわかりましたので、それに対してスタイルを適用してみることにします。
H1 { color: red; }
などとすれば良いでしょう。 書き込んだ後、"Save" し、左上のハローの x (閉じる)ボタンでエディタを閉じます。
コンポーネントにスタイルが無事に適用されました。
*5 スタイルの設定には「ライブラリ」という仕組みを使う方法もあります。後の回で扱います。
それでは次に真ん中のアイコンをクリックしてみることにしましょう。
今度は以下のような画面に切り替わります。
a WACounter となっているのは、WACounter というコンポーネントクラスのインスタンスを見ているからです。 属性(インスタンス変数)として decoration と count を持っているということがわかります。 decoration はとりあえず無視するとして、count の値を書き換えてみることにしましょう。
count を選択し、下のペインに適当な値を書いて、"do it" します。
インスペクタを閉じるとコンポーネントの値が書き換わっていることがわかります。
このようにインスペクタを使えば、コンポーネントの値を読んだり、書き換えたりすることがブラウザ経由で可能になります。
今度は一番右のアイコンをクリックしてみます。
Web ブラウザの中に、Smalltalk のコードブラウザが出現します。
WACounter クラスが最初から選択されています。 下半分に表示されているコードペインを使うと、WACounter クラスの定義やメソッドの内容を書き換えることが可能です。
一番右のリストが、WACounter のメソッド一覧になっています。 increase を選んでみましょう。コードメインを見ると、
increase count := count + 1
となっています。 先ほどインスペクタで見た count の値を 1 だけ増やしているのです。
これを
increase count := count + 2
のように書き換え、"Accept" を押してみましょう。
最初の変更なので、開発者のイニシャルを聞かれます。 自分のイニシャルを適当に入れて下さい。
イニシャルを入力すると、ブラウザに戻ります。 左上のハローの x (閉じる)ボタンでブラウザを閉じると、元の Counter の画面になります。 ++ のリンクをクリックしてみましょう。
サーバ側のコードを書き換えたので、2 ずつ値が増加するようになりました。
ここまでくれば Web ブラウザ上でデバッグといきたいものです。 残念ながら全てを Web ブラウザからというわけにはいきませんが、Seaside は Web ブラウザとサーバ側のデバッガとの連携機能を持っています。
まずは先ほどと同じようにして increase を書き換えます。 今度は数字でなく nil が足されるようにしてしまいます。
increase count := count + nil
Accept したあとで Counter に戻り ++ を押すと、当然ながらエラーが起こります。 Web ブラウザにはエラーが起こるに至ったスタックトレースが表示されます。
スタックトレース上のリンクをたどり、各段階でのオブジェクトの状態を見ることもできますが、Seaside でユニークなのは、上部に表示されている "Debug" リンクです。 クリックしてみましょう。
Web ブラウザ側では何の変化もないように見えますが、サーバ側ではデバッガが立ち上がります。
サーバ側のデバッガでは、スタックトレースのより細かな情報を見ることができます。 なによりこちらのほうが操作しやすいでしょう。 リストを 4 つほど下にたどると、エラーの原因となったメソッドである increase につき当たります。 コードを 1 が足されるように元に戻して、右クリックメニューで"了解"を選び6、左上の"継続"ボタンを押します。
Web ブラウザに戻ると、Counter のアプリケーションが復活していることがわかります。
このように Seaside では、サーバ側はもとより、Web ブラウザも落としたり再読み込みしたりせずに、極めてインタラクティブに開発を進めていくことができます。 設定ファイルベースの開発環境では、ファイルを書き換えて、コンパイルし、デプロイし直してなどの手間がかかるのに対して、Seaside では思考を途切れさせるものが一切ありません。 ノンストップでの Web プログラミングが可能になっています。
*6 Control (Mac の場合は Command ) + s のキーボードショートカットで了解させることもできます。
今回は Seaside のコンセプトの紹介がメインでした。 Web アプリにも関わらず、「そこにあるオブジェクトをつかむ」タイプの開発ができそうだという感触が得られたのではないでしょうか。 次回からはコンポーネントを用いたプログラミングの仕方に入っていきます。 ご期待下さい。
© 2008 Masashi Umezawa |
|