MVPVM 設計パターン

WPF 向けのモデル - ビュー - プレゼンター - ビューモデル設計パターン

Bill Kratochvil

コード サンプルのダウンロード

これまで私が携わり、成功を収めたすべてプロジェクトのうち、もっとも成功を収めたプロジェクトには共通する成果があります。それは、アプリケーションの規模が大きくなるほど、コード ベースが小さくなる、というものです。一見矛盾しているように思えますが、アジャイル環境でコーディングを行うと、コード ベースが小さくなります。要件が変化するにつれて、リファクタリングが行われます。こうしたリファクタリングの際に開発後に明らかになった情報を組み合わせて、既存コンポーネントの再利用効率を上げると同時に、重複するコードを削除できます。

一方、モノリシック構造のプロジェクトを採用して成功を収めたこともありましたが、ソース コードが増加する傾向があり、再利用のチャンスはほとんどありませんでした。このようなプロジェクトはリソースを集中的に使用することになり、将来拡張する際のリスクとなります。この 2 種類のプロジェクトの根本的な違いは、使用するインフラストラクチャ設計パターンにあります。使用するパターンによって、墓穴を掘ることになるか、将来利用できるかもしれないチャンスをものにできるかが決まります。

今回は、モデル ビュー ビューモデル (MVVM: Model-View-ViewModel) パターンの知名度に隠れて多くの Windows Presentation Foundation (WPF) 開発者が見過ごしてきたパターンの 1 つ、モデル - ビュー - プレゼンター - ビューモデル (MVPVM: Model-View-Presenter-ViewModel) パターンを取り上げます。このエンタープライズ アプリケーション設計パターンは、Microsoft patterns & practices の Prism プロジェクト (Prism.CodePlex.com、英語) で導入されました (注: このパターンには名前が付けられていなかったので、ここでは MVPVM と呼びます)。Prism の説明は、上記のプロジェクト Web サイトの概要を引用するのが最もわかりやすいでしょう。

「Prism は、WPF デスクトップ アプリケーション、Silverlight のリッチ インターネット アプリケーション (RIA)、および Windows Phone アプリケーションを機能豊富で、柔軟かつ管理しやすいアプリケーションとするための設計と構築を容易にすることを目的としたガイダンスを提供します。懸案事項の分離や疎結合など、重要なアーキテクチャ設計原則を実現する設計パターンを使用することで、疎結合型のコンポーネントを使用してアプリケーションを設計および構築できます。こうした疎結合型のコンポーネントは、独自に進化させることを可能にしながらも、アプリケーション全体と簡単かつシームレスに統合できるようになっています。このような種類のアプリケーションを複合アプリケーションと呼びます。」

MVPVM は (後で説明するように) MVVM の進化版ですが、MVVM の知名度と成功に隠れて影が薄くなっています。MVPVM では、MVVM の能力と機能をすべて利用できるうえ、モデル - ビュー - プレゼンター (MVP: Model-View-Presenter) パターンのスケーラビリティと拡張性が導入されます。MVVM が「WPF 向け MVP の進化形」であることを理解していただければ、MVPVM についても意義があると感じられるのではないでしょうか。

MVPVM の能力とメリットを正当に評価するには、このパターンの進化の過程を理解する、つまりこれまでの開発手法の歴史を理解する必要があります。モデル - ビュー - コントローラー (MVC: Model-View-Controller) パターンは、この歴史を理解するうえで不可欠な要素なので、まずは MVC について、おそらくこれまでにない切り口から説明しましょう。

MVC パターン

ここでは、デスクトップ アプリケーションにおける MVC を説明します。Web アプリケーションの場合は事情が異なるため、今回は対象外とします。

Martin Fowler は、「GUI のアーキテクチャ」(bit.ly/11OH7Y、英語) の中で、MVC について次のように述べています。「MVC について読んでいるユーザーとそのユーザーの立場によって MVC の考え方は異なりますが、すべて "MVC" と記載されています。この説明を読んでもそれほど混乱しない方は、伝言ゲーム方式で伝えられることによる MVC の誤解の影響を受けていると言えます。」そして、「コントローラーとはそもそも何か」(bit.ly/7ajVeS、英語) でこの点を次のようにまとめています。「概してコンピューター科学者には、用語に意味を詰め込みすぎるという困った癖があります。つまり、コンピューター科学者は、同じ言葉に複数の (ときとして矛盾する) 意味を割り当てがちです。」

Smalltalk MVC はさらに複雑です。これは、開発者と優れたアーキテクトの間に、アーキテクト環境に関して共通の核となる経験がないためです。このように、意味の詰め込みすぎと "伝言ゲーム" が物事をいっそう複雑にします。ほとんどの開発者はコントローラーを使用する必要に迫られることがないため、コントローラーの定義さえわかっていません。コントローラーの機能は、常に OS で制御されてきました。不足している共通の核となる経験を補う情報を知れば、MVC が実は理解しやすいことと、MVC の "C" は MVP の "P" とはまったく共通点がないことがわかります。

コントローラーには、明確な起源があります (この起源を理解しておく価値はありますが、現代のテクノロジに沿って考えると、MVC の最新アプローチとはつじつまが合わない点もあります)。この起源について、MVC の考案者である Trygve Reenskaug が、1979 年に「モデル - ビュー - コントローラー」(bit.ly/2cdqiu、英語) の中で説明しています。このドキュメントでは、まずコントローラーの目的について考察しています。Reenskaug の説明を引用します。

「コントローラーは、ユーザーとシステムをつなぐものです。関連するビューを調整して画面の適切な場所に表示し、ユーザーに入力を促します。ユーザーに入力の手段を提供するには、メニューなど、コマンドやデータを渡す手段を提示します。コントローラーは、このようなユーザーからの入力を受け取って、適切なメッセージに変換し、変換したメッセージを 1 つ以上のビューに渡します。

コントローラーは、決してビューを補完してはいけません。たとえば、複数のノードのビューの間に矢印を描いてビューを結び付けてはいけません。

反対に、ビューは、マウス操作やキーストロークなどのユーザー入力を認識してはいけません。コントローラーでは、一連のユーザー コマンドを正確に再現するメッセージをビューに送信するメソッドを記述できる必要があります。」

図 1 に、この考え方を示します。

MVC オブジェクト指向プログラミング (OOP) における "メッセージ" とは、メソッドを実行する手段です。"メッセージ" と呼ばれるのは、当時は仮想呼び出しが新しい概念だったので、静的関数呼び出しと区別する必要があったためです。Trevor Hopkins と Bernard Horan による書籍『Smalltalk, an Introduction to Application Development Using VisualWorks』(Prentice Hall、1995 年) の第 1 章第 2 節では、次のように説明されています。「(前略) 送信されたメッセージを受信側のオブジェクトが認識すると、このオブジェクトの内部操作 (メソッド) の 1 つが実行されます。この結果、(オブジェクトの内部変数を 1 つ以上操作して) コンピューター処理が実行されることになります」 (注: Prism では、この "メッセージ送信" という OOP の概念を EventAggregator を通じて実現しています)。

この書籍の第 29 章「モデル、ビュー、およびコントローラーの概要」では、「コントローラーは Controller クラスから派生する」と説明することで、Smalltalk MVC の役割を端的にまとめ、「このクラスのインスタンスは、マウスとキーボードを表すセンサーを参照することで、入力を処理できるようにしています」と表現しています。さらに、「コントローラーから呼び出されるアクションには、モデルとの通信 (図 1 参照) と、モデルに影響を及ぼさないビューとの通信の 2 つがある」と説明しています。

Controller Receives Input and Sends Message (Method to Execute); Views Can’t Catch User Input
図 1 コントローラーは入力を受け取ってメッセージ (実行するメソッド) を送信する。ビューはユーザー入力を受け取れない。

Smalltalk MVC では、"すべての" ビューにはコントローラーが 1 つあり、一度にアクティブにできるコントローラーは 1 つだけです。当初の Smalltalk MVC では、UI をポーリングしていました。つまり、トップレベルの ControlManager からアクティブなビューの各コントローラーに制御を求めているか確認します。制御を受けることができるのは、カーソルを保持するビューのみです。ビューが読み取り専用であれば、制御を拒否する NoController クラスを使用します。サブビューを備えたビューでは、サブビューのコントローラーにポーリングします。制御を受けるコントローラーはキーボードやマウスの結果を問い合わせて、必要に応じてマウスの移動やボタンのクリックなどのメッセージをビューまたはモデルに送信します。MVVM の概念では、これはビューの分離コードやビューモデルのコマンドを通じた、制御イベントのサブスクライブに相当します。ユーザーがコントロールを操作すると、適切なメソッドが呼び出されます。

ここまでの説明で、MVC など、イベントが自動的に処理されない環境内での、コントローラーの目的の意義がわかり始めたと思います。Smalltalk MVC 開発者とは異なり、WPF 開発者は、キーボードのバッファーやパッケージに問い合わせを行ったり、イベントを生成したりする必要がありません。イベントをサブスクライブするだけで、マイクロソフトのイベント パターンを通じてイベントが適切なメソッドに "自動的に" 渡されます。このような知識があれば、おそらくここからの説明の意味が変わり、わかりやすくなるでしょう。

Steve Burbeck は、「Smalltalk-80 のアプリケーション プログラミング: モデル - ビュー - コントローラー (MVC) の使用方法」(bit.ly/3ZfFCX、英語) の中で、次のように述べています。

「コントローラーは、ユーザーからのマウス入力やキーボード入力を解釈し、必要に応じてモデルおよびビュー、またはどちらかに変更を指示します。最後に、モデルはアプリケーション ドメインの動作とデータを管理し、モデルの状態に関する情報の要求 (通常はビューから送信) に応答し、状態の変更を求める指示 (通常はコントローラーから送信) に応答します。」

図 2 は、この概念を図解しています。

Smalltalk Model-View-Controller
図 2 Smalltalk のモデル - ビュー - コントローラー

混乱しがちなトピックを整理するための最後の論点を説明しているのが、Andy Bower と Blair McGlashan による PDF ダウンロード形式のドキュメント「3 要素の仕掛け: Dolphin Smalltalk MVP アプリケーション フレームワークの進化」(bit.ly/o8tDTQ、英語) です。これは、この話題に関してこれまで読んだことがあるドキュメントの中でも特に包括的なドキュメントです。Andy と Blair は、コントローラーについて「もちろん、ビューはドメイン データの表示を担当しますが、コントローラーは、ユーザー ジェスチャそのものを処理し、最終的には、このデータに対するアクションを実行します」と述べています。

この最後の論点をここで取り上げるのは、別の定義を紹介するためです。このドキュメント (および MVC に関する他のドキュメント) を完全に理解するには、"ジェスチャ" の意味を理解する必要があります (図 1 参照)。調査の結果見つけたのは、「UIL と Motif による GUI プログラミングの概要」(bit.ly/pkzmgc、英語) です。ここでは、次のように説明しています。

「Motif プログラムの手順で重要なことは、ユーザーがアクションを要求するまで Motif プログラムは何も実行しないことです。アクションを要求するには、メニュー項目の選択、ボタンや他のウィンドウのクリック、またはキーの押下を行います。これらの操作をまとめて、ユーザー ジェスチャと呼びます。各ジェスチャからは、いずれかのタスクを実行するアプリケーション関数がトリガーされます。」

「3 要素の仕掛け」の共著者である Andy Bower は、"ジェスチャ" についての見解を次のように語ってくれました。

「私見では、ジェスチャとは 1 つ以上のユーザー イベントをまとめて有用性を高めるものです。

たとえば、TextController は、キーを押したことと離したことを示すイベントをまとめて、1 つの"キー操作" ジェスチャに変換します。同様に、SelectionInListController (リスト ボックスにアタッチされるコントローラー) は、マウスを押しながら動かし、マウスを離したことを示すリスト内の複数のイベントをまとめて、1 つのリスト "選択" ジェスチャとして処理します。

このように考えると、現代のイベント駆動型 OS では、このジェスチャ処理のほとんどが既に自動的に行われていると言えます。」

コントローラーに関する考え方をまとめると、コントローラーの機能は、ここで紹介したさまざまな MVC でかなり一貫していることがおわかりいただけると思います。マイクロソフトのコントロール (ウィジェット) は "ユーザーからのマウス入力とキーボード入力" を処理するため、開発者の作業はそのイベントをサブスクライブして、実行が必要なメソッドを指示するだけです。指示されたメソッドは、優れたコントロール内の "コントローラー" によって実行されます (OS レベルで処理されます)。そのため、「3 要素の仕掛け」で明確に述べられているように、コントローラーは必要ありません。コントローラーがなければ、Windows アプリケーションはモデル - ビュー (Model-View) パターンになります。MVC とそのアプリケーション モデルやプレゼンテーション モデルについて調べる際は、コントローラーがなければ 3 要素ではなくなるため、この点に留意が必要です (図 3 参照)。

Without the Controller, It Has Been Model-View (not Model-View-Controller)
図 3 コントローラーがなければ、(モデル - ビュー - コントローラーではなく) モデル - ビューとなる

MVC の定義をあいまいにしているのはコントローラーだけが原因ではないことも指摘しておきましょう。Smalltalk MVC では、ビジネス ロジックやドメイン ロジックがモデルに含まれ、VisualWorks MVC では、アプリケーションモデル (ApplicationModel) に、1 つ以上のビジネス オブジェクトやドメイン オブジェクトをユーザーに表示するのに必要な "アプリケーション" ロジックが含まれます (図 4 参照)。「3 要素の仕掛け」では、これをさらに詳しく説明しています。アプリケーション モデルとプレゼンテーション モデルの機能が同じで、大きな違いはプレゼンテーション モデルではビューにアクセスできないことだと考えると (Martin Fowler は用語に意味を詰め込まないよう明確に区別しました)、本質的には MVVM と同じパターンになるので、WPF 開発者にとっては "プレゼンテーション モデル" の方が理解しやすいでしょう。MVVM の考案者である John Gossman は、この点について bit.ly/pFs6cV で公開しているブログ記事「プレゼンテーションモデル (PresentationModel) と WPF」(英語) で説明しています。Martin Fowler と同様に、John Gossman も用語に意味を詰め込みすぎないよう注意しており、MVVM の定義を実に明確にしています。いわく、MVVM とは、「WPF 固有のバージョンのプレゼンテーションモデル パターン」です。

VisualWorks Model-View-Controller
図 4 VisualWorks のモデル - ビュー - コントローラー

MVC をありのまま把握できるようになると、モデルとビューの真の役割を理解できます。基本的に、ビジネス ロジックやドメイン ロジックを含めるのはモデルとビューの 2 つだけです。「3 要素の仕掛け」を読むと、アプリケーション モデルの役割がプレゼンターに移動したことと、コントローラーを単純にプレゼンターに置き換えられないことがわかります。コントローラーとプレゼンターの意味は同じではないため、置き換えるのは不適切です。

MVP パターン

MVP について相応の注意を払いながら説明することは、この記事の範囲を超えています。さいわい、「3 要素の仕掛け」や Potel による「モデル - ビュー - プレゼンター (MVP): C++ および Java 向けの Taligent プログラミング モデル」(bit.ly/dF4gNn (英語) からダウンロードできる PDF ドキュメント) など、多数のドキュメントでこうした説明が行われています。

ただし、ここでは、MVC から MVP への進化を引き起こした重要な点が「3 要素の仕掛け」で次のように述べられていることだけは指摘しておきます。

「MVC の厄介な特徴は、少なくとも Dolphin の場合、コントローラーの概念が Windows 環境にうまく適合しなかったことでした。Microsoft Windows には、現代のグラフィカル オペレーティング システムの大半と同じように、ユーザー インターフェイスを構築できる一連のネイティブ ウィジェットが備わっています。これらの "ウィンドウ" には、コントローラーの機能のほとんどが、基盤となるオペレーティング システムの制御の一部として既に組み込まれています。」

また、Martin Fowler による「GUI のアーキテクチャ」には、「このようにウィジェットを直接操作することが必要な点は、多少不器用な回避策と見なされていますが、モデル - ビュー - プレゼンター手法の開発の助けになりました」という記述があることもお伝えしておきます。MVVM によってプレゼンテーション モデルの考え方が多くの WPF 開発者に浸透していることから、この点を理解することは重要です。WPF 開発者は、ビューを直接更新することは "不適切なプログラミング" だと考えています。ビューを参照すると、(主にこの規則から) 別のビューでビューモデルを再利用できなくなるため、MVVM とプレゼンテーション モデルの場合にはこの規則が当てはまると言えます。Smalltalk MVC が MVP パターンに進化した理由の 1 つが、この規則でした。MVPVM の場合、開発者はビューとビューモデルに直接アクセスできます (密結合されています)。そのため、ビューとビューモデルを完全に分離したままにできます (図 5 参照)。1 つのビューは複数のビューモデルを再利用でき、複数のビューが 1 つのビューモデルを再利用できます (詳細については、後で MVPVM パターンの説明時に紹介します)。これが、MVPVM に多数備わるメリットの 1 つです。

Model-View-Presenter, Supervising Controller
図 5 モデル - ビュー - プレゼンター (監視コントローラー (Supervising Controller))

Andy Bower は、この問題についてさらに説明するために、次のように述べています。

「プラグ可能な再利用こそ、すべてのパターンの目的であることを、指摘しておくべきでしょう。できる限り疎結合を保ち、インターフェイスをできる限り少なくすれば、コンポーネントを組み合わせ直す方法で最大限に再利用できます。

しかし、モデルには、関連付けられたビューとプレゼンターとの間に互換性を保つ必要があるインターフェイスが実質 2 つあります。1 つは標準の関数呼び出しインターフェイスで、値の取得と設定、およびコマンドの実行に使用します。もう 1 つはイベント インターフェイスで、ビュー (オブザーバー パターン) で想定しているインターフェイスと同じでなければなりません。こうしたインターフェイスの組み合わせを "プロトコル" と呼びます。

たとえば、Dolphin MVP の場合、リスト ウィジェット (3 要素) には互換性のあるプロトコルを備えた 3 つのコンポーネント (ListModel、ListView、および ListPresenter) が必要です。」

ビューを直接更新してはいけない理由を理解し、この理由から、ビューを更新できない制約をなくしてオブジェクトを効率的に再利用できるようにする新しい設計パターンが生まれたことを認識したら、この進化によって可能になった新しい手法を受け入れることができます。皆さんはアジャイル環境で開発しており、"歴史が繰り返されるのを防ぐために" 考えているパターンを (コードと同じように) 変更する必要があります。

MVPVM パターン

最初にこのパターンを学んだのは、Prism のライフサイクルの初期段階、具体的には CompositeWPF の Drop 7 でした。そのとき、Prism の不思議な機能に混乱しましたが、MVP パターンに気付いたことが、理解のきっかけになりました。すぐに、(現在私が Prism の開発初心者に教えているように) プレゼンターを確認するだけで、コードとアプリケーションを理解するための出発点になることを学びました。コードを実行するしくみの学習は後回しにでき、重要なスケジュールには影響しません。そのため、学習の難所の影響を受けずに済みます。

この後説明する MVPVM コンポーネントの定義は、「3 要素の仕掛け」から適宜引用しています。このドキュメントの情報は参考になり、包括的かつ正確なので、できる限り役に立つ情報を示すという目的から、ここでは単純に「3 要素の仕掛け」の定義を引用することにします。これらの定義は、「3 要素の仕掛け」の執筆時点である 2000 年 5 月に MVP 向けに作成されましたが、現在の MVPVM にも当てはまります (図 6 参照)。

Model-View-Presenter-ViewModel
図 6 モデル - ビュー - プレゼンター - ビューモデル

(注: ここでは Prism を取り上げていますが、MVPVM は Prism でなくても機能します。MVPVM のさまざまなコンポーネントは、解決される (Unity や Managed Extensibility Framework (MEF) の依存関係挿入コンテナーによって疎結合される) のではなく、それぞれの実装に密結合されます。)

MVPVM: モデル

「これは、ユーザー インターフェイスから操作するデータです。通常、モデルはドメイン オブジェクトであり、このようなオブジェクトにユーザー インターフェイスを認識させないようにすることが目的です。」(「3 要素の仕掛け」より)

モデルとビューモデルの分離は、依存関係の挿入に関する懸案事項や、保存済みデータの作成、読み取り、更新、削除、列挙 (CRUDL) を行うビジネス ロジック層 (BLL) とデータ アクセス層 (DAL) での依存関係の挿入の使用法に関する懸案事項に対処するうえで必要です。MVPVM では、保存済みのモデル オブジェクトにアクセスできるのは DAL だけです。

MVPVM: ビュー

「MVP のビューの動作は、MVC とほぼ同じです。ビューの役割は、モデルのコンテンツを表示することです。データが変更されるたびにモデルから変更が適宜通知されることを想定しているため、標準のオブザーバー パターンに従い、ビューはモデルに "依存する" ことができます。そのため、MVC と同様、複数のビューを 1 つのモデルに接続できます。」(「3 要素の仕掛け」より)

(注: この引用を使用したのは、MVP が新しいパターンではなく、MVP が MVC から進化したときと同様、現在でも有効なことを強調するためです。ただし、引用文では "モデル" と述べていますが、MVPVM では "ビューモデル" を使用しています。)

MVPVM では、分離コードにコードを記述する必要がまったくありません。プレゼンターは、ビューへのアクセス、イベントのサブスクライブ、コントロールの操作、および UI の操作を必要に応じて実行できます。この機能は、この記事付属のマルチターゲット アプリケーションの開発時に役立つことが実証されました。"ユーザー" ListBox は、選択変更イベントのデータ バインドを認識しないため、3 つのプラットフォームすべてで機能する方法を考案しなければなりませんでした (プラットフォーム間で同じコードを共有するため)。ビューがアクティブになったら、WireUpUserListBox (図 7 の 174 行目参照) を呼び出し、ビューを使用して lstUserList コントロール (DataTemplate 内に存在) への参照を取得します。コントロールが見つかったら、SelectionChanged イベントに結び付け、ビューモデルの SelectedUser プロパティを更新します。この手法は、デスクトップ、Silverlight 、および Windows Phone で機能します。

Benefits of Being Able to Access the View Directly
図 7 ビューに直接アクセスできるメリット

ビューはビューモデルを認識しないため、ビューとビューモデルは密結合されません。ビューがバインドしているすべてのプロパティをビューモデルでサポートしている限り、ビューモデルからビューを簡単に使用できます。プレゼンターは、ビューの DataContext を適切なビューモデルに設定して、ビューを対応するビューモデルに結び付けます。

MVPVM: プレゼンター

「ビューはモデルのデータを表示しますが、ユーザー インターフェイスによるモデルの操作方法や変更方法を制御するのはプレゼンターです。プレゼンターにこそ、アプリケーションの動作の心臓部にあたります。さまざまな意味で、MVP のプレゼンターは MVC におけるアプリケーション モデルに相当します。つまり、ユーザー インターフェイスの動作を制御するほとんどのコードは、プレゼンター クラスに組み込みます。主な違いは、プレゼンターは関連付けられたビューに直接リンクされるため、ユーザー インターフェイスに特定のモデルを提供するうえでプレゼンターとビューが密接に連携できることです。」(「3 要素の仕掛け」より)

図 8 の左側に示すように、プレゼンターは、ドメイン オブジェクト (データ) を取得する必要がある、取得先 BLL のインターフェイスに依存しています。プレゼンターは、モジュールでの構成に応じて解決されたインスタンスを使用するか (図 8 の右下参照)、ブートストラップを使用して、データにアクセスし、ビューモデルにデータを設定します。

Security Module Code
図 8 セキュリティ モジュールのコード

通常、MVPVM のコンポーネントではプレゼンターだけが密結合されます。プレゼンターは、ビュー、ビューモデル、および BLL インターフェイスに密結合されます。プレゼンターは再利用を目的とした要素ではなく、特定の懸案事項、またはその懸案事項のビジネス ロジックやビジネス ルールに対処します。複数のエンタープライズ アプリケーションでプレゼンターを再利用できる場合、モジュールを再利用する方が適していることがよくあります。たとえば、すべてのエンタープライズ アプリケーションで再利用できるように、ログイン モジュール (プロジェクト) を作成する場合などです。インターフェイスに対してコーディングする場合、MEF や Unity などの依存関係の挿入テクノロジを使用してモジュールを簡単に再利用できます。

MVPVM: ビューモデル

「MVP では、モデルは純粋なドメイン オブジェクトで、ユーザー インターフェイスに関する想定 (リンク) はありません。」(「3 要素の仕掛け」より)

この定義のため、ビューモデルは 1 つのビューに密結合されず、多数のビューから再利用できます。同様に、ビューモデルはアプリケーション ビジネス ロジックを含まないため、複数のエンタープライズ アプリケーションからビューモデルを簡単に共有できます。そのため、再利用とアプリケーションの統合が進みます。たとえば、図 8 の右下の 28 行目をご覧ください。この SecurityCommandViewModel は、Gwn.Library.MvpVm.xxxx プロジェクト (xxxx は Silverlight、Desktop、または Phone) に含まれています。"ユーザー" ビューモデルはほとんどのアプリケーションで必要になるので、このビューモデルは再利用可能なコンポーネントです。デモ アプリケーション固有のビジネス ロジックをこのビューモデルに含めないよう、注意する必要があります。この作業は、MVPVM では難しくはありません。なぜなら、ビューモデル内ではなく、プレゼンターでビジネス ロジックを処理するためです (図 6 参照)。

(注: ビューモデルのプロパティをプレゼンターから設定すると、NotifyPropertyChanged イベントが発生し、新しいデータが存在することがビューに通知されます。通知後にビューモデルのデータに合わせてビューを更新するのは、ビュー自体の役割です。)

ビジネス ロジック層

BLL には、保存済みのモデル データの情報がなく、ドメイン オブジェクトとインターフェイスを厳密に処理します。通常は、依存関係の挿入を使用して BLL 内で DAL のインターフェイスを解決するので、ダウンストリーム コードに影響を及ぼさずに後から DAL を交換できます。図 9 の 34 行目では、デモ アプリケーションの IBusinessLogicLayer に MockBll という実装を使用しています。インターフェイスを対象に開発するため、1 行のコードだけで、このインターフェイスの運用環境向け実装に後で簡単に交換できます。

Registering BLL, DAL and Commands
図 9 BLL、DAL、およびコマンドの登録

ビジネス ロジックは BLL だけに制限されません。図 9 では、(IPresenterCommand の) 名前付きの型を登録して、依存関係の挿入をファクトリとして使用できるようにしています。ユーザーがいずれかのボタン (図 10 の 29 ~ 33 行目参照) をクリックしたら、基本クラスでコマンド パラメーターを解決 (インスタンス化) し、適切なコマンドを実行します。たとえば、LoginCommand (図 8 の右上参照) は、UserManagerView をアクティブにするコマンドです。このコマンドを関連付けるために必要だったのは、XAML の Button 用コマンドと SecurityModule のエントリ (図 8 の右下の 32 行目参照) だけでした。

DataTemplate for the UserCommandViewModel
図 10 UserCommandViewModel のデータ テンプレート

データ アクセス層

保存済みのドメイン データは、SQL データベース、XML ファイル、またはテキスト ファイルに保存することも、REST サービスから取得することもできます。MVPVM では、データの取得に必要な具体的な情報は DAL だけが保持します。DAL は、ドメイン オブジェクトだけを BLL に返します。そのため、接続文字列、ファイル ハンドル、REST サービスなどの情報を BLL に含める必要がありません。その結果、スケーラビリティと拡張性が向上し、DAL やアプリケーション構成ファイルに含まれない既存のコードに影響を及ぼさずに、DAL を XML ファイルからクラウド サービスに簡単に切り替えることができます。新しい DAL の単体テストが CRUDL 処理で機能する限り、現在のアプリケーションとその使用法に影響を及ぼさずに、新しい DAL を使用するようアプリケーションを構成できます。

歴史を理解して経験を有効活用する

patterns & practices チームのおかげで、MVPVM などの最先端テクノロジを使用して無事に顧客を成功に導くことができます。また、チームの速度、テクノロジ、およびパターンに遅れずに付いて行くことで、新しいテクノロジやパターンが登場するたびに、過去の経験を活かして新しい分野を理解しやすくなることがわかりました。

MVP は、patterns & practices を使用してアーキテクチャを学び始めた当初から使用されている、変わらない一貫性のあるパターンです。MVP を正当に評価するには、携わってきた開発手法の歴史、特に MVC のコンポーネントを理解する必要があります。検討しなければならない要素が多いので、これは簡単な作業ではありません。

しかし、開発作業の歴史とその進化の理由を理解すれば、新しいパターンの必要性と効果を把握しやすくなります。Prism とその複雑で魔法のような機能の場合でも、この歴史を学び新しいパターンの必要性と効果を知ることで、学習の難所を回避できます。このパターンが Prism の初期段階に登場して以来携わってきたプロジェクトのうち、成功を収めたすべてのプロジェクトでは、MVPVM に関する問題、作業速度の低下、解決できない課題が発生しておらず (進化の結果、このような問題が解消されたようです)。そのため、スケーラブルで拡張性が高く、安定したアプリケーションを開発できるので、開発者の作業速度を向上できます。

Bill Kratochvil は、フリーの契約社員であり、医療業界の大手企業の機密プロジェクトに携わる、選り抜きの開発者チームの第一線に立つ技術者兼設計者です。彼自身は、テキサス州のアマリロに拠点を置く Global Webnet LLC に勤務しています。

この記事のレビューに協力してくれた技術スタッフの Andy BowerChristina Helton、および Steve Sanderson に心より感謝いたします。