Model-View-ViewModel (MVVM)とは
Model-View-ViewModel (MVVM) は、ユーザーインターフェース(UI)を持つ
ソフトウェア開発において、その構造を整理するためのアーキテクチャパターンの一つです。MVVMは
ソフトウェアをModel, View, ViewModelの3つの主要な要素に分割することで、
ソフトウェアの保守性・開発生産性を向上させることを目指します。このパターンは、プレゼンテーション層とドメイン層の分離を促し(V-VM / M)、また宣言的なViewを分離し、状態とマッピングを明確に分離します(V / VM)。
MVVMパターンは、Model-View-Controller (MVC) パターンの進化形であり、特にPresentation Modelパターンを直接の祖先としています。もともとはMicrosoftのユーザーインターフェースサブシステムである
Windows Presentation Foundation (WPF) やSilverlightで生まれた概念ですが、現在ではAndroidやウェブブラウザ上の
JavaScript環境でも広く利用されています。
歴史的背景
MVVMパターンは、2006年11月21日にリリースされた
.NET Framework 3.0に実装されたWPFとSilverlightをサポートするために考案されました。Microsoft MVPのJosh Smith氏のレポートがこのパターンの普及に貢献しました。当初はWPFやSilverlightに特化したものでしたが、現在ではMVCやMVPなど、他のドメインにも適用されています。
WPFの開発に携わったJohn Gossman氏、Josh Smith氏、Karl Shifflett氏などのMicrosoftのアーキテクトたちが、このパターンに関する情報をオンラインで発信し、その普及を後押ししました。このパターンは、model-view-binder (MVB) とも呼ばれることがあります。
MVVMが解決する課題
UIを持つ
ソフトウェア開発では、ドメインを担当するエンジニアとUIをデザインするデザイナーが協力して作業しますが、使用するツールや言語が異なることがよくあります。MVVMは、この不一致を許容することを課題の一つとしています。
また、ドメインデータとUI、すなわちModelとViewの間には、表示(Model→View)と操作(View→Model)の関係があります。単純なケースではModelの状態がそのままViewに表示され、Viewの操作がそのままModelの状態変更に反映されます(
データバインディング)。しかし、実際にはViewとModelは1対1で対応しないことが多く、Model内の複数の要素から算出される値がViewでの表示に適していたり、Viewの操作に基づいた演算結果をModelに適用したい場合があります。結果として、状態を持つModelとは別に、View自体にも状態を持たせる必要が出てきます。MVVMは、このViewが持つ状態の表現という課題も解決します。
MVVMの解決策
MVVMパターンは、ModelとViewの開発プロセスにおける差異を許容し、Viewの状態を表現するために、
ソフトウェアをModel, View, ViewModelの3つの要素に分割します。
Model: アプリケーションのドメイン(問題領域)を表現します。データとビジネスロジックを含みます。
View: アプリケーションのデータをユーザーが見るのに適した形で表示し、ユーザーからの入力を受け取ります。UIの入出力が担当です。Viewは宣言的に定義され、状態を持ちません。
ViewModel: Viewを描画するための状態を保持し、Viewからの入力を適切な形に変換してModelに伝達します。ViewとModelの間の情報の伝達と、Viewのための状態保持のみを担当します。
MVVMでは、ModelとViewを明示的に分離することで、異なるツールを使って異なる人が開発できるようになり、効率的な協業を可能にします。また、ViewModelは「Viewのためのモデル」として導入され、Modelの値を
データバインディングに適した形式に変換して保持し、Viewの操作のためのコマンドを提供します。ViewModelによる状態表現によって、ModelはViewに依存せずに構築でき、Viewは
データバインディングを介してUI表示に専念し、ModelとViewをシームレスに繋ぐことができます。
MVVMの構成要素
MVVMは、以下の3つの要素で構成されます。
1.
Model: アプリケーションのドメインを表現し、ビジネスロジックやデータを扱います。ModelはViewの表示方法を知る必要はなく、UI以外のデータの入出力はModelに隠蔽されます。
2.
View: ユーザーインターフェースを担当し、データを表示し、ユーザー入力を受け取ります。Viewは状態を持たず、ViewModelを通じてデータにアクセスします。Viewは
テンプレートエンジンや宣言型のDSLに適しています。
3.
ViewModel: ViewとModelの中間に位置し、Viewの状態を保持し、Viewからの入力を処理してModelに伝達します。Viewは
データバインディング機構を介してViewModelと通信し、ViewModelの変更は自動的にViewに反映されます。
Model-View-Controller (MVC)との違い
MVVMはMVCから派生したアーキテクチャであり、いくつかの違いがあります。
MVVMのViewは、MVCにおけるControllerを包含しています。これは、GUIプラットフォームがControllerの役割を抽象化しているためです。現代のWebブラウザは、マウスカーソルの位置を自動で処理するため、以前のMVCのようにControllerでView要素上の位置をハンドリングする必要はありません。
MVVMのViewは宣言的に定義され、状態を持ちません。MVCのViewは状態を持つクラスで、Modelとは別にView State(UI遷移状態など)を保持していました。MVVMではこの責務はViewModelに移り、ViewはUI定義と値のマッピングにのみ責任を持ちます。
つまり、MVVMはMVCをModelとViewに分け、Viewを宣言型にし、Modelへの参照とViewの状態を持つ仲介役としてViewModelを導入したものです。
Presentation Modelパターンとの違い
MVVMと同様にMVCから派生したPresentation Modelパターンも、アプリケーションをView - Presentation Model - Modelに分割します。Presentation ModelはViewModelと同様にViewの状態を保持し、Viewは
データバインディングを介して自動的に描画します。
MVVMは、特にWPFにおける高機能なXAML(XMLベースのDSL)を利用することで、Presentation Modelよりもさらに進んだ特徴を持ちます。WPFでは、Viewを完全にXAMLだけで実装したり、ViewModelに対してViewを完全に抽象化し(異なるViewで差し替え可能にする)ことができます。
実装
MVVMはアーキテクチャパターンであり、フレームワークやライブラリではありません。MVVMを採用する際には、適切なモジュール分割を行い、必要に応じてMVVMを支援するフレームワークやライブラリを使用します。
一般的には、1つのModelを用意し、ViewをViewコンポーネント群に分割し、各Viewに対してViewModelを設定します(1:N:N)。
プラットフォームとフレームワーク
MVVMは多くのプラットフォームやフレームワークで採用されています。
XAMLベース:
[Windows Presentation Foundation]] (WPF), Silverlight, Windows Runtime (WinRT), ユニバーサルWindowsプラットフォーム], [[Xamarin.Forms
その他: android-binding, Knockout.js, AngularJS,
Vue.js, ASP.NET Core Razor Pages
問題点
MVVMを実装する際には、以下の問題点に注意する必要があります。
ファットViewModel: ViewModelがModelの変換だけでなく、ビジネスロジックまで実装してしまうこと。ViewModelはあくまでViewのための状態保持と変換に特化すべきです。
ファットView: Viewがコマンド発行だけでなく、引数の計算などでビジネスロジックを実装してしまうこと。ViewはUI表示に特化すべきです。
ViewModelの相互依存: 複数のViewModelが互いに依存してしまうこと。これにより循環参照が発生し、システムの状態が予測不可能になる可能性があります。
脚注
この文書は、MVVMパターンを理解するための基礎情報を提供しています。さらに深く理解するためには、関連ドキュメントを参照してください。
関連項目
Model View Controller (MVC)
外部リンク
John Gossman. (2005). Introduction to Model/View/ViewModel pattern for building WPF apps.
MVVMパターンを提唱した原典
Model-View-ViewModel デザイン パターンによる WPF アプリケーション
MVVMのModelにまつわる誤解
android-binding - Android開発用のMVVM用ライブラリ