MSDN Magazine 2月号のM-V-VMパターンについての記事の訳(WPF のための MODEL-VIEW-VIEWMODEL (MVVM) デザイン パターン)が昨日公開されましたね。なかなか読みごたえがありました。さて、今回のエントリでは、同じくM-V-VMパターンについてを解説した、David Hill’s WebLogDavid Hill’s WebLog : The ViewModel Patternという記事を訳してみました。

-訳ここから-

ViewModelパターン(より一般的にはModel-View-ViewModelパターンと呼ばれていますが、それではとても長ったらしく、また私は無精なのです)はWPFとSilverlightの開発者にとってますます人気のあるパターンになってきました。これは、そのシンプルさ、フレキシブルさ、そしてWPFとSilverlightによる最初からのサポートによるものです。ViewModelパターンはビジネスロジック、プレゼンテーションロジック、UIロジックを分離するのを助け、多くの開発とデザインの問題においても役立ちます。

The ViewModel pattern (more formally called the Model-View-ViewModel pattern, but that’s way too long winded and I’m lazy) is an increasingly popular pattern with WPF and Silverlight developers. This is largely due to its simplicity and flexibility and its inherent support in WPF and Silverlight. It helps to separate business, presentation and UI logic which in turn helps with a whole host of development and design issues.

アプリケーションロジックとユーザーインターフェイスの間がきれいに分割出来ているということは、ユーザーインターフェイスから独立してユニットテストが出来るということを意味します。UIを通じてのアプリケーションロジックの自動テストは複雑になりがちで、準備に時間もかかります。加えて、ユーザーインターフェイスとアプリケーションロジック部分を同時にテストする場合は二つの間でエラーを切り分けるのも難しくなりがちです。

Having a clean separation between your application’s user interface and underlying application logic means that you can unit test it independently of the user interface. Automated testing of application logic through the UI can be complex and time consuming to setup. In addition, it can be difficult to isolate errors in the user interface or application logic portions of your application when they are both tested at the same time.

ViewModelパターンを使うもう一つの重要な利点は、アプリケーション開発者はアプリケーションロジックに注力し、同時にユーザーインターフェイスデザイナはアプリケーションの見た目に注力することが出来ることです。これにより、アプリケーションのルックアンドフィールを下層のアプリケーションロジックから分離して決めることができ、保守、(ユーザビリティのフィードバックによる)変更、カスタマイズを容易にします。

Another key benefit of using the ViewModel pattern is that it allows application developers to focus on application logic while user interface designers can focus on the visual aspects of the application. This allows the look and feel of the application to be defined separately from the underlying application logic, making it easier to maintain, modify (say as a result of usability feedback) or to customize.

ViewModelパターンは、同様にアプリケーションを理解、保守しやすくします。ViewModelパターンにより、コードの再利用の機会が増えます。同じアプリケーションでの別の部分でのアプリケーションロジックの再利用が可能になります。ユーザーインターフェイスを特定のユーザーのロール、言語に合わせることが可能になります。アプリケーションロジックを同じアプリケーションのデスクトップ版とRIA版とで共有することが可能になります。これらのすべてのケースで、見た目が非常に違っていても、下層にあるアプリケーションロジックは同じです。

The ViewModel pattern also makes the application easier to understand and maintain. It also provides more opportunities for code re-use, allowing application logic to be re-used in different parts of the same application, or allowing the user interface to be tailored to specific user roles or locales, or allowing application logic to be shared between desktop and RIA versions of the same application. In all of these cases, the underlying application logic is the same though its visual representation may be quite different.

テーマのバリエーション Variations On A Theme

世の中にはViewModelパターンについてのたくさんの記事(お気に入りのものはこの記事の最後に挙げました)があり、それらはパターンの定義の仕方においてすべて少しづつ違うように見えます。もちろんこれは全て無理からぬ話です。パターンは潜在的な解決策を描く一つのただのやり方であり、実際に使う局面では状況に一番合うようにパターンを変更することが必要です。私はいわゆる「デザインパターン専門家」が参加している(常に激しく争っている)議論を見たことがあります。彼らはパターンのあるべきより良い細目について論争していましたが、「退屈で役に立たない」とだけ言っておきましょう。問題なのは、根本にあるパターンの魂と原則が理解され、適用されることであり、細かいことは殆ど意味を持ちません。

There are many posts and articles out there that describe the ViewModel pattern (my favorite ones are listed at the end of this post), and they all seem to differ slightly in how they define or describe the pattern. This is, of course, totally reasonable. Patterns are just a way to describe a potential solution to a design problem and specific scenarios will call for a pattern to be modified to best suit the situation. I find the (invariably heated) debates that the so-called ‘design pattern experts’ engage in as they argue about the finer details of a pattern to be, let’s just say, tedious and unhelpful. What matters is that the spirit and the underlying principles of the pattern are understood and applied – the details don’t matter nearly as much.

ViewModelパターンは分離されたプレゼンテーションパターンのカテゴリに入るたくさんのパターンの一つに過ぎません。本来、ViewModelパターンはPresentation Modelパターンのバリエーションの一つです(実際、ViewModelパターンは本当はPresentation Modelパターンと同じであると言う人も居ます)。あなたの考え方が何であれ、私はパターンの必要不可欠な機能であると私が信じる物について説明します。次の記事では、私が最近触っている、collection-based modelにViewModelパターンを適用したコードをお見せしましょう。

The ViewModel pattern is just one of many patterns that fall into the ‘Separated Presentation Pattern‘ bucket. Essentially, the ViewModel pattern is a variation of the Presentation Model pattern (actually, some would say that the ViewModel pattern it is in fact the same as the Presentation Model pattern). Whatever your point of view, I’m going to describe what I believe are the essential features of the pattern. In my next post I’ll show you some code that I’ve been playing with recently that applies the ViewModel pattern to collection-based models.

ViewModelの概要 ViewModel In A Nutshell

では、何がViewModelパターンの必要不可欠な機能なのでしょうか?私はViewModelパターンをこのように表現しました:

So what are the essential features of the ViewModel pattern? I describe the ViewModel pattern like this:

ViewModelパターンでは、UIとUIロジックはViewの中にカプセル化されます。Viewはプレゼンテーションのロジックと状態をカプセル化するViewModelを監視します。ViewModelは同様にModelと情報のやり取りをし、ModelとViewの間の代理人として振舞います。

In the ViewModel pattern, the UI and any UI logic are encapsulated in a View. The View observes a ViewModel which encapsulates presentation logic and state. The ViewModel in turn interacts with the Model and acts as an intermediary between it and the View.

ViewModel

分割されたプレゼンテーションパターンは全て、アプリケーションロジックとUIの様々な特色を異なるクラス、コンポーネントに配置することでアプリケーションロジックからUIを分離することを助けるために存在します。様々なパターン間の違いは二つのことに起因します。クラスに割り振られた役割と責任、そしてそれらクラスがどう情報をやり取りするか、です。ではViewModelパターンをこれら二つの観点からみてみましょう:

All of the separated presentation patterns exist to help separate UI from application logic by placing the various flavors of application logic and the UI into distinct classes or components. The differences between the various patterns are largely due to two things: the roles and responsibilities assigned to these classes, and how these classes interact with each other. Let’s look at the ViewModel pattern in these two respects:

役割と責任 Roles & Responsibilities

ViewModelパターンのクラスの役割と責任はこのように特徴づけられます:

The roles and responsibilities of the classes in the ViewModel pattern can be characterized like this:

  • ViewModelはプレゼンテーションロジックと状態をカプセル化する。プレゼンテーションロジックはここではアプリケーションのユースケース(あるいはユーザーストーリー、ユーザータスク、ワークフロー、etc.)に影響するアプリケーションロジックと定義され、アプリケーションの論理的な動作や構造を決定します。ViewModelはコントロールのコードビハインドでは決してありません。プレゼンテーションロジックは視覚的表現がどうなるか知るべきではなく、どんなユーザーインターフェイスの実装からも独立しているべきです。再利用機会を最大化するために、ViewModelは特定のUIクラス、要素、動作(アニメーションなど)に対して参照を持つべきではありません。UI基本クラスから派生するべきではありません(理想的にはPOCOであるべきです)。(もちろん)ユニットテスト可能で、 全くUI無しでも機能するべきです。
  • Modelはビジネスロジックとデータをカプセル化する。ビジネスロジックはここではアプリケーションデータの検索と管理に影響し、データの整合性と有効性を確保するいくつかのビジネスルールを確実に課すためのアプリケーションロジックと定義されます。 再利用機会を最大化するために、モデルはユースケース/ユーザーストーリー特有の動作やアプリケーションロジックを含むべきではありません。
  • ViewはUIとUIロジックをカプセル化する。Viewはアプリケーションの具体的なユーザーインターフェイスを定義します。Viewは典型的にはViewModelにバインドされたときによく動くようにデザインされた、ただのコントロールです。その特有の役割は、ユーザーに、最も適切な方法で下層にあるアプリケーションのデータとロジックを表現するユーザーインターフェイスで表示すること、そして、ユーザーの入力を受けて、それをどのようにモデルの中の下層にあるデータとアプリケーションの状態に影響させるかを定義しているViewModelに転送することです。幾つかのケースでは、Viewはコードビハインドファイルに、UIロジック―ユーザーインターフェイスの実装に固有のアプリケーションロジック―を含むことができます。しかしながら、そのようなUI固有のコードはテストが難しく、出来る限り避けるべきです。もちろん、ViewがXAMLでは宣言的に記述できない固有の動作を持つ時もあり、Viewのコードビハインドにいくらかコードがあっても差し支えありません。しかし、このコードはView内のUIコントロールの操作だけに注力すべきで、プレゼンテーションロジックを実装するべきではありません。
  • The ViewModel encapsulates presentation logic and state. Presentation logic is defined here as the application logic that is concerned with the application’s use-cases (or user stories, user tasks, workflow, etc) and defines the logical behavior and structure of the application. The ViewModel is NOT a control’s code behind. Presentation logic should have no idea what its visual representation will be like and should be independent of any specific user interface implementation. To maximize re-use opportunities, the ViewModel should have no reference to any specific UI classes, elements, controls or behavior (like animations). It should not derive from any UI base class (ideally it should be a POCO). It should (of course!) be unit testable and be able to function without any UI at all.
  • The Model encapsulates business logic and data. Business logic is defined here as any application logic that is concerned with the retrieval and management of application data and for making sure that any business rules that ensure data consistency and validity are imposed. To maximize re-use opportunities, Models should not contain any use-case or user-story specific behavior or application logic.
  • The View encapsulates UI and UI logic. Views define the specific user interface for a piece of the application. Views are typically just controls that are designed to work well when bound to a ViewModel. Their specific role is to present the user with a user interface that represents the application’s underlying data and logic in the most appropriate way, and to interpret user input gestures and forward them to the ViewModel that then defines how they affect the underlying data and application state in the Model. In some cases the view may contain UI logic – application logic that is specific to the user interface implementation – in the view’s code-behind file. However, such UI specific code is difficult to test and should be avoided as much as possible. Of course, there will be times when the View will have specific behavior that cannot be expressed declaratively in XAML so there may be some code in the View’s code-behind, but this code should be specifically focused on managing the UI controls in the View and should not implement presentation logic.

情報のやり取り Interactions

次に考えなければならないのは、お互いがどのように情報のやり取りをするかです。ここで重要なのは、ViewとViewModel間の双方向の情報のやり取りの理解です。ViewModelパターンの本質的特徴はViewがViewModelを監視することであり、それはViewModelがViewへの直接の参照を持たないことを意味します。ViewModelはステートマシンのように動作し、Viewの責任は適切な方法で状態を描くこと、受け取ったユーザー入力をもとに状態に影響させることです。

The next thing to consider is how they interact with each other. The key here is to understand the two-way interaction between the View and the ViewModel. I think the essential feature of the ViewModel pattern is that the View is an observer of the ViewModel, which means that the ViewModel doesn’t have a direct reference to the View. The ViewModel acts like a state machine and the View’s responsibility is to render the state in whatever way is appropriate, and to influence that state by interpreting user input gestures.

Viewは典型的にはViewModelが公開するプロパティを通じてViewModelの状態を引き出し、ViewModelの状態変化はViewが購読するイベントと通知を通じて連絡されます。逆方向には、Viewはユーザー入力を受け取り、ViewModelの状態を変化させることでViewModelと情報をやり取りします。これは様々な方法で行われえます。Viewは単にViewModelの公開するプロパティに値をセットすることも出来ます。より複雑な状態変化はViewModelによって公開されているアクションメソッドを通じて実現できます。

The View typically extracts state from the ViewModel through properties that the ViewModel provides and changes of state in the ViewModel are communicated through events and notifications that the View consumes. In the other direction, the View captures user input gestures and interacts with the ViewModel to change its state. This can happen in a number of ways. The View can simply set a value on a property provided by the ViewModel. More complex state changes can be achieved through action methods that are exposed by the ViewModel.

WPFとSilverlightにおけるViewModelパターン The ViewModel Pattern in WPF and Silverlight

ここまでのViewModelのパターンの説明で、私がWPFやSilverlightの特定の機能について言及していないことに気付かれたかもしれません。これは意図的なもので、パターンはテクノロジーに関知すべきではないからです。ViewModelパターンを解説する記事の多くはViewModelパターンを直接サポートするWPFやSilverlightの特定の機能に焦点を当てます。実際、これらの機能はViewModelパターンをサポートするのに素晴らしい仕事をしてくれ、そしてそのことはパターンからそれらの機能を切り離すことを困難にしています。

You may have noticed that in the description of the ViewModel pattern above I don’t make any mention of any specific WPF or Silverlight frameworks features. This is intentional since a pattern should be technology agnostic. Most of the posts and articles that describe the ViewModel pattern focus on the specific features of WPF and Silverlight that directly support the ViewModel pattern. In fact, these features do such a great job of supporting the ViewModel pattern that it becomes difficult to separate them from the pattern itself.

では、それらの機能と、それらの機能がどのようにViewModelパターンをサポートしているかをみていきましょう。

Let’s look at some of these features and see how they support the ViewModel pattern…

Data Binding: WPFとSilverlightのデータバインディングはViewをViewModelにバインドするのを容易にします。データバインディングはXAMLで宣言的に定義され、とてもフレキシブルです。ほとんどのものをほとんどのものにバインドすることができます。Viewのデータバインディングがそのプロパティとイベントを解決するために、ViewのDataContextはViewModelを参照します。双方向のデータバインディングはViewのプレゼンテーションのための、ユーザのUI操作の結果としてのViewModelの状態の更新のためのViewModelの状態の検索の世話をします。ViewModelによって発生された変更通知は、ViewModelの状態が変化したときは何時でもViewが自動的に更新できるようにします。

Data Binding: WPF and Silverlight data binding make it easy to bind a View to a ViewModel. Data bindings can be defined declaratively in XAML and are very flexible – you can pretty much bind anything to anything. The View’s DataContext references the ViewModel so that the View’s data bindings resolve to its properties and events. Two way data binding takes care of retrieving state from the ViewModel for presentation in the View, and for updating state in the ViewModel as a result of the user’s interaction with the UI. Change notifications fired by the ViewModel allow the view to be automatically updated whenever the ViewModel’s state changes.

Commands:データバインディングはプロパティとして公開される状態のためにViewとViewModelの間の双方向の情報のやり取りをサポートするための素晴らしいメカニズムを提供しますが、ViewModelはしばしばユーザーがUIを通じて始められるAction―注文の送信や経費報告書の承認など―を表すメソッドを公開します。Commandはこれに対して良い解決策を与えます。Commandによって、Viewのコントロールは、UIロジック接着コードなしでユーザーが実行できるActionと簡単に連携することが可能になります。また、Actionの視覚表現、即ちUIがCommand、即ちハンドラの実際の実装からきれいに分離されるのも可能にします。WPFはWPFより(訳注:silverlight?)一層広範囲にわたるCommandのサポートを持ちますが、基本的なメカニズムは ViewとViewModelがきれいに情報のやり取りをできるように使われることができます。

Commands: While data binding provides a great mechanism for supporting two-way interaction between the View and the ViewModel for state exposed as properties, the ViewModel will often provide methods that represent actions that the user can initiate through the UI – submit an order, approve an expense report, etc. Commands provide a good solution for this. They allow controls in the View to be easily associated with actions that the user can carry out without requiring any UI logic glue code, and they allow the visual representation of the action (i.e. the UI) to be cleanly separated from the actual implementation of the command (i.e. the handler). WPF has much more extensive support for commands than WPF, but the basic mechanism can be used to allow a View and a ViewModel to interact cleanly.

Data Templates:WPFとSilverlightのデータテンプレートの機能はViewを完全に宣言的に定義することを可能にします。UIロジック(コードビハインド)を必要とせず、純粋なUIであることは、Viewにとって凄く良いことです。データテンプレートはコントロールと、連携したバインディングを含みます。テンプレートが適用されると、そのDataContextはテンプレートとしているオブジェクト(この場合はViewModel)にセットされ、バインディングが支配するようになります。データテンプレートはあなたにViewModelのプレゼンテーションロジックに注力することが出来るようにし、ViewModelの「スキニング」をBlendのようなツールをテンプレートを構築するのに使えるUIデザイナーに、いかなるコードも書いて貰うことなしに託せるようにします。WPFは暗黙のデータテンプレートをサポートするので、データテンプレートをViewModel型と連携させることができますし、システムがその型のViewModelを見ることが出来る場合はいつでもデータテンプレートは自動的に適用されます。Silverlightはまだ暗黙のデータテンプレートをサポートしていませんが、個々のコントロールにデータテンプレートを指定してやることは可能です。最後に、WPFデータテンプレートセレクタはシステムがユーザーの役割やロケーションについて責任を負うカスタムロジックに基づいてデータテンプレートを選択することを可能にします。

Data Templates: The Data Template feature of WPF and Silverlight allow you to define a View entirely declaratively. This is great for Views that require no UI logic (no code behind) and are ‘pure’ UI. Data templates contain controls and their associated bindings. When a template is applied, its DataContext is set to the object that it’s templating (in our case, the ViewModel) and the bindings take over. Data Templates allow you to focus on the presentation logic in the ViewModel and leave the ‘skinning’ of your ViewModel to a UI designer who can use a tool such as Blend to built the template without having to write any code whatsoever. WPF supports implicit data templates so you can associate a data template with a ViewModel type and wherever the system sees a ViewModel of that type, the data template will automatically get applied. Silverlight doesn’t yet support implicit data templates, but you can manually specify the data template for individual controls. Finally, WPF Data Template Selectors allow the system to choose a data template based on custom logic, say to account for user roles or location.

CollectionViews:WPFのCollectionViewは実際ViewModelの良い例でしょう。それらは特にコレクションベースのModelをサポートし、フィルタリング、ソート、グルーピング、選択をサポートするプレゼンテーションのロジックと状態をカプセル化します。それらはデータバインディングを通じてViewによって容易に使用され、また、UIから独立しており、ユニットテストをサポートします。Silverlightはまだこの分野を十分にサポートしていませんが、ICollectionViewインターフェイスを提供しており、同等の物を実装することは出来るでしょう。(これが次のエントリのテーマなので、引き続き見ていてね!)

CollectionViews: I think WPF’s CollectionViews are actually good examples of ViewModels. They specifically support models that are collection based and they encapsulate presentation logic and state to support filtering, sorting, grouping and selection. They are easily consumed by Views through data binding, are independent of the UI and support unit testing. Silverlight doesn’t yet have as much support in this area, but it does provide the ICollectionView interface so you can implement something equivalent (this is the subject of my next post so stay tuned!!).

WPFとSilverlightには他にもたくさんの機能があります。例えばStyle, Visual State Manager, Trigger等。これらは間接的にViewModelパターンを支援しますが、ここまで説明してきたものが一番よく支援します。これらの機能すべてはViewがViewModelときれいに情報のやり取りをするのを助けるのに役立ちます。私は「きれいに」という言葉を、特に、全てを統合するのに必要なUI固有のコードの量を減らすこと、という意味で使っています。

There are many other features in WPF and Silverlight – such as Styles, Visual State Manager, Triggers*, etc – that indirectly support the ViewModel pattern but the ones described above are the big ones. All of these features work together to help the View interact cleanly with the ViewModel. By ‘cleanly’ I specifically mean that they reduce the amount of UI specific code that is required to glue everything together.

* 付け加えておきますと、私はtriggerの大ファンではありません。triggerは視覚的な挙動を定義するためのいくつかの状況ではとても便利ですが、プレゼンテーションロジックをViewに定義するよう(間違って)使うこともでき、それは良くありません。私はVisual State Managerの方が視覚的挙動を定義するのに優れたメカニズムだと思います。

* As a side note, I am not a big fan of triggers. They are very useful in some situations for defining visual behavior, but they can also be (mis-)used to define presentation logic in the view which is bad. I find the Visual State Manager a much better mechanism for defining visual behavior…

正しいコードを正しい場所に The Right Code in the Right Place

要約すると、正しいコードを正しい場所に置くのが、WPFとSilverlightアプリケーションをフレキシブルに構築し、再加速させるために、ViewModelパターンを活用するキーとなります。あるコードがどこまでやるかを判断するのはしばしば難しくなりますが、しかしやっているうちに簡単にもなりますし、WPFとSilverlightが提供する機能はこのプロセスを劇的に単純化するのを助けます。

To summarize, getting the right code in the right place is the key to leveraging the ViewModel pattern to build flexible, robust WPF and Silverlight applications. Deciding where a specific piece of code should go can sometimes be difficult, but it gets easier with practice and the features that WPF and Silverlight provides help simplify this process dramatically.

ViewModelについてもっと More Stuff On ViewModel

私がWeb上で見つけたもっとも役立ち興味深い記事をいくつか挙げておきます。

Here’s a short of list posts and articles on the web that I’ve found the most useful and interesting

oO——Oo

Silverlightでのナビゲーションについての私の次の記事を熱心に待っている方々へ。この記事と私の前のview-firstとpresenter-firstの複合についての記事は、本当は、あのシリーズのパート2aと2bです。 私はこれらの記事で描いたコンセプトに基づいて構築し、navigationとViewModelパターンがどのように相互作用をするかについて特に注目したいと思います。時間がかかっていて申し訳ありません。しかし上手くいけば待つ価値のあるものとなるでしょう:-)

For those of you who are keenly awaiting my next post on navigation in Silverlight, this post and my previous post on view-first and presenter-first composition are really parts 2a and 2b of that series. I’ll be building on the concepts that I’ve described in these posts and focusing specifically on how navigation and the ViewModel pattern interact. Sorry it’s taken so long, but hopefully it’ll be worth the wait :-)

Trackbacks : 2

Trackback URL for this entry
http://blog.sharplab.net/computer/cprograming/wpf/1840/trackback/

Listed below are links to weblogs that reference this entry

ピンバック from M-V-VMパターンについてのエントリを訳してみた 原題:”WPF patterns : MVC, MVP or MVVM or…?” - SharpLab. 09-02-21 01:32:05 JST

[...] もう一つ記事を訳してみました:M-V-VMパターンについてのエントリを訳してみた2 原題:「David Hill’s WebLog : The ViewModel Pattern」 – SharpLab. [...]

ピンバック from M-V-VMパターンについてのエントリを訳してみた3 原題"CollectionViewModel" - SharpLab. 09-02-22 02:06:53 JST

[...] 、M-V-VMパターンについてのエントリを訳してみる試みの三本目です。前回のDavid Hill’s WebLog : The ViewModel Patternという記事の続きの記事です。前回の記事で言及されていた、M-V-VMパターンに [...]