WPF/Silverlightの特徴と一般的な設計原則から導出する MVVM(Model/View/ViewModel)パターン

Similar presentations


Presentation on theme: "WPF/Silverlightの特徴と一般的な設計原則から導出する MVVM(Model/View/ViewModel)パターン"— Presentation transcript:

1 WPF/Silverlightの特徴と一般的な設計原則から導出する MVVM(Model/View/ViewModel)パターン
わんくま同盟 東京勉強会 #60 尾上 雅則

2 自己紹介 尾上 雅則(おのうえ まさのり) 使用技術 MVVMer。MVVM星人とか呼ばれたりもします。
昭和58年度生 フリーランス 使用技術 C#er WPF/Silverlight・ASP.NET・WindowsFormsなど。 AzureとかASP.NET MVCとか覚えたい。 MVVMer。MVVM星人とか呼ばれたりもします。 Blog : the sea of fertility Twitter

3 アジェンダ WPF/Silverlightの特徴と、 一般的な設計原則から WPF/Silverlightのための設計パターンである
MVVMパターンを導出して、 MVVMパターンはなんら特別なパターンではない という事を理解して頂きます。 また、インフラの必要性についても話します。

4 アジェンダ WPF/Silverlightの考慮すべき特徴の紹介 WPF/Silverlightアプリの設計定石を考える(1)
見た目と機能の分離 WPF/Silverlightアプリの設計定石を考える(1) 一般的な設計原則から WPF/Silverlightアプリの設計定石を考える(2) WPF/Silverlightの特徴から、そしてMVVMパターン へ WPF/Silverlightアプリの設計定石を考える(3) リッチクライアントだから考えなくてはならない事 まとめ

5 WPF/Silverlightの 考慮すべき特徴の紹介
ControlTemplate VisualStateManager 双方向データバインド DataTemplate

6 コントロールの機能と外観の分離(1) ControlTemplate
同じコントロールも外観をXAMLだけで別の外見に。 外見の変化はカスタムコントロールを作る動機ではなくなった。 <TreeView> <ListBox> 画像貼りミス じゃないんですよ!

7 コントロールの機能と外観の分離(2) VisualStateManager
コントロールに状態に応じた外観を定義する事が可能 になった。(状態間にアニメーションの定義も可能/状 態を追加する事も可能) 外観に関わるコードはこうやってほぼ全てXAMLに委 譲できる。

8 データバインド指向(1) 双方向データバインド
WPF/Silverlightのデータバインディングは双方向の データバインドに対応している

9 データバインド指向(2) DataTemplate
コレクションコントロール(ListBox/TreeView)などに は最強の武器がある。

10 WPF/Silverlightの考慮すべき特徴 まとめ
WPF/Silverlightでは見た目に関する定義をほとんど XAMLに委譲できるようになっている。 データバインドが見た目と機能の分離をさらに促進す る。 データバインドに頼らないで作ろうとすると動作に制 約がつく。 たとえばC#/VBコードから構築されたDataTemplateでは Templateのすべての機能を使用する事ができない旨がMSDN に明記されている

11 WPF/Silverlightの 設計定石を考える(1)
一般的な設計原則から レガシーなイベントドリブン コードの問題点 相互依存 ざっくりとした一般的なGUI 責務分割型設計

12 レガシーなイベントドリブン イベントの発生順序と処理の依存
イベントハンドラに全ての処理を書くと、イベントの発 生順序とビジネスドメイン(アプリ本来の問題領域)の処 理が強く結合してしまいやすい。

13 相互依存です。 アプリ本来の処理シーケンスと、見た目のコード の混在を片づけるには、そりゃあ責務を分離すれ ば良いんです。
レガシーなイベントドリブン 対策 アプリ本来の処理シーケンスと、見た目のコード の混在を片づけるには、そりゃあ責務を分離すれ ば良いんです。 しかし気を付けなければならない事があります。 相互依存です。

14 相互依存 相互依存が引き起こす事 相互依存とは 分割された責務が、互いが互いに依存する事。

15 相互依存 相互依存が引き起こす事 互いが互いに依存する事で単一責任の原則に反し やすくなる。

16 相互依存 相互依存の排除(1) – シンプルなinterface
インターフェースによるアプローチ 相手がインターフェースを実装している事だけを知って いれば良い。 OOPでの疎結合の基本。

17 相互依存 OOPでの相互依存の排除(2) - Observer
イベント受信側について、イベント発行側が全く知る必要がな い。

18 相互依存 シンプルなinterface vs Observer
責務間の関連が深い(通信相手の存在が前提)場合 がシンプルなinterfacceの方が良い。 記録処理クラスと、記録の実体(ファイル・DB)クラスの 通信 いわゆるリポジトリパターン 責務間に関連が無い場合はイベントObserverに よるアプローチが良い 完全に責務に関連がない場合、通信相手の存在を前提と したシンプルなinterfaeよりObserverの方が優秀。

19 まずはざっくり分けてみよう 外観 ここまでを踏まえて、GUIアプリをざっくり分け てみます。 呼出 イベント通知
ビジネスドメイン (アプリの機能) イベント通知 ビジネスドメインから外観への通信はイベントの方が望ましい

20 まずはざっくり分けてみよう 外観 Model View ここまでを踏まえて、GUIアプリをざっくり分け てみます。 呼出 イベント監視
ビジネスドメイン Model イベント監視 イベント通知

21 まずはざっくり分けてみよう View Model 実はこれがMVCに代表されるUIパターンの共通 理念であり、基本的な形。 呼出
イベント監視 イベント通知

22 まとめ 全てのUIパターンの正しい理解のためには、この 形を理解する事が基本です。あとでも出てくるの で覚えておいてください。 View 呼出 Model イベント監視 イベント通知

23 WPF/Silverlightの 設計定石を考える(2)
そしてMVVMパターンへ コレクションコントロールの罠 イベントの発生順序とコントロー ルの状態の複雑化 別途状態ストアを持とう! MVVMパターン

24 コレクションコントロールの罠 コレクションコントロールには罠がある。 ListBox/ListView

25 コレクションコントロールの罠 コレクションコントロールには罠がある。 TreeView 展開するまで やはり子のインスタンスが無い!

26 コレクションコントロールの罠

27 コレクションコントロールの罠 DataTemplate内の別のコントロールの情報をと りにくい
VisualTreeHelperとかいう静的クラスの、 自分の子の数を習得するだけのメソッドと インデックスで対象の子コントロールを取得してくるだ けのメソッド でしか、DataTemplate内のコントロールは触る事がで きない。。。有り得ない。。。

28 コレクションコントロールの罠 ではどうするか 各項目に対応するような
→ データバインドで全て解決 各項目に対応するような 表示用のデータバインド用オブジェクトがあれば全てデータバインドで解決できる (チェック状態などもboolとして持つ) むしろ他のアプローチじゃ解決できない!

29 WPF/Silverlightコントロールの 特徴
コレクションコントロール以外でも、レイアウト 関連プロパティなどでは、イベントの発生状況に よってプロパティの値が信用できない。 WinForms/ASP.NETまではむしろデータバイン ドはおまけ機能の印象が強かった。 WPF/Silverlightではデータバインドこそが本 流。使わないと制約だらけ。

30 WPF/Silverlightコントロールの 特徴
コントロールの状態は、レイアウトシステムとの 連携やコントロールの内部実装で使用する事にな る。 だから・・・・

31 画面のための状態ストアを持とう! コレクションコントロール以外のものも含めて、画 面のレンダリングに必要な動的に変化する情報を保 存する責務を新たに設ける。 バインド用オブジェクト テキスト:1992 バインド! 選択されているかどうか テキスト:1993 選択されているかどうか

32 画面のための状態ストアを持とう! 外観 画面を描画するための状態ストアを別途持ってしま おう! 画面 XAML 画面を レンダリングする
Data Binding

33 画面のための状態ストアを持とう! つまりこれが・・ 外観 ビジネス ドメイン (アプリの機能) 呼出 イベント

34 画面のための状態ストアを持とう! 外観 呼出 画面 画面を レンダリングする ための情報 Data Binding イベント ビジネス
ドメイン (アプリの機能) Data Binding イベント

35 画面のための状態ストアを持とう! View : UIの外観と構造を定義 ViewModel : Viewをレンダリングするための情報 Model : アプリ本来の問題領域に対するコード 呼出 画面 View レンダリング情報 ViewModel ビジネス ドメイン Model Data Binding イベント

36 MVVM(Model/View/ViewModel)パターン
依存 View ViewModel Model Data Binding イベント

37 WPF/Silverlightの 設計定石を考える(3)
リッチクライアントだから考えな ければいけない事 責務間通信に関わる問題 インフラストラクチャの使用 通信手法の統一がもたらすも の

38 リッチクライアントは難しい リッチクライアント開発では、リッチクライアント だからこそ考えなければならない問題があります。 WinFormsなどの開発で、開発の最後の方まで残り がちで解決の厄介なバグ、覚えがありませんか? 代表的な一例 そう メモリリーク です。

39 責務間通信に関わる問題 メモリリーク イベント 受信側A イベント発行元 ButtonA そもそもメモリリークとは
public class イベント受信側A { ButtonA.Click += Clicked; private void Clicked(object sender, RoutedEventArgs e) //処理 Click イベント公開

40 受信側AのClickedメソッドの参照を保持している
責務間通信に関わる問題 メモリリーク そもそもメモリリークとは イベント 受信側A イベント発行元 ButtonA 実は発行元(Button A)が 受信側AのClickedメソッドの参照を保持している public class イベント受信側A { ButtonA.Click += Clicked; private void Clicked(object sender, RoutedEventArgs e) //処理 Click イベント公開

41 受信側が勝手に消滅しようとしても発行側に参照されているので消えられない!
責務間通信に関わる問題 メモリリーク そもそもメモリリークとは イベント 受信側A イベントの登録を解除しないで、 受信側が勝手に消滅しようとしても発行側に参照されているので消えられない! イベント発行元 ButtonA public class イベント受信側A { ButtonA.Click += Clicked; private void Clicked(object sender, RoutedEventArgs e) //処理 Click イベント公開

42 責務間通信に関わる問題 メモリリーク つまりメモリリークとは イベントを公開しているオブジェクトがあり、発行 元より寿命の短いオブジェクトがイベントを受信し ている時に起きやすい問題。 きちんと登録を解除できれば良いけど、 WPF/Silverlightではそのタイミングの管理が非常 に面倒。

43 責務間通信に関わる問題 メモリリーク ちなみにWebでは滅多に発生しない問題。 Webではすべてのオブジェクトの生存期間が基本的 に1リクエストの中に納まるから、分けた責務のオ ブジェクト全てがほぼ同時に生成され、ほぼ同時に 消滅する。(static使用時を除く) ステートフル(状態を持つ・持ち続ける)アプリ、つ まりほとんどの場合リッチクライアントに固有の問 題!

44 責務間通信に関わる問題 メモリリーク MVVMパターンでのメモリリークについて、 それぞれ View ⇔ ViewModel間
コレクションコントロールの中身とか、頻繁にイ ンスタンスが出来たり消えたりしています。 ViewModel ⇔ Model間 検索結果画面など、一時的な画面はWindow消す 時に普通ViewModelも捨てちゃいます。 についてみていきます。

45 責務間通信に関わる問題 メモリリーク(View⇔ViewModel)
データバインディング機構の正体 View ViewModel Data Binding

46 責務間通信に関わる問題 メモリリーク(View⇔ViewModel)
データバインディング機構とは リフレクションなど View ViewModel Data Binding イベントによる 変更通知

47 責務間通信に関わる問題 メモリリーク(View⇔ViewModel)
しかし、データバインディング機構内部では WeakEventパターン(後述)が適用され、メモリ リークのリスクがありません。 リフレクションなど View ViewModel イベントによる 変更通知

48 責務間通信に関わる問題 メモリリーク(View⇔ViewModel)
逆に言えば、データバインディング機構から漏れた 通信手法を使用する事でメモリリークのリスクがあ ります。 リフレクションなど View ViewModel イベントによる 変更通知

49 責務間通信に関わる問題 メモリリーク(ViewModel⇔Model)
呼出 ViewModel Model イベント通知

50 責務間通信に関わる問題 メモリリーク(ViewModel⇔Model)
そこでWeakEventパターンです。 リフレクションなど ViewModel Model イベント通知

51 責務間通信に関わる問題 WeakEventパターン
WeakEventパターンとは弱いイベントパターンの 事です。関連クラスはSystem.Windows名前空間 に定義されていて、WPFなどでの使用が考慮され ているように見えます。 MSDNによれば ええ、まさにうってつけです。 弱いイベント パターンは、リスナーをイベントに登録する必要がある際に、いつ登録を解除するかを明示的には認識できない場合に使用できます。

52 責務間通信に関わる問題 WeakEventパターン
端的に言えば、イベントを受 ける代理のオブジェクトを立 て、そのオブジェクトをグ ローバルに弱参照で管理する 事によってCLRにイベントハ ンドラを参照と認識させない パターン

53 責務間通信に関わる問題 WeakEventパターン
いちいち実装とか説明とかやっていられないレベルで面倒なので説明省略 責務間通信に関わる問題 WeakEventパターン 端的に言えば、イベントを受 ける代理のオブジェクトを立 て、そのオブジェクトをグ ローバルに弱参照で管理する 事によってCLRにイベントハ ンドラを参照と認識させない パターン

54 責務間通信に関わる問題 WeakEventパターン
とにかくリッチクライアント は、 ステートフルであるがゆえに 適切に作成するには、ある意味 ではWebより深い知識が要求さ れます。

55 責務間通信に関わる問題 WeakEventパターン
要はこんな事を 自分で考えたくないんです! チームメンバーに全て理 解してもらえますか?

56 既存の MVVM補助インフラストラクチャ を使えば、 そんな事自分で理解する必要も 考える必要もないんです!

57 インフラストラクチャの使用 MVVMインフラストラクチャ
Livet 作者: 僕 WPF4専用。補助ライブラリとしての機能の他に各種VS用テンプ レート・スニペット・Expression Blend デザイナ拡張機能など を持つ。 もうすぐver 1.0 Prism 作者:MS Pattern & Practiceチーム WPF3.5/4 Silverlight4用。純粋な補助ライブラリ。 外部の方がテンプレートなどを提供してくれている。チュートリ アルなどもある。巨大。

58 インフラストラクチャの使用 MVVMインフラストラクチャ
MVVM Light Toolkit 作者:Laurent Bugnion WPF3.5/4 Silverlight4 WindowsPhone 7用。おそらくは世界 で一番利用者が多いライブラリ。補助ライブラリとしての機能の 他に各種テンプレート・スニペットなどを持つ。 私見では現状ではWPFならLivet一択。 SilverlightならMVVM Light Toolkitでコードビ ハインドありをおすすめします。Windows Phone 7 ではMVVM Light Toolkitしか選択肢が ないのが現状です。

59 インフラストラクチャの使用 MVVMインフラが提供する機能
ViewModel⇔Model間通信で提供される機能 MVVM用にカスタマイズされたWeakEventの実装 Livet Notificator/ViewModelHelper/NotificationHelper Prism EventAggregator MVVM Light Toolkit Messenger

60 インフラストラクチャの使用 MVVMインフラが提供する機能
View⇔ViewModel間通信で提供される機能 通信手法のデータバインドへの統一 メソッドのバインディング DelegateCommand/RelayCommand XAML機能の拡充 ビヘイビア・トリガー・アクション 揮発性の現象への対応 メッセージングシステム

61 インフラストラクチャの使用 MVVMインフラが提供する機能
(補足)View⇔ViewModel間通信 コードビハインド無し云々を聞いた事がある 方もいらっしゃると思いますが、それはView とViewModel間の通信をデータバインドに統 一する事によって生まれる付随的なメリット です。それがMVVMパターンの目的であるわ けではありません。

62 インフラストラクチャの使用 MVVMインフラが提供する機能
(補足)View⇔ViewModel間通信 コードビハインドを失くす事で、管理面(責務 の遵守が容易に)、XAMLのXMLたるメリット (WYSIWYGなエディタとの相性とか)を活か しやすくなります。 コードビハインドを失くすのが目的ではな く、データバインドに通信を統一する事で、 考慮事項を減らし、MVVM本来のメリットを 引き出そうとするのが目的!

63 インフラストラクチャの使用 MVVMインフラを使用する理由
外部ライブラリを使うのは敷居が高 い? それは無い。 スキルが低い人間が混じるからこそ、インフラが必要。(WeakEventとかみんなが理解できるもの?)

64 まとめ

65 むしろWPF/SLにとって一択ってくらい普通のパターン
まとめ MVVMパターン 特別なパターンどころか、 むしろWPF/SLにとって一択ってくらい普通のパターン 外観 呼出 画面 View 画面を レンダリングする ための情報 ViewModel ビジネス ドメイン (アプリの機能) Model Data Binding イベント

66 まとめ MVVMパターン 責務 責務間の通信 View:UIの外観と構造を定義 ViewModel :UIレンダリングのためのデータストア
View⇔ViewModel : 極力双方向データバインディン グで。インフラの導入具合によっては全てデータバイ ンディングに統一する事も可能。 ViewModel⇔Model : イベントとメソッド呼び出し

67 まとめ MVVMパターン 各種MVVMインフラが提供する機能は、 WPF/SilverlightでMVVMパターンの持つ思想の メリットをより引き出したり、面倒な考慮事項 を失くすためのもの。DelegateCommand使う からMVVMとか、コードビハインド無いから MVVMとか勘違い。 スキルに自信がないからこそMVVMインフラを 使う。

68 まとめ 今後の学習 - 概念に踏み込む MVVMで良く聞く具体的な実装要素 (DelegateCommandとか)のうち、何を使えば どういうメリットがあり、使わなければどんな メリットが損なわれるかを把握する事で実務で の導入をしやすくする。 @IT MVVMパターンの常識 「M」「V」「VM」の役割とは? gentry_02/greatblogentry_02_01.html

69 まとめ 今後の学習 - 概念に踏み込む MVC/MVP/PMなどの、別のUIパターンとの違 いを学ぶ。
the sea of fertility MVVMパターンとイベント駆動開発、そして MVC/MVP/PMパターンとの関係 - 何故MVVMなのか eventdriven.html

70 まとめ 今後の学習 – 採用環境ごとに何をしるべきか
.NET/Silverlight標準、MVVM Light Toolkit/Prism/Livetなどを採用した場合の何を どこまで学べば良いかのガイドライン。  the sea of fertility MVVMパターン学習のファーストステップ - 何をどこま で勉強するか

71 ご清聴 ありがとうございました 以下の方々に 簡易レビュー協力頂きました。 ありがとうございます。 秘密組織 謎クエリの会(3名)
@xin9leさん


Download ppt "WPF/Silverlightの特徴と一般的な設計原則から導出する MVVM(Model/View/ViewModel)パターン"

Similar presentations


Ads by Google