対象となる読者
- C# 経験者で C#言語を理解している
- MVVM パターンを理解したいが良く分からない
- WPF を利用する
- アーキテクチャについてある程度触れたことがある
- WPF の分離コード(xaml.csファイル)の記述が多くなっていて気になる
この記事を書くきっかけ
最近よく Qiita を利用させて貰っていて、何か返したいと思ったから。
また、今までずっと MVVM などのアーキテクチャパターンを勉強したいと思っていたが、ずっと取っ掛かりが持てなかったから。
MVVMパターンの特徴
- 処理部分を Model とする
- 表示部分を View とする
- 表示と処理をつなぐ役割を ViewModel とする
- ある程度以上の規模を持つアプリケーションに有効
- WPF あるいは UWP, MAUI を利用している
なぜ MVVM パターンを使うのか
MVVM パターンは
- INotifyPropertyChanged インターフェイスを実現した ViewModel クラスをDataContext などを使ってデータバインディングを行う
あるいは
- Button に ICommand インターフェイスを実現したクラスを XAML で紐づける
ことにより
イベントハンドラを 分離コードで記述せずに、あるいは、最小限に抑えることを目的としている と思われる
なぜ分離コードを最小限に抑えるのか
関心の分離が目的と思われる。
分離コードにイベントハンドラを記述していくことは関心が集中することに繋がる。分離コードが俗に言う神クラスになる可能性を持っている。
関心が一つのクラスに集中すれば、デバッグは大変で、機能追加も難しくなる。
だから、イベントハンドラの記述を xaml.cs ファイルの分離コードに記述し続ければ修正、拡張の難しいプロジェクトになってしまう。
だからそれを避けるために、関心を分離するために、つまり
コードをシンプルにするために、分かりやすく、修正、拡張しやすくするために MVVM パターンを使うと思われる。
なぜ MVVM パターンが分かりずらいのか
Model, View は比較的分かりやすい。しかし、ViewModel とは何なのか、どのような役割(目的)を持っているかが分からないから MVVM パターンはとっかかりづらいのではと思われる。
また、MVC や MV(R)P など、似た名前があってどれを勉強すれば良いか混乱するのもあると思います。
その場合には、後述する 「ViewModel を使うとなぜ関心が分離出来るのか」を見て頂けたらと思います。
ではその ViewModel とは何なのか
INotifyPropertyChanged インターフェイスを実現したクラスや ICommand インターフェイスを実現したクラスを持っているクラスと連動する、あるいはそのもののクラス。
バインディングを実現させるための要素だと思われる。
よく聞くバインディングって何よ
バインディングとは、例えば、テキストボックスってあるじゃないですか。アプリで文字を入力するやつ。
あれって単体では、枠に文字を入力するだけなんですが、入力した時に、それを使って処理をしたい。あるいはそのデータを他の部分と連動させたい。
そんな時に、処理や他の部分に繋げる機能の一つがバインディング(接合する)だと僕は思っています。
で、INotifyPropertyChanged インターフェイスと ICommand インターフェイスって何よ
INotifyPropertyChanged
データバインディングを実現するために、バインディングソースとして機能させるためのインターフェイス。
つまり、変更などがあった際に、バインディングターゲットに通知を行うためのインターフェイス。
ICommand
ボタンを使う時に、イベントハンドラを分離コードに記述せずに、処理だけを一つのクラスに定義でき、このインターフェイスを実現することで、XAML から呼び出して、ボタンコントロールに登録できる。
バインディングターゲットとかバインディングソースって何よ
バインディングターゲット
バインディングターゲットとは、データに変更があった時に、それを反映する側のコントロール。基本的に View などの表示部分が多い。
バインディングソース
バインディングソースとは、表示されているコントロールから入力した実際に処理する側のデータ。MVVM では基本的に ViewModel 部分などに存在するプロパティなどにしていく。
なぜ ViewModel を使うと関心を分離出来るのか
WPF では、ViewModel を使わないと前述した xaml.cs ファイルが段々と神クラスへと膨張してしまう。つまり ViewModel や MVVM パターンとは、WPF の持つ xaml と分離コードの xaml.cs ファイルを神クラスにしないための、つまり WPF 固有のアーキテクチャパターンだと僕は考えます。
また、まだ他のパターンは勉強していないのですが、他のツールでは、関心の分離を行うアーキテクチャパターンの呼称が MVC(ASP.NET と ASP.NET Core) や、MV(R)P(Unity/C#)と呼び名を変えているのではないか。つまり、ASP.NET を勉強する人は MVC を、Unity を使う人は MV(R)P を勉強すると関心を分離出来るのではないでしょうか。
追記・ASP の MVC は元々 Java で普及していたアーキテクチャパターンで、ASP.NET でそれを2008 年に実現させた物だそうです。
元を辿ると Smalltalk で1979年に考案されたところに行き着くようです。
対する MVVM は2005年に WPF のために考案され、2006年に実現されたらしいのですが、MVC,MVVM は共に影響しあって発展したようです。
ですので、 MVC を勉強するのなら、Java や ASP.NET で、 MVVM なら WPF を使って勉強する(WPF でないと MVVM は勉強出来ない!)と理解を助けるのではないかと思います。
MVC を Unity を使おうとしたり、MVVM を Java で使おうとすると上手く行かないのではないかと思いました。
それと、簡単に調べただけですが、UWP や MAUI アプリも xaml ファイルを利用するので MVVM は使えるようです。訂正しました。
その他の言語やフレームワークでは、クリーンアーキテクチャを勉強すると関心の分離を助けると思われます。
まとめ、どういう時に MVVM パターンを使うのか
ある程度の機能を持つアプリを作る時に、イベントハンドラを xaml.cs 上で記述する部分が多くなって神クラスになってきたな、と思ったら、ICommand, INotifyPropertyChanged, MVVM, データバインディング の単語を思い出して検索、勉強すると幸せになれるかも知れません。