|
|
WPF/Silverlight/WindowsPhoneから WinRTまで見据えた リッチクライアントModel設計 RIAアーキテクチャ研究会 第2回セミナー 尾上 雅則
自己紹介・デモアプリ紹介 リッチクライアントのModel 古き良き設計 WinRTとAsync CTP/ReactiveExtensions リポジトリ非同期ステートフルModel まとめ アジェンダ
1.自己紹介・デモアプリ紹介 3プラットフォームで 実装された Twitterクライアント
尾上 雅則(おのうえ まさのり) 28歳 C#er / MVVMer WPF/Silverlight/WindowsPhone/WindowsForms/ASP.NET/SQL Server/ReactiveExtensions勉強中 Blog The sea of fertility – http://ugaya40.net Twitter @ugaya40 1-1.自己紹介
3Platform(WPF/Silverlight/WindowsPhone) Twitterクライアント 1-2.デモアプリ WPF4 Silverlight4 Windows Phone 7.1
設計(全プラットフォーム共通) Full MVVM リポジトリ非同期ステートフルModel なぜTwitterクライアントなのか DBアクセスは定型的に過ぎ、またオブジェクトの変化が少なくそもそも適切な粒度でリッチクライアントらしくまとめるには無理があると判断。 サンプルで使用するDBアクセスの方法を標準と思われがちなのが心外。DBアクセスは機能・非機能要件によって使い分けましょう! 1-2.デモアプリ
使用ライブラリ MVVM Light Toolkit 軽量であるが故に、もっとも万能である。 http://mvvmlight.codeplex.com/ ReactiveOauth OAuthでの通信をReactive Extensionsを利用して使用して行える。 作者 : @neueccさん http://reactiveoauth.codeplex.com/ Reactive Extensions コールバック・イベントハンドラのネストの撲滅 イベント合成 詳細は http://neue.cc の各記事参照 1-2.デモアプリ
2.リッチクライアントのModel 「リッチクライアント」のって 言わなきゃいけないのは何故?
2.リッチクライアントのModel MVVMパターンでのModelの位置づけは? 外観 画面 ビジネス ドメイン (アプリの機能) 画面を レンダリングする ための情報 呼出 イベント Data Binding
2.リッチクライアントのModel MVVMパターンでのModelの位置づけは? 画面 View ビジネス ドメイン Model レンダリング情報 ViewModel 呼出 イベント Data Binding
2.リッチクライアントのModel Modelとは? ビジネスドメイン Model アプリの外観・見た目・小手先の操作性に関わる部分以外 UI想定前のアプリのイメージ ちょっと高度なバッチ処理を書くようにModelを書く アプリの外観・見た目・小手先の操作性以外の事をViewModelに混ぜないように書く
2.リッチクライアントのModel Modelとは? ビジネスドメイン Model Modelの仕様を決めるための、 いわゆる業務的なインプットは 例えばユースケース定義の粒度。 ユースケース定義には アプリを使用するユーザー・外部システムのアクション アプリが外部に及ぼす影響 などが定義されている。 入力仕掛りなどユースケース定義にはない。
2.リッチクライアントのModel Modelとは? Model クラス群 ユーザー 外部システム(DBなども) 視認できる情報 (表示・帳票) 操作情報 操作指標となる情報 (進捗・オブジェクトの生滅など) データ送信 データ受信 アウトプット システム
2.リッチクライアントのModel Modelとは? Model クラス群 IN OUT システムが受ける入力・すべき出力、 それらをユースケース定義の様な粒度で過不足なく満たす、 それがModelの仕様であると理解しています。
2.リッチクライアントのModel デモアプリに見るモデル(ユースケース1) IN OUT ユーザーがアプリを起動する 認証されている場合 認証情報をストレージから復元する 認証されていない場合 認証する 次回のために認証情報を保存する 認証済になった場合 ユーザーの基本情報を表示する ユーザーのリストのタイムラインをTwitterから取得し、基本タイムラインと合わせて表示する
2.リッチクライアントのModel デモアプリに見るモデル(ユースケース2) IN OUT ユーザーがポストする ユーザーが投稿をTwitterにポストする
2.リッチクライアントのModel デモアプリに見るモデル(ユースケース3) IN OUT ユーザーが更新したいタイムラインを更新操作する 指定されたタイムラインの新しいツイートをTwitterから取得し、新しいツイートを追加表示する。
2.リッチクライアントのModel デモアプリに見るモデル IN OUT 起動時 アプリケーション コンテキスト TwitterSampleApplication 認証サービス AuthorizeUrlBuilder,Authorizer 各種ストレージ ①認証情報の復元 を求める ②あれば返す ③なかったら通知 ④認証 ⑤認証情報 をセット ⑥認証情報 を保存
2.リッチクライアントのModel デモアプリに見るモデル IN OUT アプリケーションコンテキスト TwitterSampleApplication 認証済アカウントコンテキスト AccountContext タイムライン TimeLine Tweet Tweet Tweet Tweet 自ユーザー情報
2.リッチクライアントのModel Model設計の注意点 IN OUT 多くの場合当然ただのデータの入れ物じゃだめ。プロパティ(状態)を持ち、メソッド(操作)を持ちます。ここまでの内容を踏まえれば自明のことです。 ドメインモデル貧血症じゃだめな事が多い Modelをただのデータの入れ物にすると、ViewModelがデータを詰めるんですか?。ViewModel/Viewの役割は? また、サーバと通信するアプリであっても、クライアント側にも当然Modelはあります。これもここまでの内容を踏まえれば自明のことです。
2.リッチクライアントのModel Model基本まとめ IN OUT リッチクライアントのModelは ビジネスドメイン ステートフル(状態を持つ) ドメインモデル貧血症ではない(状態だけではない) Modelの粒度はユースケース定義を想像して! 悩んだときは、「ではこの処理をModelでしなかった場合ViewModelがするのが適切なのか?」 なんでも設計の基本は、対象のINとOUTを明確に。
3.古き良き実装 WPF/MVVMなオールドスタイル
2.古き良きWPF/MVVMの実装 UIをブロックしないための非同期 IN OUT Modelで時間をかかる処理を行った場合(ネットワークアクセスなど)に、GUIをブロックして操作不能にしてしまうようでは話にならない フリーズって言われちゃいますよね?
2.古き良きWPF/MVVMの実装 UIをブロックしないための非同期 IN OUT ソリューションは非同期呼び出ししかありません。 本質的な問題は、それがView/ViewModelの責務(外観や小手先の操作性)に属するのか、Modelの責務(ビジネスドメイン)に属するのかです。
2.古き良きWPF/MVVMの実装 UIをブロックしないための非同期 IN OUT 多くの人が直観と実装しやすさから、 Modelはすべて同期的に実装する ViewModelが非同期でModelを呼び出す 事を選択しました。 しかし・・・
2.古き良きWPF/MVVMの実装 問題点 ・非同期前提のプラットフォーム IN OUT Silverlight(WindowsPhone)を含むプラットフォームは、Webアクセスなどが非同期APIでしか提供されていません。 もしこのWPF/MVVMのベーシックスタイルで実装すると。。。 あれ?非同期は小手先の操作性と判断してViewModelに寄せたんじゃなかったの? ViewModelとModel両方非同期って問題を複雑化させているだけじゃ・・・。
2.古き良きWPF/MVVMの実装 問題点 ・イベントの連鎖 IN OUT ステートフルModelは、ViewModelへの通知にイベントを使用します。イベントハンドラのネストが発生しやすいんですね。。。 このプロパティの変更通知来たら・・・ その時にこっちのプロパティの変更通知きたら・・・ フィルタリングして・・・
2.古き良きWPF/MVVMの実装 問題点 ・イベントの連鎖 IN OUT どう解決するのか? いくつかアプローチはあります。 しかしはずれのアプローチは当然引きたくないわけで・・・ ちょっと先を見てみることにします。
4.WinRTと Async CTP/Reactive Extensions 未来と未来へのソリューション
4.WinRT/Async CTP/ReactiveExtensions WinRTとは? IN OUT Windows 8から搭載される新たなネイティブの基盤(Win32後継?) .NETから見ると普通に.NETに見えるらしい。 C++erはネイティブアプリをXAMLで書くようになるらしい。 OSレベルで処理が50ミリ秒以上かかる可能性のあるものはすべて非同期APIしか提供されなくなる。 .NETだけやるにはあまり関係ない?いいえ。Silverlight/WindowsPhoneも考慮すればMSの姿勢は明らか。
4.WinRT/Async CTP/ReactiveExtensions WinRTとは? IN OUT WindowsPhoneを含むSilverlight環境に加えて、ついにWindows本体にも非同期が! 非同期を克服しなきゃいけない! そもそも非同期の何が嫌か 単純に書くのが面倒くさい ブロックのネストが増える。 異常系まで絡むとわけわかめ。 しかもリトライとかしなきゃいけないネットワークアクセスが非同期とか・・・ とにかくネストが醜い。 では、非同期処理へのソリューションは??
4.WinRT/Async CTP/ReactiveExtensions Async CTPとは? IN OUT 次期?C#での、非同期処理の構文レベルのサポート? こんなに簡単に! 詳しくはhttp://ufcpp.netで!
4.WinRT/Async CTP/ReactiveExtensions Reactive Extensionsとは? IN OUT LINQ to Events by @neuecc イベント・非同期などのネストをフラットに、イベントや非同期を時間を超えて合成・フィルタリングなど。 LINQ to Objectがループブロックのネストを殺害したように、本当に非同期やイベントのネストが消えてなくなります! 多少はデモアプリの実装として紹介しますが、詳しくはhttp://neue.ccにて。
5.リポジトリ非同期ステートフルModel 提案
5.リポジトリ非同期ステートフルModel リポジトリって? IN OUT リポジトリとは? 外部システムとの通信 ファイルアクセス DBアクセス など、システムにとって厄介な異常系を引き起こしかねない呼び出しを、リポジトリの呼び出しと今回は定義しています。 語源はリポジトリパターンからです。
5.リポジトリ非同期ステートフルModel リポジトリがソースコードに与える影響? IN OUT リポジトリは、ソースコードにとって テストが容易でない 非同期のネストを生む(Silverlight/今後) リトライなど厄介な要件が多い などの問題を引き起こす要因です。 逆に言えば、これらリポジトリを除いたソースコードは比較的可読性に優れ、テストも比較的容易です。
5.リポジトリ非同期ステートフルModel リポジトリ非同期ステートフルModel IN OUT リポジトリ非同期ステートフルModelとは、 リポジトリへのアクセスをすべてReactiveExtensionsの返す継続(?)に置き換えたModelです。 このModelでは、リポジトリにアクセスするメソッドはすべてIObservable<T>を返します。 なんの事かわからないでしょうし、 実際どういったメリットがあるのかわかりにくいと思いますので、デモアプリのソースコードから説明します。
5.リポジトリ非同期ステートフルModel リポジトリ非同期ステートフルModel IN OUT リポジトリ非同期ステートフルModelとは、 リポジトリへのアクセスをすべてReactiveExtensionsの返す継続(?)に置き換えたModelです。 このModelでは、リポジトリにアクセスするメソッドはすべてIOservable<T>を返します。 なんの事かわからないでしょうし、 実際どういったメリットがあるのかわかりにくいと思いますので、デモアプリのソースコードから説明します。
5.リポジトリ非同期ステートフルModel Web APIへのリトライ処理 IN OUT 不調な事で有名なTwitter API。気分よく使うにはリトライ処理が必須です。 Twitterに特定のユーザーの情報を問い合わせています。 この例では異常時に2回まで1.5秒ごとにリトライをかけています。 (TwitterApiクラス)
5.リポジトリ非同期ステートフルModel 多段Webアクセス IN 大きすぎるので、ソースコードで確認してください。 最低でも3段の連鎖WebAPIアクセスがネストすることなく順番に実行されます。 (AccountContextクラス)
5.リポジトリ非同期ステートフルModel 多段Webアクセスーカーソル処理 IN OUT フォロワー数を5000件づつカーソルとともに返してくれるAPIを叩いています。 カーソルが0になるまでアクセスを繰り返して、結果を集計して一つにして返してくれます。 もちろん各アクセスごとにリトライ1.5秒ごと2回までしてます。
5.リポジトリ非同期ステートフルModel リポジトリをすべて非同期にしたので IN OUT 非同期の責務はすべてModel側に集中することになりました。 異常系がきちんと考慮されているにもかかわらず、異常系コードがほとんど出てこないModelコードになりました。 LINQ的な機能が使えるので、イベント・非同期の結果のフィルタリングもでき、ifのネストすら減りました。
6.まとめ
6.まとめ Modelについての基本 IN OUT 継続や非同期やらの扱いに関係なく、Modelが満たすべき要件は同じです。 ViewModelとModelの責務の違いをしっかりと意識して開発すれば、ModelはUIの影響を受けないため、非常に教科書的な、クラス構造が仕様を表すようなOOPの実装に近くなってきます。 Modelをより強く意識していただけるようになる一助となっていれば幸いです。
6.まとめ リポジトリ非同期ステートフルModel IN OUT リポジトリ非同期ステートフルModelですが、すでに実戦投入経験もあり非常にうまく機能しています。 しかしまだより良い書き方があるはずだという意識はもちろんあります。 非同期へのソリューションもようやく皆が意識し始め、たたき台をもとに議論し高めていくには最良の時期に思います。非同期とリッチクライアントパターンの関係についてもっと多くの人と詰めていきたいと思っています。ご意見いただけると幸いです。
6.まとめ デモアプリについての言い訳 IN OUT まずModelですが、僕がRxスキルが未熟なためまだ汚いです。 そしてViewModelも、MVVM Lightの上に即興で構築した適当なインフラを急遽あつらえたものなので汚いです。 しかしこの資料とソースは公開します。今後もリファクタしていくたたき台にしようとも思っているので、ぜひ積極的に参加していただいたり、ご意見をいただけるとありがたいと思っております。
ご清聴 ありがとうございました
Summary: WPF/Silverlight/Windows Phone から WinRT まで見据えたリッチクライアント Model 設計と題して、リポジトリ(ファイルアクセス・ネットワークアクセス)を非同期にRxで扱うステートフルModelの提案を行いました。
| URL: |
No comments posted yet
Comments