Brad Olenick 氏は MIX11 で,RIS/JS jQuery プラグインを新たに発表した。RIA DomainService をラップして,イベントや変更追跡 (change tracking),バリデーションなどの機能を追加する プラグイン だ。氏が行った "jQuery によるデータセントリックな N 層アプリケーション構築" という プレゼンテーション では,共有バリデーション(shared validation) やソーティング,フィルタリング,バッファリング,変更追跡などの機能が多数紹介されている。
RIA/JS jQuery プラグインの基本は データソース だ。RIA ドメインサービスを JavaScript オブジェクトのコレクションにリンクするために,データソースを使用しているのだ。コレクションに項目が追加された場合,削除された場合,あるいは個々の項目が更新されたり削除マークされたりした場合には,このデータソースのイベントによって処理が実行される。このモデルはさらに,サーバ側とクライアント側で実行された削除処理を区別する機能も備えている。
データソースはバインドしたコレクションのイベントを監視し,それを自動的に処理する。例えば $.push を使ってコレクションに項目を追加すると,データソースが自動的にサーバへのコールバックを処理する。必要であればデータソースへの変更をバッファリングして,.commitChanges() または .revertChanges() がコールされるまで蓄積することも可能である。
共有バリデーションは,同じバリデーションアクションを行うコードがサーバ側とクライアント側とで別々のものになるという,ありがちなシナリオを回避するために有効な機能だ。プラグインが RIA ドメインサービスのバリデーション属性をシリアライズして,それをクライアントに送信する。この方法により,クライアント側でも同じルールによるバリデーションの実行が可能になる。
私たちは Brad Olenick 氏にコンタクトを取り,これら機能の詳細に関して質問をした –
InfoQ: 共有バリデーションをカスタムバリデータの記述に活用することは可能なのでしょうか?
Brad: ご質問の "カスタムバリデータ" は,「C# で記述され,クライアントへシリアライズ送信されるバリデーションロジック」の意味と考えてよろしいでしょうか。
それについては,いろいろな議論がありました。
基本的には,RIA DomainService に C# で記述されたバリデータの非同期起動を RIA/JS で管理する,という方向で考えています。C# を JavaScript にクロスコンパイルする,という別案には不安があるのです。その大きな理由は,C# の .Net ライブラリメソッド ("Int32.ToString()" のような) を同等の JavaScript に変換しなければならない点にあります。
InfoQ: 今よりも粒度の小さい,例えばイベントレベルの変更などをバッファリング可能にする,という考えはありますか? 例えば insert は即時実行する,update はバッファリングする,というような方法です。
Brad: そうですね,それについても実際に多くの案を考えています。ですが適当なデザインを見つけるだけの時間がないのです。現状では $.dataSource を生成する時に粒度を決めているのですが,ご質問にあるようなシナリオには至っていません。粒度を アプリケーションからコントロール可能な 暗黙的コミットのように,もっと自由度の高い方式を検討しているところです。ここでのシナリオとしては,JS のクリックイベントハンドラで,一連の編集操作を単一トランザクションとしてコミットする必要のある場合です。
RIA/JS のプログラミングモデルは,ある意味で .Net の System.Transaction に似ているかも知れません。グループエディットを適用する $.dataSource に JS アプリが関数を渡すことがありますよね。$.dataSource はこの関数コールの間だけ更新操作をトラッキングして,それからコミットを実行するのです。
現在考えているもうひとつのシナリオは – 先ほどの "例えば ..." の内容かも知れませんが – HTML <form> で複数の RIA/JS エンティティの変更をバッファリングして (先述の "update はバッファリング" にあたります),それを包含する UI で暗黙的なコミット編集を行う ("insert は即時実行" に相当します),というものです。
このシナリオについては,まだ検討中です。今現在でも,別々の $.dataSource インスタンスを使えばこれを実現できます – 一方を <form> に,もう一方を包含する UI に対応させれば。ですが,まだ改良の余地があると思っています。
InfoQ: WCF JQuery は UI コントロールのベースとしても素晴らしいものになりそうですが,そちらの方向で何か期待できるものはありませんか?
Brad: JavaScript と jQuery のコミュニティが望んでいるのは選択肢を持つことです。ですから私は,jQuery UI Grid プロジェクトの一端として jQuery の – データモデル – に力を注いでいます。
jQuery チームが十分に設計されたデータモデルに到達できれば,– 最低でも – jQuery UI コントロールは,RIA/JS にとって非常に有用なものになるでしょう。さらに他の UI や UI コントロール製品についても,jQuery UI と同じようにデータモデルの上にレイヤを置く構成を選択する可能性は十分にあると思います。そうすれば RIA/JS を利用する開発者に対して,この部分に関してより多くの選択肢を提供できることになります。彼らが UI として Wijmo や jQuery Mobile,knockOut.js などを選択できるようになるといいですね。
特に MS 製の UI コントロールについては,WCF RIA と Windows AppFacric の開発者に優れたエンド・ツー・エンド開発エクスペリエンスを提供する,というコンテキストで私たちが考えている選択肢のひとつです。
InfoQ: 今後のリリースで計画されている機能について教えてください。
Brad: WCF RIA サービスの Silverlight クライアントに機能レベルで追いつくまで,RIA/JS の機能構築を継続するつもりです。先ほど話した "カスタムバリデータ" などはその好例ですね。私たちはアプリケーションに対して CUD 以上のフレキシビリティと,独自の起動操作や更新操作のサポートを提供したいと思っています。VS との統合ツールの向上にも投資する予定です。
この件とは別ですが,私たちは RIA サービスを Windows AppFabric のアプリケーションパターンとして利用可能にする作業を行っています。RIA の n 層アプリケーションパターンを好む開発者には,クラウド用アプリの開発をする上で最高の方法だと思います。デプロイやモニタリング,管理操作などの良さなど,AppFabric のメリットが実感できることでしょう。
さらに私たちは,OData プロトコルサポートを RIA/JS に追加して,RIA DomainService の OData サポートを向上することも計画しています。これによって比較的大規模なアプリ (WCF RIA サービス,WCF Web API,WCF データサービス) 用サービスのビルド方法に関して,もっと大きな柔軟性を提供できると思っています。
InfoQ: 最後になりますが,MIX11 までにカバーしようと考えていて,時間的制約のために実現できなかったことはありますか?
Brad: 今回提供できなかったもののひとつは,エンティティの下位コンテキストを共有するデータソースのサポートです。アプリに Customer とその Order を可視化する部分と,Order と OrderDetail を可視化する別の部分があるような場合,これがあると便利です。同じシナリオで,ひとつの $().dataSource().dataContext() を2つのデータソースが共有できるようになれば,Order エンティティを共有して,両方のデータソースを通じて更新を反映することができます。
もうひとつ - JavaScript 開発者にとっての関心事 - は,$.dataSource で形成されたデータ形式をコントロールする方法です。JavaScript 開発者の中には,ブラウザに送信するデータ形式としてもっぱらデータ行を使う人もいれば,XML ツリー構造のデータ項目に慣れている人もいます。エンティティのグラフを,複雑で分かりにくいと思う人もいるでしょう。$.dataSource() がグラフを表示できるのは,下位サービス (現状では RIA DomainService) が適切な主キーと外部キーのメタデータを返す場合に限られています。RIA DomainService の設計作業の一環として,開発者は,どのプライマリ/外部キーメタデータを JavaScript クライアントに対してシリアライズすべきかを決定します。極端な場合,キーメタデータを送らないという選択をするかも知れません。このときに RIA/JS の $.dataSource が公開するのは,スカラ型フィールド値のみで構成された単純なデータレコードです。
MIX 後に生じた疑問は,RIA/JS のコードダウンロードのサイズに関してである。現時点において – 開発中であるため,今はまだ重視されていないが – ダウンロードサイズが 50k にも満たないのだ。参考値ではあるが,jQuery コアは 70k 以上のサイズがある。
下記のリストは,同じコンテキストを共有するデータソースの説明のために氏が示したものだ。
// Constants var serviceUrl = "CustomersAndOrders.svc"; var customerID = 42; // Data var customers = [], orders = []; // Get single customer with ID == 42 $([ customers ]).dataSource({ serviceUrl: serviceUrl, queryName: "GetCustomers", filter: { property: "ID", value: customerID } }).refresh(); // Get orders for that customer $([ orders ]).dataSource({ serviceUrl: serviceUrl, queryName: "GetOrders", filter: { property: "CustomerID", value: customerID }, dataContext: $([ customers ]).dataContext() // These two data sources share the same cache of entities. }).refresh(); ... var customer = customers[0]; // Each order.Customer should match the customer we explicitly loaded. $.each(orders, function() { var order = this; assert(order.get_Customer() === customer); }); // Each order in customer.Orders should match an order we explicitly loaded. $.each(customer.get_Orders(), function() { var order = this; assert($.inArray(order, orders) >= 0); });