Lift Web フレームワーク :: Lift の概要

Lift は、それぞれ独立したいくつかの要素から構成されています。Lift は、JNDI、JTA、JPA などと同等のものをサポートしています。こうした J/EE の要素を必ずしも使用する必要がないという事実は、Lift の優れたモジュラー設計をよく表しています。

  • ビューに対する Lift のスタンスは、「開発者に決めてもらう」というものです。Lift は、ビューにロジックコードを持ち込むことを一切認めないテンプレート機構をはじめ、Scala コードの実行と Scala の XML リテラルに基づくビュー機構、そして、Scalate (http://scalate.fusesource.org/ を参照) に基づくビュー機構を提供しています。XML テンプレート機構を選択した場合は、ビジネスロジックにどれだけマークアップを採り入れるかを (そうする場合には) 指定します。Lift の XML テンプレートの中では、ビジネスロジックを表現することは一切できません。
  • 「オブジェクト <-> 永続性」に対する Lift のスタンスは、「開発者に決めてもらう」というものです。Lift には、ActiveRecord スタイルのオブジェクトリレーショナルマッパーである Mapper があります。小規模なプロジェクトでは、この Mapper がすべて面倒をみてくれます。Lift は JPA をサポートしています。Lift には、リレーショナルデータベースに加え、NoSQL ストアへのオブジェクトの出し入れをサポートする Record 抽象化があります (Lift には CouchDB と MongoDB のネイティブサポートが含まれていますが、アダプタレイヤは数百行のコードなので、Cassandra など、ほかのデータベースの場合もそれほど苦労せずに使用できるようになるはずです)。基本的に、Lift という Web フレームワークは、オブジェクトがどのようにセッションに具体化されるかは関知しません。さらに、セッションサイクルとリクエストサイクルはオープンなので、リクエスト/レスポンスサイクルにトランザクションフックを挿入することも簡単です。
  • Lift のスタンスは、「サーバーチームは複数の言語を知る必要はなく、1 つの言語を知っていればよい」というものです。これは、構成 (コンフィギュレーション) が Scala を介して行われるという意味です。これは、実際に Java の言語コンストラクトの 40% は XML 構文で実装する必要がなかったということ、そしてそれでも柔軟な構成オプションが作成可能だという意味です。これは、構成データの構文と型をコンパイラがチェックするので、実行時に XML パースの不具合が生じたり、不適切なデータが生成されたりしないという意味です。これは、使用しているライブラリの注釈の細かい点まで理解する IDE を用意する必要がないという意味です。

私は、Lift を書き始める前に、次のような記事を書きました: http://blog.lostlake.org/index.php?/archives/16-Web-Framework-Manifesto.html。Lift はかなりの程度まで、そして私が知っている、ほかのどの Web フレームワークよりも高いレベルで、この記事に書いた目標を満たしています。

Lift はその中核となる部分において、HTTP リクエストをオブジェクトラッパーで包むのではなく、HTTP リクエスト/レスポンスのサイクルを抽象化することを目指しています。これは実質的には、ユーザーが行うほとんどすべてのアクション (フォーム要素のサブミット、Ajax の実行など) が、ブラウザ側の GUID とサーバー側の関数によって表現されることを意味します。GUID が HTTP リクエストの一部として提示されると、指定されたパラメータとともに関数が適用されます (呼び出されます)。GUID は推測が困難で、セッション固有なので、Spring をはじめとするほかの大半の Web フレームワークと比べ、Lift ではリプレイ攻撃やパラメータ改ざん攻撃は困難です。また、開発者は HTTP リクエストのパックやアンパックの処理ではなく、ユーザーのアクションと、ユーザーのアクションに関係するビジネスロジックに集中できるので、開発もより生産的になります。たとえば、Foursquare のフレンドリクエストを受け入れたり拒否したりするためのコードは次のとおりです。

ajaxButton("Accept", () => {request.accept.save; 
                            SetHtml("acceptrejectspan", <span/>}) ++ 
ajaxButton("Reject", () => {request.reject.save; 
                            SetHtml("acceptrejectspan", <span/>})

こんなに簡単に記述できます。friendRequest は、関数が作成されたときのスコープ内にあるので、スコープを過ぎると関数はクローズされます。フレンドリクエストのプライマリキーを公開するといった処理は必要ありません。単にボタンのテキストと、ボタンが押されたときに実行する関数を定義するだけです (ボタンのテキストは、ローカライズしたり、XHTML テンプレートやローカライズしたテンプレートから引き出したりすることができます)。GUID の割り当てをはじめ、Ajax 呼び出しのセットアップ (jQuery または YUI 経由。もちろん自分の好みの JavaScript ライブラリを追加できます)、バックオフ付きでの自動再試行の実行、Ajax リクエストのキューイングによる接続枯渇状態の回避などの処理は、Lift が受け持ちます。

GUID と関数を関連付けて使うという Lift のやり方には、セキュリティも開発者の生産性も大幅にアップするという二重のメリットがあります。GUID -> 関数の関連付けは非常に永続性が高いことがわかっており、通常のフォーム、Ajax、Comet、複数ページから構成されるウィザードなどで、同一のコンストラクトを使用できます。

Lift のもうひとつの中核は、高次元での抽象化をできるだけ長く維持している点にあります。ページ生成側について言えば、これはページを XHTML 要素として構築し、レスポンスをストリーミングする直前まで、このページを XHTML として保持することを意味します。こうすることのメリットは、クロスサイトスクリプティングエラーに対する耐性がある、ページが作成された後に CSS タグをページの頭に、スクリプトをページの最後に移動できる、ターゲットブラウザに応じてページを書き換えることができるなど、たくさんあります。一方、入力側について言えば、URL を書き換えて、パラメータ (クエリパラメータとパスパラメータの両方) を型保証された方法で取り出し、リクエストサイクルの早い時点で、高次元かつセキュリティチェックされたデータを取得することができます。たとえば、次に示すのは REST リクエストの処理の定義方法です。

  serve {
    case "api" :: "user" :: AsUser(user) :: _ XmlGet _ => <b>{user.name}</b>

    case "api" :: "user" :: AsUser(user) :: _ JsonGet _ => JStr(user.name)
  }

Scala 組み込みのパターンマッチングを使って、受信したリクエストを調べ、パスの 3 番目の部分を取り出して、この値に対応する User を取得し、さらにアクセス制御チェック (現在のセッションまたはリクエストは、指定された User レコードにアクセスする権限を持っているかどうかのチェック) も行っています。したがって、User インスタンスがアプリケーションロジックに達する時点で、すでに綿密なチェックが行われていることになります。

上に述べた 2 つの中核となる部分を持つ Lift は、セキュリティの面で非常に高いアドバンテージを持っています。Lift のセキュリティがきわめて高く、しかもそれが本来の機能の邪魔をしていないことは、Yahoo! のセキュリティ対策を担当した Rasmus Lerdorf (http://en.wikipedia.org/wiki/Rasmus_Lerdorf, 日本語) が FourSquare について言った次の言葉からもわかります (FourSquare は Lift の申し子的サイトの 1 つです)。

Four stars to @foursquare - 1st site in a while I have taken a good look at that didn't have a single security issue (that I could find)
 [@foursquare は星 4 つ - 私が調べた中では久しぶりにお目にかかった、セキュリティの問題を (自分の知る限り) 1 つも抱えたことがないサイト]

http://twitter.com/rasmus/status/5929904263

当時、FourSquare にはコード担当のエンジニアが 1 人いて (1 人というのは @harryh が天才だからですが)、その主な仕事というのは、毎週倍々ゲームで増えていくトラフィックに対処しながら、PHP バージョンの FourSquare を書き直すことでした。

セキュリティに関して Lift が力を入れているもうひとつの部分は SiteMap です。SiteMap は、アクセス制御、サイトナビゲーション、そしてメニューが統合されたシステムです。開発者は各ページのアクセス制御ルールを Scala コードで定義します (If(User.loggedIn _) または If(User.superUser _) など)。これらのアクセス制御ルールは、ページのレンダリングが始まる前に適用されます。Spring Security によく似ていますが、異なるのはプロジェクトの始めから含まれていて、アクセス制御がアプリケーションのほかの部分と統合されていることです。このため、URL が代わったり、アクセス制御を計算するメソッドが変わったりしても、XML のセキュリティルールを更新するプロセスは必要ありません。

これまでに説明したことをまとめると、Lift の設計哲学によって、組み込みのアクセス制御のメリット、OWASP の10大セキュリティ脆弱性に対する耐性、高いレベルでの Ajax サポート、そして開発者の生産性向上がもたらされることになります。

しかし、それだけではありません。Lift は最も Comet サポートが優れている Web フレームワークでもあります。Novell が自社の Pulse 製品 (http://www.novell.com/products/pulse/) で Lift を採用したのも、そのためです。Novell は Lift について次のように述べています。

Lift は、開発者がグランドデザインに集中することを可能にするタイプの Web フレームワークである。強力で表現力の高い型付けと、組み込みでの Commet サポートをはじめとするハイレベルな各種機能により、開発者は処理のための処理ではなく、本当にイノベーティブな作業に力を注ぐことができる。Novell Pulse のようなリッチなリアルタイム Web アプリケーションが必要としているのは、バックに Lift のような強力な機能を持つフレームワークである。

Lift は、単なるもうひとつの新しい MVC フレームワークではありません。コアデザインに関して非常に成熟した原則を持ったフレームワークなのです。Lift には、セキュリティと開発者の生産性を向上させるという二重のメリットがあります。Lift は階層的に構築されたフレームワークであり、開発者は Lift を使うことで、自分のニーズに応じて、ビューの生成、永続性など、さまざまなものを適切に選択することができます。

Scala と Lift を使えば、XMLや注釈、その他のイディオムの寄せ集めである Spring を使う場合と比べ、開発者ははるかに心地よく作業することができます。