ViewModel不要論について

MVVMにおいてVMが不要という論

VMがないとなるとModelとViewModelのMVでソフトウェアを構成する事になる。

 

UIのあるソフトウェアにおいてプレゼンテーションロジックがないものは存在しない。

 

MVアーキテクチャの場合、プレゼンテーションロジックをどこかに置かなければならない。

 

・Modelに置く場合

 

 ViewにバインドするプロパティをModelに用意することになる。

Model内にUIの制御プログラムが存在する事になり、

UIとUI部分を分離するという目的が達成できなくなる。

 

・Viewに置く場合

 

 ViewにUIの制御プログラムが存在することになり、

UIの見た目とコードを分離するという目的が達成できなくなる。

 

MVVMの基本的な考え方

・ソフトウェアはView,ViewModel,Modelから構成される。

・ViewはUIの見た目のみ決める。

・Viewにプログラム(ロジック)はない。
・ModelはUIに関与しない。
 
この4点のみ抑えておけば、ViewModelの役割と責務が理解できる。
ソフトウェアの内、ViewとModelを抜いた部分がViewModelとなる。
 
プレゼンテーションロジックがないソフトウェアは存在しない。
Viewにはプログラムがない。ModelはUIには関与しない。
なので、プレゼンテーションロジックはViewModelにしか置けない。
 
ViewMdelにはロジックがあってよい。

プレゼンテーションロジックとは何か

プレゼンテーションロジックとは何かがわからないために

MVVMのViewModelの意味、役割がわからないと思われる。

 

プレゼンテーションロジックとはUIを制御するプログラム

UI要素に直接アクセスするプログラムはプレゼンテーションロジックになる。

 

WPFのMVVMで説明する。

 

ViewにLabelを一個配置

ViewModelにLabelにバインドするプロパティAがある。

プロパティAはViewという具象を抽象化したものであり、Viewの抽象に

直接アクセスして制御するプログラムはプレゼンテーションロジックになる。

 

Modelからデータを読み取りバインドするプロパティに代入するだけの

プログラムもプレゼンテーションロジックである。

 

Viewのためのプロパティにアクセスするものはすべてプレゼンテーションロジック

 

 

誤解されているViewModel

・ViewModelはViewの抽象化である

 

 wikiにも記載されている言葉であるが、

抽象化は何のためにあるか。誰のための抽象化なのかの観点から考えると

抽象化する意味とは具象に直接さわらないで抽象化してアクセスする。

Viewを抽象化してアクセスするのは誰か?

ここで間違えやすいのはModelがViewをViewModelで抽象化してアクセスするという方式。この方式もありだが、直接的ではないが間接的にViewを制御していることになるので、UIとUI以外を分離した意味がなくなる。

 

Viewを抽象化してアクセスするのはViewModel自身

 

ViewModelの中から見て、Viewの抽象化が見えている。

 

ViewModel = View抽象化層 + ViewModelロジック

 

ViewModelはViewの抽象化を含んでいるが正しいと思われる。

抽象化という言葉自体が誤解を与える表現と思われる。

 

・ViewModelはViewをモデリングしたものである。

 

 Viewの抽象化ということでViewをモデリングしたものがViewModelであるという

のと、View”Model”という言葉からモデリングしたものという考えだと思わるが、

Modelにはソフトウェアの中核のデータとロジックという意味もある。

Viewのためのデータとロジックという理解が正しいと思われる。

 

・ViewModelはUIの都合を隠すためにいる

 

 ViewModelの役割がこれしかないと考えている人がViewModelを不要と判断する場合がある。

 WPFの場合、UIスレッド以外のスレッドからコントロールに直接アクセスすると例外がおこる。

このUIの都合はバインド機構が肩代わりしてくれている。

バインドするプロパティを用意すれば自動的に表示更新を行ってくれる。

プロパティはただの変数なのでUIスレッド以外からもアクセスできる。

ViewModelはバインドするプロパティを用意しているだけであり、UIの都合を隠すためにViewModelが何かをやっているわけではない。

Modelにバインドするプロパティを置けば動くものはできるがMVVMではない。

MVになるだけである。Model内にViewの抽象化を抱え込む形になる。

UIとModelの分離するのがViewModelの仕事である。ViewModelにはViewModelの仕事がある。

 

・ViewModelがバインドしている

 他でバインドしているからViewModelはいらない。

 

 ViewModelがバインドしているわけではない。

ViewModelはバインドするプロパティを用意しているだけ。

他でバインド機構が動いていたとしてもViewModelの役割はある。

 

・ViewModelにはロジックを書かない

 

 ViewModelにビジネスロジックは置かない。という言葉が誤解されて広まったものと

考えられるが。UIロジックは置かなければいけない。

ViewにはUIロジックは置かない。

ModelはUIを知らない。

UIロジックの置き場はViewModelしかない。

 

・ViewModelはViewとModelの橋渡し

 

 橋渡しだけなら、無くてもいいだろうという考えもあるが

 

 ViewModelの役割

 ・VIewへバインドするプロパティ、コマンドを用意する。

 ・Modelのデータを変換してView用のデータにする。

 ・Viewのロジック

 

橋渡しだけが仕事ではない。

 

 

 

 

 

 

 

 

 

Modelメソッドの戻り値はvoidでなくてよい

voidの場合もあるし、戻り値がある場合もある。絶対的な決まりがあるわけではない。

 

voidの場合

 

1.ただメソッド実行したいだけで戻り値がいらない。

 

  例)Model.Start();

 

2.メソッド実行して、非同期に動作する場合

 

 非同期に動作するのでメソッドの戻り値はvoidでよい場合もある。

 

 イベントで動作完了を報告する。

 メンバ変数で動作完了を報告する。

 

反例)

 実行開始成功したかどうかを返す場合もありうる。

 

設計しだいでケースバイケース。絶対的な指針ではない。

 

 

 

 

MVVMのよくある誤解

    ・Modelはデータのみ。データ処理をViewModelでやる。
   -> Modelの仕事をViewModelが奪っている。データ処理はUIの仕事ではない。

    ・ViewModelからネットワークアクセス
     -> ネットワークアクセスはUIの仕事ではない。

    ・ViewModelはViewのデータを用意するだけ、プログラムは入れない。
     -> Viewにプログラムはない。ModelにはUIのプログラムはない。
         よって、UIのプログラムはViewModelがするしかない。
         例)
            ・textbox入力のバリデーション(Modelでやる場合もある)
            ・ボタンのイネーブル/ディセーブル
            ・メニューチェックマーク

    ・ModelからViewModel,Viewにアクセスする。
      -> ModelがUIに依存している事になるのでUI処理とUI処理以外の分離というMVVMではない。


    ・VVM  ModelなしでViewとViewModelで構成する。
      -> 間違いではないが、MVVMではない。
         表示+入力 と それ以外は分離できるが、UI処理とUI処理以外が分離できない。
         

    ・Modelのメソッドの戻り値は当然voidである。

        -> voidの場合もあるし、戻り値を返す場合もある。設計による。

 
・Modelはステートフルである。
 -> 場合による。

WPFのMVVMとは何か

UIとUI以外を分離するアーキテクチャ


アプリケーション =  UI処理 + UI処理以外


UI処理以外をModelと呼ぶ。

アプリケーション = UI処理 + Model

UI処理の中をViewとViewModelに分離する。

アプリケーション = View + ViewModel + Model


アプリケーションのすべてのプログラム、データはView,ViewModel,Modelのどこかに所属する。


View,ViewModel,Modelの依存は一つのみ。方向は一方通行

View -> ViewMdel -> Model
(ViewはViewModelに依存、ViewModelはModelに依存)



・View

    Viewは画面表示と入力を担当する。データとプログラムは持たない。

    ViewはViewModelを知っている。
    =ViewはViewModelのインスタンスの参照を持っている
    =ViewはViewModelにアクセスできる。

    Viewの表示するデータはViewModelが持つ。
    Viewの入力処理(Command)はViewModelが持つ。



・ViewModel

ViewModelはUIの中の表示と入力以外全部を担当する。

ViewModelはViewを知らない。
=ViewModelはViewのインスタンスの参照を持たない。
=ViewModelはViewにアクセスできない。

Viewの表示するデータはViewModelが持つ。
Viewの入力の対応処理プログラム(Command)はViewModelが持つ。
UIとModelの橋渡しをするのはViewModelの仕事。


ViewModel = データ + プログラム


ViewModelの仕事
    Viewとのやり取り
    UIの仕事
    Modelとの橋渡し

だけ


ViewModelがViewに公開するもの

    プロパティ
    Command
    NotifyChangedイベント


ViewModelはModelを知っている。
=ViewModelはModelのインスタンスの参照を持っている。
=ViewModelはModelにアクセスできる。

ViewとViewModelをつなぐのはバインド機構

バインド機構はアプリーケーションの外側


・Model

Model = データ + プログラム

ModelはViewModelを知らない
= ModelはViewModelのインスタンスの参照を持たない
= ModelからViewModelにアクセスはできない。


Modelが公開するもの

    メンバ変数
    プロパティ
    メソッド

 デリゲート
    イベント

ViewModelとModel間については規定はない。
ModelはUIが切り替わっても動作できるように作ってもよいし、UIを固定して作ってもよい。


重要なのはUIとUI以外を分離すること。