前回のMVVMに関する記事を書いてから約1カ月経ちました。この1カ月で非常に熱心に調べ、実装してきたのでありがちな間違いも紹介しながら今回はより正しく理解できるように記事を纏めてみました。

MVVM初学者が陥りがちな「コードビハインドにはコードを書かない」「どこに処理を書くべきか分からない」といったことについても書いています。

前回の記事

MVVMって何だっけ

かりまたかりまた

りんちゃん、MVVMって聞くと、何をイメージする?

りんちゃんりんちゃん

にゃ~、次の3つかにゃ~。

  • コードビハインドには絶対にコードを書かない
  • ViewModelとModelのどちらに書くべきなのか迷う処理がある
  • ViewModelからModelを呼び出してModelから値を受け取る

かりまたかりまた

なるほどなるほど。りんちゃんはMVVMの間違った理解をしているかもしれないね!

なんだとさんなんだとさん

なん…だと…

MVVMを体系的に学ぶ

かりまたかりまた

MVVMに対してのみスポットライトを当てるのではなく、もっと大きな枠組みから話をスタートさせます。まずは一番大きな枠組みのSoCからです。

SoC (Separation of Concerns)とは?

関心の分離(かんしんのぶんり、英語: separation of concerns、SoC)とは、ソフトウェア工学において、プログラムを機能面において可能な限り重複がない、複数の機構に明確に分割することをいう。ここでいう「関心(関心事)」とは、プログラムのある機能や振る舞い、目的のことである。

かりまたかりまた

Wikipediaさんはこう仰ってる訳ですが、なんのこっちゃわからん。そもそも、SoCってどこから出てきた|д゚)!という感じですがまあ落ち着いてください。

かりまたかりまた

MVVMとはUI (Xaml)UIにまつわる部分 (ViewModel)、そしてLogicに分離するアーキテークチャです。そしてこの 「分離をする」 という根源的な考え方がSoCです。

SoCの具体的な例

りんちゃんりんちゃん

Wikipediaにも例に挙げてあるように、HTMLが良い例なのにゃ~。書こうと思えばHTMLの中にjavascriptCSSを一緒くたにして書くことができるのにゃ~。

りんちゃんりんちゃん

やってみるとわかるが、全てを一つのファイルに詰め込むとすぐに限界が来るのにゃ~。そこで 「関心の分離」 なのにゃ~。

りんちゃんりんちゃん

UIHTMLCSSで、ロジックはjavascriptでそれぞれ別のファイルに分けてやる事で見通しがよくなるのにゃ~。一言でいえば、「分業」と言えそうなのにゃ~。次に、PDSについてだにゃ~。

PDS (Presentation Domain Separation)とは?

かりまたかりまた

残念ながらまだMVVMについての話ではない!一番大きな枠組みとして、根幹にSoCという考え方があると言いました。では、次に大きな枠組みと言えば何か?その答えがPDSです。

プレゼンテーションとは?ドメインとは?

かりまたかりまた

PDSPはプレゼンテーションを指しますが、一体こいつは何を指しているのか?というと、UIの事を指しています。じゃあDomainは何だ?と言うと、ロジックの事を指しています。

かりまたかりまた

つまりこのPDSという得体の知れない単語は、 UIとロジックを分離しようね! という事を指し示している訳ですね。なるほど簡単♪

改めてMVVMとは?

かりまたかりまた

さて、ようやく本題です。MVVMUI (Xaml)UIにまつわる部分 (ViewModel)、そしてLogicに分離するアーキテークチャと冒頭で述べました。これを先ほどのPDSの考え方と比較しててみるとこうなります。

かりまたかりまた

そんな大差ないよね!UIの部分がVとVMに分かれている事が見て取れます。まあこうなるのは当たり前ですよね。MVVMの根幹的な考え方がSoC (関心の分離)PDS (UIとロジックの分離)なのですから。

かりまたかりまた

要は、プログラム全体をどういう構成に切り分けていくか?という事だけに着目している訳ですね。

再度、改めてMVVMを振り返ってみる

かりまたかりまた

さてさて。冒頭で私はりんちゃんにこう問いかけました。「MVVMって聞くと、何をイメージする?」と。ここまで述べてきたように、MVVMとはプログラム全体をどう切り分けていくかの指針でしかありません。

MVVMではコードビハインドに何も書かない?

かりまたかりまた

ネット上で調べるとよく書いてあるのが「MVVMではコードビハインドには何も書かない」とあります。確かにUIとロジックの分離 (PDS)という観点から言えばそうかも知れませんが、コードビハインドに何も書かないからMVVMになる!という考え方は完全に逆です。

かりまたかりまた

あくまでも、MVVMに則る為にコードビハインドに極力コードを書かないようにしている訳です。

MVVMでもコードビハインドにコードを書く場面とは?

かりまたかりまた

「コードビハインドにはコードを極力書かない」と書きましたが、裏を返せばコードビハインドに書く場合があるということです。それはどういう場合か? メッセージボックスやダイアログを表示させる場合 にコードビハインドに書きます。

かりまたかりまた

ここでは詳しく触れませんが、メッセージボックスで「Hello Wolord!」とダイアログで表示させたい場合、どこに書くのが正しいのでしょうか。世間的には散々議論されたようでして、MessengerパターンというViewのコードビハインドでダイアログを表示させるのが自然だという答えに行き着いたようです。

かりまたかりまた

なので必ずしも、「コードビハインドにはコードを書かない!」という事にはなりません。寧ろ、UIとロジックを分離した結果、コードビハインドに書くべきという考え方になっているわけですね。

ViewModelに書くべきかModelに書くべきか悩む場面

かりまたかりまた

MVVMを学び始めた時に処理をどちらに書くべきかで悩む事が多いのではないのでしょうか。別にViewModelに書いてもModelに書いても変わんないと思うけどな~。というファジーな理解。誰しもあると思います。

かりまたかりまた

どこに処理を書くべきか迷った場合には思い出してください。MVVMUI (Xaml)UIにまつわる部分 (ViewModel)、そしてLogicに分離するアーキテクチャだと。(本日、3度目)

かりまたかりまた

つまり、書こうとしている処理がUIに関する処理であれば勿論ViewModelに書くべきだし、そうでなければModelに書く必要があるのです。つまりそもそも、処理を書く場所に迷ってはいけないです。迷う場合は理解が足りてない可能性が非常に高いです。

ViewModelからModelを呼び出して値を直接受け取る?

かりまたかりまた

Modelに定義しているメソッドの戻り値は何型であるべきでしょうか。基本的にはVoid型です。

りんちゃんりんちゃん

え?値を返さないのにどうやって値を受け取るのにゃ~?

かりまたかりまた

そう思われる方、いらっしゃると思います。私も最初はよく分からなかったのですが答えは明快でModelのインスタンスを作成しておき、インスタンスの状態を受け取れば良いだけです。

Void型で返すメソッドを実行して値を受け取る具体的な方法
かりまたかりまた

字面だけだとイメージが湧かないと思うので、以下のような足し算を行う計算クラスを用意しました。

かりまたかりまた

使い方として、ViewModel側でこの計算クラスのインスタンスを生成しておき、何かしらのタイミングでAddメソッドを呼び出す。戻り値はVoid型なのでそのまま値は返ってきませんが、予め生成していたインスタンスのAddResultプロパティにアクセスすることによって値を取得する事ができます。

かりまたかりまた

このように、Modelから直接値を受け取らないようにすることで、ViewModelModelを疎結合にすることができます。

MVVMを学ぶにあたって参考にさせて頂いたサイト

かりまたかりまた

上記のサイトを穴が開くほど読み直しました。まだまだ理解が足りていない部分もあるとは思いますが、1カ月前の私よりかは進化できたと思います。次回はPrismを使用した記事を書いてみたいと思います。

まとめ

  • SoC (関心の分離) ⊃PDS (UIとロジックの分離) ⊃ MVVM という包含関係
  • MVVMは必ずしもコードビハインドにコードを書かない訳ではない
  • 処理を書く場所に迷ったらMVVMへの理解が足りていない可能性が高い
  • ViewModelとModelを疎結合に保つ為にModel内のメソッドの戻り値はVoid型にする