Presentation is loading. Please wait.

Presentation is loading. Please wait.

RIAアーキテクチャ研究会 第4回セミナー 尾上 雅則. 自己紹介  尾上 雅則 (おのうえ まさのり)  昭和58年生。フリーランス  Blog – the sea of fertility  Twitter -

Similar presentations


Presentation on theme: "RIAアーキテクチャ研究会 第4回セミナー 尾上 雅則. 自己紹介  尾上 雅則 (おのうえ まさのり)  昭和58年生。フリーランス  Blog – the sea of fertility  Twitter -"— Presentation transcript:

1 RIAアーキテクチャ研究会 第4回セミナー 尾上 雅則

2 自己紹介  尾上 雅則 (おのうえ まさのり)  昭和58年生。フリーランス  Blog – the sea of fertility http://ugaya40.nethttp://ugaya40.net  Twitter - @ugaya40@ugaya40  Facebook – http://facebook.com/ugaya40http://facebook.com/ugaya40  C#er/MVVMer  Microsot MVP for Visual C#(2012/7~)

3 Agenda  WPF MVVM開発の悩みどころ  Livetの概要  Livetのライフサイクル管理  冗長で面倒なコードを倒す  Livetのメッセージング機能  Livetのその他の機能  まとめ - Livetの未来

4 WPF MVVM開発の悩み処

5 MVVM という考え方 – 概要  Model – View – ViewModelパターン  WPFをはじめとするXAML系プラットフォームのため に生まれたMVC系パターン  PresentationDomainSeparationを目的とする  現在はXAML系のみならずAndroidやブラウザ Javascriptの世界でも利用される  MVCなどと比べて優劣があるものではなく、適する プラットフォームと適さないプラットフォームがある のみであることに注意

6 MVVM という考え方 – 各責務  Viewの責務  XAMLとXAML関連コードで賄える事(表示など)  ViewModelの責務  XAMLのための状態ストア  Modelの責務  ViewとViewModel以外の部分(XAMLプラットフォームが関連 ない部分)  詳細はこちら http://ugaya40.net/architecture/20120804wankuma.html http://ugaya40.net/architecture/20120804wankuma.html

7 問題① – メモリリーク MVVMに限らず、Observaerパターンを使用するス テートフルなリッチクライアントのための責務分割型 設計パターンではWebシステムでは発生しにくいイベ ント関連のメモリリークが非常に発生しやすい。 .NETにおけるイベントの仕組みと参照の関係  責務分割した際のライフサイクル  C#でのイベントハンドリングと解除

8 イベントの仕組み - 問題① ||.NETではイベント発行側がイベント受信側の参照を保 持している。つまりイベント受信側はイベントの購読 を解除してからじゃないと勝手に消滅できない。 イベントの購読を解除せずに、受信側オブジェクトを 破棄したつもりだと実際には受信側オブジェクトは消 滅せずメモリリークとなる。

9 責務分割型のライフサイクル – 問題①  ViewとViewModelは基本データバインド(内部で WeakEventが使用されメモリリークしない)  Model(ViewとViewModel以外の部分)はアプリケー ションの本質にかかわる部分なのでずっと消滅しない ことが多い。つまりViewModelより長生き。

10 責務分割型のライフサイクル – 問題① < 長生き イベント監視 参照保持 イベントハンドラの解除をかなり正確にやらないとリ スキーなのはわかりますよね?

11 C#でのイベント - 問題① C#でのイベントハンドリング、どう書きますか? では解除はこうですか? これでは解除できません。残念ながらラムダで直接イベント ハンドラを書いた時点でイベントを解除する手段はなくなり ます。

12 C#でのイベント - 問題① イベントハンドリングとその解除を適切に行うにはこ うします。 しかしイベントハンドラの登録と解除を同じメソッド 内で行うことは稀有です。つまり・・

13 C#でのイベント - 問題① ハンドラとイベント発行オブジェクトでフィールド管理が地 獄に!!!

14 問題① – メモリリーク まとめ  MVVMパターンではイベント受信側オブジェクトの方 が基本的に寿命が短く、メモリリークのリスクが大き い。  そのため適切にイベントハンドラの登録と解除を管理 する必要がある。  C#でのイベントハンドラの登録と解除が複数メソッ ドにまたがる場合(その方が多い)、クラスフィールド でイベントハンドリング関連オブジェクトが増えやす くつらい。

15 問題②–バインドできないプロパティ  MVVMパターンのViewModelはViewの状態ストアで す。XAMLはバインディングファーストなDSLである ため、Viewは基本的にViewModelのプロパティをバ インドで表示する形でレンダリングされます。  ViewとViewModel間の通信は極力データバインディ ングで統一されるほど問題が発生しにくくなっていま す。  データバインディングを使用するとViewはViewModel の変更通知イベントを監視しますが、データバインディ ング機構内部ではWeakEvent(弱いイベント)という機 構が使用されているため、メモリリークが発生しません。  単純に責務感通信方法が統一されるほど管理は容易

16 問題②–バインドできないプロパティ バインドできない!  依存関係プロパティとして用意されているもの以外は バインドできません。それが結構多いんです・・。

17 問題③–冗長なコード1 バインドするために必須な 変更通知プロパティ。 冗長なコードの代表格です ね。面倒です。 (ViewModel & Model)

18 問題③–冗長なコード2  操作をバインドするため のICommand実装。こ れも冗長です。 (ViewModel)

19 WPF MVVM開発の悩み処 – まとめ ① メモリリークが発生しやすい & きちんとした管理が難し いのでイライラする ② バインドできないプロパティにイライラする ③ 冗長なコードにイライラする → 要はイライラする。 ※一番上のもの以外はMVVMのせいではなくWPF(というか XAML系全般)自体の問題であることに注意 Livetはこれらに対応するソリューションです。

20 Livetの概要

21 Livetとは?  WPF4のための「国産」MVVMインフラストラクチャ  ライセンスはzlib/libpng  通常の使用であれば、クレジットなど必要ない  ソース改変使用する場合はクレジットの明記が必要  Project Home  http://ugaya40.net/Livet http://ugaya40.net/Livet  GitHub  https://github.com/ugaya40/Livet https://github.com/ugaya40/Livet

22 Livetとは?  来月(2012/10)で開発開始から2年  採用実績は企業・個人開発者ともに多数  おそらくは日本一のC#erたちが集うTLにて多くの方 からフィードバックをいただき、議論を積み重ねて 作ってきました  MVVMの概念そのものを突き詰めた結果のシナリオを ベースに機能を構築しており、ほかのMVVMライブラ リが未着手な問題の多くに着手できています

23 Livetのインストール  Visual Studio 2010/2012なら拡張機能マネージャ から一発導入  Visual Studio 2010 Express C#/Visual Basic ある いはVisual Studio 2012 Express for Windows DesktopならSetup.exeから一発導入  ライブラリだけならNugetからも導入可能です

24 Livetの構成  Visual Studio2010/2012/Express各環境用、 C#/VisualBasic双方用のプロジェクトテンプレー ト・アイテムテンプレート・コードスニペットなどが 含まれます。

25 Livetのライフサイクル管理

26  Livet0.99系までは、Model⇔ViewModel間のライフ サイクル管理にWeakEventを使用してメモリリーク を防いでいました。  しかし、WeakEventはCPUが回りすぎるという フィードバックをいくつかいただいたため、また ViewModelとModelの間はView⇔ViewModelの間ほ どライフサイクル管理が難しくはないため、現在の Livet1.0系ではすべて手動管理する形になっています。 ※View⇔ViewModel間は極力データバインディングによ る通信を行う事で、WeakEventが自動的に使用されます

27 Livetのライフサイクル管理  メモリリークの問題、このコードをLivetはどう変え るのでしょうか?

28 Livetのライフサイクル管理  ViewModelではこうなります。ともにLivetの機能で あるPropertyChangedEventListenerと CompositeDisposableが鍵です。

29 PropertyChangedEventListener  PropertyChangedEventListenerとは、 PropertyChangedイベント購読状態をIDisposable として扱うための機能です。Disposeによってイベン ト購読が解除されます。  また、普通にイベントハン ドラでは変更通知が来たプ ロパティ名ごとにこうなり がちなところが・・

30 PropertyChangedEventListener  あるいはコレクション初期化子を用いて・・  こう書けたりします。

31 LivetCompositeDisposable  LivetのViewModel型には最初からメンバとし て定義されているIDisposableのコレクション です。CompositeDisposableをDisposeするこ とでコレクションメンバのIDisposableもすべ てDisposeされます。  LivetのViewModel(IDisposable)型では ViewModelがDisposeされる際に CompositeDisposableがDisposeされます。

32 LivetCompositeDisposable  つまりこう記述するだけで、listenerのイベン ト購読もViewModel破棄時にすべてDisposeさ れるわけです。

33 ViewModelのDisposeは誰が呼ぶのか?  LivetのWindowテンプレートではWindowを閉じる 際に、DataContextがIDisposableであれば Disposeを行うビヘイビアが最初から記述されてい ます。  WPFのViewModelのオブジェクト階層は結局常 にWindowのDataContextがルートにいます。 メンバに子ViewModelが存在するViewModelも、 その子ViewModelを自身の CompositeDisposableに放り込むことで簡単に ハンドラの解除が管理できるわけです。

34 ViewModelのDisposeは誰が呼ぶのか?  Windowが閉じられるとす べてのイベントハンドラ や破棄可能なリソースが 連鎖的に破棄されます

35 Livet - ViewModelのライフサイクル管理  LivetではPropertyChangedEventListener以外にも、 CollectonChangedEventListener、ユーザー定義イ ベントに対応するための汎用クラスEventListenerク ラスが定義されています。  LivetのViewModelでは用意されている CompositeDisposableや各種EventListenerを使用し てViewModelのライフサイクル管理が容易に行える ようになっています。

36 ViewとViewModelのライフサイクル管理  データバインドでの通信はWeakEvent機構が使用さ れ、メモリリークは発生しえませんが、データバイン ドでは処理できないイベントが残ります。  次章で説明するメッセージング機構を使えば、 ViewModelからのイベントをデータバインディング で扱えますが、ビヘイビア・トリガー・アクションな どの知識も必要ですし、そういったコードビハインド に依存しない実装はView抽象化要件がなければ意義 は薄いものです。

37 ViewとViewModelのライフサイクル管理  Model⇔ViewModel間と異なりView⇔ViewModel間 のハンドラの管理は難易度が高いため(Viewの生成消 滅の頻繁さ・WPF自体バグ起因・部品コンポーネン ト化による複雑さ)自分でハンドラの管理をしっかり できれば一番ですが、不安な場合は LivetWeakEventListenerを使用することができます。  LivetWeakEventListenerは汎用WeakEvent機構で す。.NET標準のものより手軽に、しかもはるかに高 速に(実測4~5倍)WeakEvent機構を使用できます。

38 LivetWeakEventListener

39 冗長で面倒なコードを倒す

40 コードスニペット - デモ  Livetでは変更通知プロパティ・ICommand2種のコード スニペットが用意されています。  ReSharper7のINotifyPropertyChangedサポートにも対応し ています。  lprop/lpropn  それぞれ.NET4/4.5用の変更通知プロパティ  lvcom/lvcomn  引数を取らないICommand実装クラスViewModelCommand のフル・CanExecute無し版  llcom/llcomn  引数を取るICommand実装クラスListenerCommandのフ ル・CanExecute無し版

41 メソッド直接バインディング - デモ  Livetを使用すると実はICommandを全く使わずに ViewModelからViewに操作を公開することも可能で す。  LivetのView機能はすべてICommand無しのメソッ ド直接バインディングに対応しています  内部ではリフレクション・式木・Taskなどをフル活 用したメソッドキャッシュ機構があり、またそれらメ ソッドキャッシュ生成機構はMethodBinderというク ラスにまとめてあり、開発者が自身のクラスに簡単に メソッド直接バインディングの仕組みを追加すること もできます。

42 メソッド直接バインディング  LivetCallMethodActionはBlend SDKの CallMethodAcitonより高速で、かつ引数をとること もできます。  後述するメッセージング機構でもメソッド直接バイン ディングは使用できるので後でまた確認することにし ます。

43 Livetのメッセージング機能

44 メッセージング機構とは?  ViewModelからViewに操作指示メッセージを送るた めの機構です。  ViewModelから既定のメンバであるMessengerを使 用してViewにメッセージを送信します。  現在のLivetでは、XAML上に記述する InteractionMessageTriggerでMessengerからの メッセージを受け、対応する処理となるアクションを 実行します。  View抽象化要件がなければ、しいてメッセージング 機構に頼る必要はありません!

45 2種類のメッセージ対応アクションの起動-デモ  ViewModelからInteractionMessageTriggerを介し ての起動  ViewModelのMessenger + InteractionMessageTriggerによるアクションの起動  Viewから直接の起動  EventTriggerなどの任意のトリガーによるアクション の起動

46 Livetのメッセージング機能まとめ  ご覧のとおり、Livetのメッセージ機能はすべてメ ソッド直接バインディングが使用でき、かつView起 点・ViewModel起点でアクションを起動できます。  メッセージング機構はイベントをデータバインディン グで処理するような機構であり、その内部ではデータ バインディングと同じくWeakEventが使われていま す。  View抽象化要件がないシナリオでは特にこだわる必 要はありません。

47 そのほかのLivet機能

48 ViewModelHelper. CreateReadOnlyDispatcherCollection  Modelの変更通知コレクションに自動的に連動する ViewModelのコレクションを作製します。  戻りであるReadOnlyDispatcherCollectionはIDisposable であり、DisposeすることでModelコレクションとの連動 が解除され、自身の各要素がIDisposableである場合すべ てDisposeします。  簡単にModelコレクションからViewModelのコレクション を生成でき、CompositeDisposableと組み合わせること で管理も容易です。

49 バインドできないプロパティ対策  Livetではバインドできないプロパティの単一方向バインドを可 能にするビヘイビアとアクションが大量に含まれています。  バインドシステムの制約から、2種類ともつけて双方向と いうやり方はできません。

50 ビヘイビア・アクション・トリガーなど  LivetDataTrigger  Blend SDKのそれと違い、初期値に対応した DataTrigger  WindowCloseCancelBehavior  Windowのクローズ可否処理をViewModelなどバインド 先に委譲できるビヘイビア  SetFocusAction  アタッチしたコントロールにフォーカスを移動する など

51 その他  ObservableSyncronizedCollection  スレッドセーフなObservableCollection  汎用EnumToBooleanConverter  Enumとboolの相互変換を行いIValueConveterの実相 の手間を削減する  アタッチしたコントロールにフォーカスを移動する など

52 Livetの未来 - まとめ

53 Livetの今後の予定  Livet英語化プロジェクト  コードビハインド実装の補完  より簡潔なViewModelイベントのコードビハインドで のハンドリングなど  バインドできないプロパティ対策の高度化  バインドできないプロパティの中からシナリオベースで よく使われる機能を双方向バインド可能にする  (すでにTextBoxとPasswordBoxはある)

54 Livet - まとめ  LivetはMVVMについて適切に理解していれば適切に 理解しているほどその機能がいかせるライブラリです。  ほかのMVVMライブラリと異なりViewModel単体で はなく全体を見たライブラリになっています。  プロジェクトテンプレート・スニペット・ハンドラ管 理・メソッド直接バインディングなどの機能をつかっ ていただければ2度とほかのMVVMライブラリには戻 れないものになっていると思います。

55 ご清聴ありがとうございまいた!


Download ppt "RIAアーキテクチャ研究会 第4回セミナー 尾上 雅則. 自己紹介  尾上 雅則 (おのうえ まさのり)  昭和58年生。フリーランス  Blog – the sea of fertility  Twitter -"

Similar presentations


Ads by Google