スマート クライアントによる状態管理
Chris Sells
May 20, 2002 日本語版最終更新日 2002 年 7 月 22 日
筆者の新しい MSDN Online コラムの第 1 回目へようこそ。このコラムのタイトルから、2 つのことがすぐにわかると思います。これは Windows フォームに関するコラムであり、筆者はこのテクノロジをかなり好きである、ということです。もちろん、どのようなテクノロジにも言えることですが、Windows フォームには優れた点と「改善の余地」のある点の両方があります。このコラムでは、Microsoft .NET のさまざまな長所と短所を、スタンドアロン アプリケーションと、クライアント サーバー アプリケーションおよび n 層アプリケーションのクライアント サイドの作成に関係する面から取り上げていきます。これにはフォーム、コントロール、アプリケーション、マルチスレッディング、データ連結、配置、セキュリティ、描画、スクリプティング、そしてその他の、インターネットとイントラネット上のあらゆる世代の分散型システムに関わるトピックが含まれます。このコラムで取り上げて欲しい具体的な話題や、答えの欲しい質問がある方は、ぜひ csells@sellsbrothers.com (英語で)にメールでお知らせください。
最初のトピックに入る前に、筆者がなぜ Windows フォームをこれほど気に入っているのかを説明しておきましょう。そもそも、Windows フォーム パッケージはすでにいくつも存在しているのであり、この新しいパッケージについて改めて何か言うべきことはあるのでしょうか。 後に述べるように、実は言うべきことはたくさんあるのですが、それを実際に口にしている人はほとんどいません。誰もが Web アプリケーションばかりに注目しているようなのです。Web アプリケーションは、守備範囲を広げるという点では素晴らしい手段ですが、Windows フォームで実現可能なリッチなクライアントの貧弱なまねごとに過ぎないというケースも少なくありません。Web バージョンの電子メール クライアントと、それに対応する Microsoft Windows® バージョンの電子メール クライアントでのユーザー エクスペリエンスの違いを考えてみてください。どちらの方が使いやすいでしょうか。 どちらの方が高機能でしょうか。 どちらの方が高速でしょうか。 日常的に使用しているのはどちらですか。 もちろん、Web アプリケーションは複数のプラットフォーム上の複数のブラウザに対応することができます (HTML、DHTML、CSS、JScript®、プラグイン、ActiveX® などをうまく組み合わせて提供できればの話ですが)。しかし、ターゲット クライアントに .NET がインストールされている場合には、Windows フォームは十分に検討に値する選択肢となります。それだけでなく、Windows フォーム アプリケーションは通常、「Winodws フォームという驚異の世界」 に足を踏み入れる第一歩となる今回の記事で解説するように、ごく簡単に開発できるのです。
クライアントと状態
ブラウザの動作が安定し、HTML DOM をターゲットにプログラミングを行って、高機能なクライアントを作成できるようになるにつれ、HTML はグラフィカル ユーザー インターフェイス (GUI) の作成には適していても、それ以外にはほとんど得意な分野がないことがわかってきました。喧伝された「シングルページ Web アプリケーション」を構築するために必要な、アプリケーション フレームワーク的な機能が存在しないためです。次にアプリケーションを実行したときに同じユーザー設定を適用するといった簡単な作業にも、クライアント側には cookie や JScript といった、無効化されていることの多い機能が必要で、サーバー側では複雑な HTML 生成が必要となります。このため、ほとんどの Web サイトは、最大公約数のアプローチをとらざるをえませんでした。メニュー バー、ツールバー、標準化されたインターフェイス、キーボード ショートカットといった機能は諦めざるをえず、手作りのグラフィックス、配色、そして広告など、複数のブラウザとプラットフォームで安定して動作するということのみを狙って作られた見慣れない GUI が採用されるようになりました。
「シン クライアント」 は、ここから生まれました。このようなクライアントは、手軽なインストール モデルを使って、任意のマシンに個別に導入することができます。これは、クライアント側での作業を可能な限り減らし、興味深いすべての機能をサーバー側に任せるプログラミング モデルによって実現されたものです。ASP.NET のような第 3 世代のテクノロジは、この方針の最先端に位置しています。例として、図 1 に示す単純な単位変換アプリケーションを考えてみましょう。

図 1. ASP.NET による単位変換 Web アプリケーション
この Web アプリケーションは、いくつかのカテゴリの単位変換を行います。たとえば、温度や体積の変換が可能で、各カテゴリ内でも摂氏、絶対温度、華氏などの複数の単位をサポートしています。これらのカテゴリと単位は、このアプリケーションがサポートしている変換のリストを提供し、要求があった場合に実際に変換を行う Web サービスが提供しています。ユーザーが別のカテゴリを選択すると、そのカテゴリ内の変換可能な単位のセットが表示されます。この UI の再構成は、次の 2 つの方法で実装できます。
- すべての変換カテゴリと単位をシン クライアントに送信し、ユーザーがカテゴリを切り替えたときに、JScript を使って単位を変更する。
- ユーザーがカテゴリを切り替えるたびにサーバーに接続し、ユーザーの選択に合わせてサーバー側で UI を再生成する。
前者の方法は、ユーザーに対する応答性という点では明らかに優れていますが、複数の種類のブラウザで JScript を正常に動作させるためのプログラミングが難しくなります。この種のクライアント サイド スクリプティング モデルを扱うための優れたツールセットが存在しないということが、さらに問題を複雑にしています。一方 Visual Studio .NET では、HTML の生成と UI イベントの処理をサーバー側に任せる Web フォームの使用が推奨されています。サーバー側では真のクロスブラウザの HTML をインテリジェントに生成することができますし、開発者は C# と Visual Basic® .NET のどちらを使ってもアプリケーションを実装できるという利点があります。次に示すコード例は、この Web アプリケーションを、ASP.NET のサーバー サイド UI モデルを使って実装する方法を示しています。
まず、Web フォームのコードを見てみましょう。
public class WebForm1 {
protected System.Web.UI.WebControls.DropDownList _categoryList;
protected System.Web.UI.WebControls.DropDownList _fromList;
protected System.Web.UI.WebControls.DropDownList _toList;
protected System.Web.UI.WebControls.TextBox _from;
protected System.Web.UI.WebControls.TextBox _to;
protected System.Web.UI.WebControls.Button _convert;
…
void FillCategories() {
foreach( Conversion conversion in GetConversions() ) {
if( _categoryList.Items.FindByText(conversion.Category)
!= null ) continue;
_categoryList.Items.Add(conversion.Category);
}
}
void FillMeasures() {
// カテゴリが切り替えられたときに From と To のリストを更新する
string category = _categoryList.SelectedItem.Text;
_fromList.Items.Clear();
_toList.Items.Clear();
foreach( Conversion conversion in GetConversions() ) {
if( String.Compare(conversion.Category, category, true)
!= 0 ) continue;
_fromList.Items.Add(conversion.Measure);
_toList.Items.Add(conversion.Measure);
}
_fromList.SelectedIndex = 0;
_toList.SelectedIndex = 1;
}
void Page_Load(object sender, EventArgs e) {
if( !IsPostBack ) {
FillCategories();
FillMeasures();
_to.Text = "";
}
}
void _convert_Click(object sender, EventArgs e) {
Converter converter = new Converter();
_to.Text = converter.Convert(_categoryList.SelectedItem.Text,
_fromList.SelectedItem.Text, double.Parse(_from.Text),
_toList.SelectedItem.Text).ToString();
}
void _categoryList_SelectedIndexChanged(object sender,
EventArgs e) {
FillMeasures();
_to.Text = "";
}
}
ドロップダウン リストが変更されるたびにラウンドトリップが起こるという事実にとりあえず目をつぶれば、このコードからは、Web フォームが Windows フォームのようなクライアント サイド テクノロジからいかに影響を受けているかがわかります。Web アプリケーション内のどのページについても、単位変換プログラムの観点からは動的に再生成する必要がない場合でも、ユーザーがサーバーに対して要求した UI のすべての要素をサーバー側で生成する必要があります。クライアント サイドのブラウザ キャッシュがラウンドトリップを減らすのに役立つのは確かですが、コンテンツが現在のデータ、ユーザ設定、および (または) 現在のセッション状態に基づいて動的に生成される場合にはその効果を期待できません。そして、現在のデータ (われわれの例では、使用可能な変換単位のリスト) は、このアプリケーションがサーバーに再接続しなくてはならないそもそもの理由なのです。Web アプリケーションを単にユーザーのハード ドライブにコピーして済ませることをしないのは、集中化された最新のデータ リポジトリを提供することこそ Web アプリケーションの目的に他ならないからです。
一方、UI の既定となるユーザーのお気に入りの単位や、複数の部分から成るフォームでのユーザーの現在位置を示すセッション状態といったユーザー設定は、クライアント側に保存した方がいいように思えるかもしれません。残念ながら、このデータはやはり UI の生成に使用されるので、サーバー上に持っておく必要があります。ただし、これでクライアントの責任が免除されるというわけでもありません。HTTP は、クライアントがページを要求するたびにサーバーへの新しい接続を確立するコネクションレス型のプロトコルなので、サーバーから見ると、各接続を個々のクライアントに、したがってクライアントのセッション状態に関連付ける手段はありません。このため、クライアントはサーバーに対して要求を行うたびに、hidden のフォーム フォールド、cookie、セッション固有の URL (Amazon.com の長い数字の詰まったアドレスを思い出してください) などのメカニズムを通して一意の識別子を送信する必要があります。この一意の ID は、メモリまたはデータベースからセッション状態を取り出すために使用されます。この方法はうまく機能し、世界中の無数の Web アプリケーションで使用されていますが、サーバー サイドにキャッシングされるデータをどれだけの期間保持しておくべきかという問題は残ります。サーバーは、ユーザーが別の URL にナビゲートした、またはブラウザを閉じたので、キャッシュをクリアしてもよいという通知を受け取ることができません。そのためサーバーは、キャッシングされたデータにタイムアウトを割り当てておき、無礼なクライアントがさよならも言わずに切断したときに、リソースを他のクライアントのために解放できるようにしています。
残念ながら、この「状態」に関する処理は、最も単純なものを除けばあらゆる Web アプリケーションで必要となります。これは主な機能が Web サービスによって提供される場合も同様です。Web サービスは UI の作業は行わないからです。優れた Web サービスは、アトミックな機能への完全にステートレスなアクセスを提供します。UI の生成を、ユーザーとの実際の対話から分離することの必要性から、通常は図 2 に示すような典型的な 4 層 Web アプリケーション アーキテクチャが生まれます。

図 2. 典型的な Web アプリケーション アーキテクチャ
リッチ クライアントと状態
その一方で、ユーザーのマシンに完全にインストールされるスタンドアロン アプリケーションであるリッチ クライアントは、ユーザー設定とセッション状態を問題なく処理することができます。実際、Windows フォーム アプリケーションでは、状態の管理は、シン クライアントのケースとは異なり、機能を実装する過程で自動的に行われます。すべてのロジックとデータがクライアント上に存在するので、UI を作成するためにラウンドトリップは必要とされません。また、セッション状態のタイムアウトの問題もありません。クライアントは自分の実行がどこで終了したかを正確に知ることができるため、次のセッションのために状態をキャッシングし、クライアント マシンにリソースを解放させることができます。もちろんリッチ クライアントは、図 3 に示すように、Web アプリケーションには望めないオペレーティング システム固有のすべての利点を活かすことができます。

図 3. 単位変換の Windows フォーム アプリケーション
Windows フォームでの実装は ASP.NET の実装とよく似ていますが、UI を生成するためのポストバック、アプリケーション状態、またはサーバーへのラウンドトリップを気にする必要がないという点が異なっています。もちろん、スタンドアロンのリッチ クライアントには、Web アプリケーションのように、サーバーに置かれた中央の最新データに手軽にはアクセスできないという明らかな短所があります。最新のデータを手に入れるためには、アップデート バージョンをインストールする必要があります。まさにこのような状況において、Windows フォームと Web サービスはお互いを補い合う完璧なペアとなります。
スマート クライアントと状態
Windows フォームのシック アプリケーションの利点 (リッチな UI と単純化された状態管理など) を、Web シン アプリケーション (Web 経由での配置やサーバー上のデータとサービスへのアクセスなど) と組み合わせることで、.NET コミュニティで言うところのスマート クライアントを実現することができます。スマート クライアントは、クライアント サイドの実装では Windows フォームを使用し (オプションとして Web 経由でオン デマンドでダウンロードされます)、サーバー サイドの実装としてバックエンドの Web サービスを組み合わせるという特徴を持っています。優れた Web サービスは本質的にステートレスで、UI と状態管理の仕事はすべてクライアントに任せているので、典型的な Web アプリケーションに必要となる、UI の生成と状態の管理を行うハイブリッド層は存在しません。スマート クライアント アーキテクチャは、Web アプリケーション アーキテクチャから、図 4 に示すようなはるかに単純な 3 層のアーキテクチャに進化しています。

図 4. 典型的なスマート クライアント アーキテクチャ
もちろん、Web アプリケーションがリッチ クライアントよりも優れている点の 1 つは、UI をサーバー側で生成しているため、複数のマシンで単純なログオンを通してユーザー設定を統一することができ、ユーザーがどのマシンを使用しても同じカスタマイズされた UI を使用できるということです。しかし、スマート クライアントが、ユーザー設定を個々のマシンにキャッシングしなくてはならないという理由はありません。MSN® Instant Messenger は、このテクニックを使っている典型的な例です。連絡先は個々のユーザー マシンではなく MSN Instant Messenger サーバーに格納されているため、ユーザーがサービスにログインすると、ユーザーの設定はリアルタイムでダウンロードされます。このため、ユーザーは自分が使用するすべてのマシンで Instant Messenger の設定を繰り返す必要がなくなります。異なるマシン間でのユーザー設定の共有は、Web サービスの便利な用途の 1 つです。
要約
真のスタンドアロン アプリケーションは絶滅しつつあります。ユーザーは、Web アプリケーションの利点と、オペレーティング システムがサポートしている優れた UI 機能を組み合わせて使用したいと考えています。機能のみを提供し、UI は提供しない Web サービスを、UI とセッション状態を管理する Windows フォーム クライアントと組み合わせることで、.NET 対応ユーザーのための完璧なハイブリッドを構築することができます。
関連情報
Chris Sells は、.NET と COM での分散アプリケーションを専門とする独立コンサルタントで、DevelopMentor のインストラクタでもあります。現在、ATL7 に合わせて改訂作業が行われている『ATL Internals』を含む数冊の著作があります。また、Addison-Wesley から出版される『Essential Windows Forms』と、O'Reilly から出版される『Mastering Visual Studio .NET』も執筆中です。Chris は、余暇の時間を利用して Web Services DevCon のホスティングを行い、Genghis source-available プロジェクトを統括しています。Chris とその各種のプロジェクトの詳細については、http://www.sellsbrothers.com を参照してください。
|