質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.49%

[WPF] MVVMのModelの実装について

解決済

回答 2

投稿

  • 評価
  • クリップ 1
  • VIEW 11K+

score 10

現在、 WPF ⁺ Prism ⁺ ReactiveProperty で MVVM を勉強中です。

元々 Livet を使ってでWPFアプリを作ったことはあるのですが、現在の主流?が Prism ⁺ ReactiveProperty ということで、勉強しなおしているところです。

そこで気になった点がありますので、質問させていただきます。

 Model は最低2レイヤー構成となるのか?

Prism ⁺ ReactiveProperty で Model 層を実装すると、Model 層側で BindableBase を継承したクラスを用意し、それらにゲッターセッタープロパティを持たせることになると思います。

そこで違和感があったのですが、そもそも BindableBase という関心ごとは MVVM を実現するための機能であり、本来の業務ロジックとは異なります。また、クラスにゲッターセッタープロパティを持たせるとカプセル化を破壊することにつながる恐れがあると考えます。(一般的に、業務ロジックを扱うドメイン層では、ゲッターはまだしもセッターは極力使うべきではないと考えています)  

となると、BindableBase を継承したクラスは、対 ViewModel 向けの関心ごとを保持していることになるので、もはや MVVM の本来の目的である「ビューからモデル層を独立させる」ということが達成できていないのではと違和感を覚えました。

それを解決するためには、モデル層を以下の最低2レイヤー構成にするほうがいいのか?と思ってきました。

  • 「対 ViewModel 向けの BindableBase を継承したゲッターセッタープロパティを保持するクラス」を扱うレイヤー(つまりViewModelを向けにドメインオブジェクトを加工するレイヤー)
  •  純粋な業務ロジックや、いわゆるインフラ層(ここはプロジェクトや問題の複雑度により任意数のレイヤーとなる)

 んなわけないですよね?

自分で書いていてなんですが、ググってもそんな記事見つからないので、上記の疑問は根本から間違っているのかなと思います。  
しかし、Model層で「BindableBase を継承したゲッターセッタープロパティを保持するクラス」を他のドメインロジックと同じレベルで扱うことにかなりの違和感があるのは事実です。

ここら辺、 WPF ⁺ Prism ⁺ ReactiveProperty で開発経験のある諸先輩方はどのように考えていらっしゃるのでしょうか。  
私の間違っている部分をご指摘いただけると幸いです。    
感覚的な質問になってしまいますが、ご教授いただければ助かります。

宜しくお願い致します。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • Zuishin

    2018/08/11 11:54

    そのプロパティを使わないということです。使わせないために隠蔽しているので使ってはいけません。逆に使わなければならないプロパティであれば公開しなければなりません。隠蔽の行き過ぎです。

    キャンセル

  • hmmm

    2018/08/11 12:07

    UI側にバインドさせるようなデータは順不同で編集可能なのだから、絶対にsetterが必要ですよね。そのクラスにビジネスロジックを埋め込むのであれば、順不同で設定されても問題ないように単純なプロパティにする感じではないでしょうか?

    キャンセル

  • hihijiji

    2019/07/23 12:21

    「んなわけないですよね?」以降が「んなわけない」です
    Modelが層を持つなんて当たり前です。
    趣旨と関係ないModelの構造にまで触れていないだけです。

    キャンセル

回答 2

+2

解決済みのようなのでコメントするか悩みましたが、トゲトゲしいコメントしかついてなかったので一応。

仰るとおりINotifyPropertyChangedについては「主としてUIとのバインディングに利用される」ため、Model層への実装に違和感を覚える気持ちはわかります。

ただし、提供している機能はあくまで「プロパティの変更を通知する」ものです。
これ自体単独ではUIとは無関係の話で、オブザーバーパターン実現のひとつの手段に過ぎません。
そこの理解が違うと「ModelはUIを意識しないはずだからおかしい」と混乱するかもしれません。

System.ComponentModelに定義されているものは、あくまでコンポーネント(再利用可能な部品)を構成するものですので、UIと無関係なものでも使えます。そう考えると違和感はありませんよね。

逆にModelが「必ずINotifyPropertyChangedを実装するべき」という発想は間違いだと思います。
これは「目的を実現するための手段」であり、採用するかどうかはケース・バイ・ケースでしょう。

考えるべきは「Modelとして公開するこのオブジェクトのプロパティ変更は必ず通知されるべきか?」であり、そうでないケースがあった場合にINotifyPropertyChangedが実装されていたら、それはおかしいですよね。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

check解決した方法

0

もちょっとググってみると、私と同じ疑問を持っている人がmsdnのフォーラムでスレッドを立てていました。

WPF MVVMにおけるModelのViewModel, Viewへの対応について

Model にINotifyPropertyChanged を実装」すること

これが私が違和感を抱いていた部分なのですが、リンク先では色々な考え方が提示されており、参考になりました。

個人的には「Modelはビジネスロジックのみに集中しViewを意識しない」ということが最重要であり、そのために Model 層では INotifyPropertyChanged (つまり BindableBase)を実装すべきではないのかなと思いました。(その実現方法として、Model層をUI層向けとビジネスロジック向けに分離する方法もありだなと思いました)

しかし、利便性を重視して、Model 層では INotifyPropertyChanged を実装する方針もありだと思います。

勝手につらつら書きましたが、既に同様の議論が行われており、そこでは方針によりけりだという結論が出ていますので、それを参考にすることで本質問は終了させていただきます。

ありがとうございました。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/08/13 12:32

    ビューにバインドされるのはモデルではなくビューモデルです。
    モデルを直接バインドすることもありますが、それができなくても良いように(つまりモデルが INotifyPropertyChanged を実装しなくても良いように)ビューモデルがあります。

    そして質問にはプロパティの変更通知についての記述は何もなく、ゲッターセッタープロパティなるものとセッターを隠蔽したプロパティについて書かれています。

    この二つは全く別問題であり、それを混同する限り本質的な理解はできないでしょう。

    もう一度書きます。
    プロパティの通知とプロパティの隠蔽は全く別の問題です。
    これらが同じものにしか見えない人に説明するのは大変困難です。

    ですから、もう一度それらについて自分で読み直してください。
    私にはあなたに理解できるよう説明するのは無理そうです。

    キャンセル

  • 2018/08/13 13:05

    > ビューにバインドされるのはモデルではなくビューモデルです。
    https://qiita.com/hiki_neet_p/items/e381c687b0644c0e4978#viewとevent
    上記のブログ等、複数の Prism ⁺ ReactiveProperty でWPFを実装するサンプルで、モデル層で INotifyPropertyChanged を実装している例が提示されています。
    そこで、私はモデル層で INotifyPropertyChanged を実装することに違和感があったわけですが、Zuishin様は INotifyPropertyChanged はビューモデルで実装するという考え方なのですね。
    それも一つの方法であり、個人的にはモデル層で INotifyPropertyChanged を実装するより、そのほうがしっくりきます。

    > そして質問にはプロパティの変更通知についての記述は何もなく
    これは、BindableBase を実装することを指していました。

    また、プロパティの通知とプロパティの隠蔽は全く別の問題であることはわかっていますし、そのことを混同するような言い方をしたつもりもありません。

    キャンセル

  • 2018/08/13 13:36 編集

    INotifyPropertyChanged はバインド専門ではありません。
    モデルで実装しても問題ありません。
    ビューにバインドするかしないかは別の問題です。
    しかし、モデルをビューに直接バインドするのが MVVM の基本であるなら、ビューモデルの役割はなくなりますね。

    BindableBase はプロパティの変更を通知できますが、質問にあるゲッターセッタープロパティともカプセル化とも何の関係もありません。

    あなたは混同していないつもりでしょうが、それはあなたの判断です。
    私には複数の問題を混同しているようにしか見えません。
    もう一度カプセル化と INotifyPropertyChanged とデータバインディングと MVVM について読み直してください。
    私にはあなたに理解できるよう説明するのは無理そうです。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.49%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る