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

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

新規登録して質問してみよう
ただいま回答率
85.31%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

Q&A

解決済

2回答

5483閲覧

MVVMの概念について(とくにViewとViewModelの関係について)

WhiteTempest

総合スコア404

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

2グッド

0クリップ

投稿2022/03/08 07:14

編集2022/03/09 04:44

前提:質問者知識概要

主言語:

  • C++
  • Java

その他経験言語:

  • C#.NET
  • VB.NET
  • VB6
  • VBA
  • Python
  • Ruby
  • Delphi
  • etc...

MVVMの経験:

  • C#.NETのWPFでほんの少し、かじった程度

前提:MVVMの概念理解度/概要

View - ViewModel - Model の関係について、
漠然役割イメージは下記の通り持っています。
■View
ユーザーインタフェース(UI)。
XMLなどで作成。

■ViewModel
UIとモデルの橋渡し。
クラスとして作成。

■Model
実処理部。
クラスとして作成。

質問内容

主にViewModelの役割やクラス設計等について、
実務レベルで乖離していないか、ご意見/ご回答いただけると幸いです。

①ViewModelはViewの数だけ存在すべきという認識で合っていますか?
※複数のViewで流用しやすいように、様々なデータを保有したViewModelを作るのは、いかがなものかと疑念を抱いたため、
質問にあげさせていただきました。
※あくまでViewの各コンポーネントから参照されるデータ群であるべきなので、
Viewの数だけViewModelを作成するのがオーソドックスと考えました。
細かいお話だと宗教論争に発展するかもしれませんが、
ご回答者様の主観で構いませんので、ご意見いただけますと幸いです。

②ViewとViewModelのデータ的関係については、
Bindingでリンクしているだけなので、
ViewModelの構成要素(クラスメンバ)が変化しない限り、
Viewへの影響は無い(ようにするすべき)認識で合っていますか?

③たとえば、DBから取得したデータを画面等で利用する場合、
データ本体を格納しておくデータクラスをModel部で保有しておき、
Model部でViewModelにデータセットすることで、
Viewに自動反映させるイメージで大きく認識に相違無いですか?
※ViewModelとViewのBindingはおこなっていると仮定

④たとえば、複数の画面から1つのデータを利用したい場合などは、
Model、「共通データ」、View1/ViewModel1、View2/ViewModel2
を準備しておき、
Model部で「共通データ」をViewModel1/2へセットすることで、
View1/2に反映させる形がオーソドックスでしょうか?

⑤ViewModelは橋渡しが主な役割の認識ですが、
簡単なデータ変換であれば実装しても良いものでしょうか?
それとも"変換"はロジカルな部分となるため、Modelに実装すべき内容でしょうか?
※True->1、1->Trueなどの簡易な変換であれば、持ち合わせても良いのでは?と考えたため、質問させていただきました。

的外れな内容、意図が理解できない言い回し等含みましたら大変申し訳ありませんが、
ご助力いただけますと幸いです。

Bongo👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

私はWPF + MVVMでの開発をスタートしてから半年くらいですが、先達の諸氏にもご意見賜りたく、回答してみます。

(1)

ViewModelはViewの数だけ存在すべきという認識で合っていますか?

自分はそのように認識しています。
※利用するMVVMライブラリにも依存すると思います。

(2)

ViewとViewModelのデータ的関係については、
Bindingでリンクしているだけなので、
ViewModelの構成要素(クラスメンバ)が変化しない限り、
Viewへの影響は無い(ようにするすべき)認識で合っていますか?

おっしゃりたいことが
「ViewModelの内部実装が変わっても、Viewに対してBindingしているプロパティの仕様が変更されなければ、Viewに対する影響はない」
ということであれば、YESです。

客先から表示内容や入力について要件の追加・修正がなければ、Viewは変更されないと思います。
ViewModelはViewのためのものなので、Viewの仕様変更がなければ、ViewModelのI/F(== publicプロパティ)も変更されないと認識しています。

(3)

たとえば、DBから取得したデータを画面等で利用する場合、
データ本体を格納しておくデータクラスをModel部で保有しておき、
Model部でViewModelにデータセットすることで、
Viewに自動反映させるイメージで大きく認識に相違無いですか?

「Model部でViewModelにデータセットする」という文章からは、ModelがViewModelに依存しているというふうに読めます。
適切な参照方向は「View→ViewModel→Model」だと思います。

(WPFのINotifyPropertyChanged等のObserverパターン的なイベント発行等によって)Modelから通知先が誰かわからない状態で値変更を通知伝搬していて、結果的にその通知先がViewModelになっている、ということを指しているのであれば、私もその認識です。

(4)

たとえば、複数の画面から1つのデータを利用したい場合などは、
Model、「共通データ」、View1/ViewModel1、View2/ViewModel2
を準備しておき、
Model部で「共通データ」をViewModel1/2へセットすることで、
View1/2に反映させる形がオーソドックスでしょうか?

複数の画面から同じデータを参照するとき、それはModelに属するデータであると認識しています。つまり私の認識では「共通データ」はModel部に属します。

その共通データの出元ですが、VM1とVM2を両方知っている親ViewModelがいて、その親VMがDIコンテナを通じて共通データ(または共通データのファクトリ)を注入してもらい、それをVM1及びVM2に対してプロパティsetしているイメージです。

C#

1class ParentVm 2{ 3 private readonly _vm1; 4 private readonly _vm2; 5 public ParentVm(Func<ISharedData> dataFactory, IVm1 vm1, IVm2 vm2) 6 { 7 _vm1 = vm1; 8 _vm2 = vm2; 9 var data = dataFactory(); 10 _vm1.Data = data; 11 _vm2.Data = data; 12 } 13}

(5)

ViewModelは橋渡しが主な役割の認識ですが、
簡単なデータ変換であれば実装しても良いものでしょうか?

BindingでのConverterのためにIValueConverterを実装するにあたって、どのプロジェクトやパッケージに配置するのが適切か、という話でしょうか。

私は、表示要件でC#コードであるなら、クラスの配置としてはViewModelのパッケージが適切かと思っていました。

ただMVVMエキスパートの尾上様のブログ記事
https://ugaya40.hateblo.jp/entry/model-mistake
を見ると、ViewModelはできるだけ薄くする、ModelはUIを意識する、等との記述がありますので、その線から考えるとModelに入れるべきなのかもしれません。

投稿2022/03/08 07:39

編集2022/03/08 08:00
ttact

総合スコア171

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

WhiteTempest

2022/03/08 07:58 編集

早速のご回答、ありがとうございます。 >(2) >「ViewModelの内部実装が変わっても、Viewに対してBindingしている >プロパティの仕様が変更されなければ、Viewに対する影響はない」 汲み取っていただきありがとうございます。 ご認識の通りです。 >(3) >おっしゃりたいことが、INotifyPropertyChanged等で間接的に >ModelからViewModelに値変更を通知伝搬することを指している >のであれば、私もその認識です。 表現が悪く申し訳ありません。 ※汲み取っていただけて、感激です。 今になって考えると、 「データセット」というのは、「ViewとViewModelをBindingで紐づける」 というイメージがしっくり来る気がします。 Modelで直接的にViewModelを操作するのは、MVVMに反すると思うので。 →双方向参照になってしまうため、結合度が一気に増してしまう。。。 >(4) >解決した共通データオブジェクトを、各子ViewModelのsetプロパティを >通じてセットしているイメージです。 大筋認識違い無さそうで安心しました。 >(5) >その線から考えるとModelに入れるべきなのかもしれません。 私もいくつか指南/解説サイトや有識者の見解なども拝見させていただいたのですが、 この点に関しては、  ・絶対処理を入れてはダメ!  ・簡易なデータ変換ならOK♪ というように、微妙にエンジニアによって(?)解釈が異なるようだったので、 賛成多数の意見を理解しておこうと思っております。 ※着地点としては、「客先/現場に合わせる」ことになるとは思いますが。
ttact

2022/03/08 08:02

ごめんなさい、コメントと回答の修正がすれ違ってしまいました。 冒頭に書いた通り、私も経験がとても浅く、よく知っている方にコメント頂きたいなぁ。。。と思っています。 あまり過信しないで下さい。。。
退会済みユーザー

退会済みユーザー

2022/03/08 12:10

興味深い質問でしたので私もコメントしてみます。 (C#、WPF、MVVMの質問の数は少ないですけれども、それなりに閲覧数はあるのですね{前後の質問が19、32に対し、96の閲覧でした}) 私自身のWPF、MVVMの業務的な経験は1年とちょっとになります。 (私の認識にも誤りがあると思いますので、意見交換できればと思っております) --- > ①ViewModelはViewの数だけ存在すべきという認識で合っていますか? 細かいかもしれませんが、 ViewModelの数=Viewの数 ということだと個人的には少し違和感がありました。 MVVMで実装するViewを対象にすると、 ViewModelの数>=Viewの数 になりそうな印象でした。 > 通常、最低 1 つの画面に 1 つの ViewModel が必要で、コレクション・ビュー(= ListBox や TreeView など)の項目ごとに操作があるなら、それの 1 項目ごと用の ViewModel も必要です(操作がなくても普通は作ります)。大抵、コレクション・ビューの各項目は操作を持つし、表示方式を Model のものから変えて表示したい場合が多いからです。 > https://elf-mission.net/programming/wpf/getting-started-2020/step09/ 引用した記事は、2022年現在で比較的最近まで、試行錯誤しながらMVVMを業務システムの中に取り入れているような印象があって、個人的には参考にしています。 --- > ④たとえば、複数の画面から1つのデータを利用したい場合などは、 現在、私の所属する現場では、MVVMフレームワークが使われておらず、DIもしていないので、ttactさんのご回答は参考になります。 ttactさんのご回答の中にもありましたが、私もMVVMエキスパートの尾上さんの記事を参考にしていたりします。 ですが、2022年の現在でも、当時(2015年?)の記事からMVVM自体の発展がないような印象です。 (成熟を迎える前に衰退してしまったような・・) > MVVMにおいてはViewModel同士がお互いを操作する必要なんて基本的にはありません。所有関係はあることはありますがそもそもViewModelはModelの影なのです。 > https://ugaya40.hateblo.jp/entry/model-mistake ttactさんがご回答してくださった、親ViewModelに子ViewModelをDIするというのは、所有関係を表すという意味ですよね? 親ViewModelが子ViewModelを操作することはないですよね? --- > ⑤ViewModelは橋渡しが主な役割の認識ですが、簡単なデータ変換であれば実装しても良いものでしょうか? > 一般的にViewModelは、C#などの汎用プログラミング言語で記述され、プレゼンテーション・ロジックとステート(=状態)を持ちます。 > ドメイン・エンティティをViewに表示できるように整形したり、ドメイン・ロジックが公開するメソッドを操作として公開したりする責務を持ちます。 > https://atmarkit.itmedia.co.jp/fdotnet/chushin/greatblogentry_02/greatblogentry_02_03.html 「Viewに表示できるように整形したり」の責務はViewModelで良いのではないかと思っていたりします。 ttactさんのご回答の中にIValueConverterが出てきましたので、こちらも意見交換してみたいです。 現在、私の所属する現場では、各項目ごとにIValueConverterが実装されてしまっているような状況があります。 (IValueConverterの実装クラスが結構な数あります) 次のリンク先にあるような、汎用的なものであればIValueConverterで実装しても良い気がしますが、汎用性のない個別なものがIValueConverterで実装されていると、ちょっと疑問に思ってしまいます。 https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.toolkit.uwp.ui.converters?view=win-comm-toolkit-dotnet-7.0 View層はユニットテストしづらいですので、できるだけModel層の方に実装して(あるいはViewModelに実装して)、ユニットテストできた方が良いのではないかと思っています。 (私は、個人的にはIValueConverterはView層の印象でした) (IValueConverter単体でユニットテストが実装できたとしても、コントロールとの繋ぎ目のところで不具合・修正漏れなどが起きそう{不具合・修正漏れの発生を防ぎづらそう}に感じますので、できるだけ汎用的なものだけの使用に留めた方が良いのではないか、という感じです) IValueConverterの使い所についてもご意見いただけますと幸いです。
ttact

2022/03/08 23:44

xg63ex2bさん、コメントありがとうございます。 > (1)ViewModelはViewの数だけ存在すべきという認識で合っていますか? >> 通常、最低 1 つの画面に 1 つの ViewModel が必要で、コレクション・ビューの項目ごとに操作があるなら、それの 1 項目ごと用の ViewModel も必要です。 1画面に1ViewModel、これは例外なくそう作っています。TabControlについても、タブ毎に1ViewModel用意しています。 コレクションは微妙で、ログをDataGridで表示する箇所などではUIを意識してModelを作ってしまうので、ViewModelは作ってないです。 > 親ViewModelに子ViewModelをDIするというのは、所有関係を表すという意味ですよね? > 親ViewModelが子ViewModelを操作することはないですよね? 親画面が子画面の画面遷移(表示・非表示)を管理しています。親ViewModelが子ViewModelのメソッドを呼んだりプロパティをgetしたりはしてないです。 TabControlの各TabItemに当てはめるViewModel群も、TabControlを保持するViewに対応するViewModelがDIで注入してもらっています。 > IValueConverterの使い所についてもご意見いただけますと幸いです。 xg63ex2bさんの懸念がどこにあるのかがうまく理解できなかったのですが、例えばModelの値を直接バインディングして、表示に適した変換をIValueConverterで行うようなことはやってないです。大半のケースではViewModelでgetプロパティを提供するまで(つまり、ViewModel or Modelのレイヤ)に変換を済ませておいてます。 ドメインの知識が含まれるオブジェクトに対するIValueConverterは、ごく少数の例外を除いてはほぼ作ってないですね。ごく少数の例外について、私のシステムでは機械制御を行うために物理単位をよく扱うのですが、設定値やセンサー値を表示する際、メモリ上の単位と表示要件の単位が食い違っていることがよくあるので、その表示用コントロールでは表示単位への変換をConverter指定できるようにしています。そうすると、他の画面仕様と併せて確認する際にXAMLで閉じるので、XAMLとC#コードをいったりきたりしません。結果として作業性が向上し人的ミスが減ります。
WhiteTempest

2022/03/09 00:31

xg63ex2bさん、ttactさん コメントありがとうございます。 >> 通常、最低 1 つの画面に 1 つの ViewModel が必要で、コレクション・ビュー(= ListBox や TreeView など)の項目ごとに操作があるなら、それの 1 項目ごと用の ViewModel も必要です(操作がなくても普通は作ります)。 >1画面に1ViewModel、これは例外なくそう作っています。TabControlについても、タブ毎に1ViewModel用意しています。 これはとても理解できる意見でした。  「画面内のコンポーネントグループ毎にViewModelを作りましょう」 ということですね。 たしかに、これをやらないと、1つのViewModelが、とても肥大化し、管理が煩雑になりそうですね。 >表示方式を Model のものから変えて表示したい場合が多いからです。 イメージ的には、Modelが持ちたいのはシーケンス制御などのロジックに特化しようというイメージですかね? ※例えば、任意条件でのフィルタリングや並び変え等、当該データ/当該View固有の処理であれば、   ViewModelに実装した方がいい  といった感じ? >他の画面仕様と併せて確認する際にXAMLで閉じるので、XAMLとC#コードをいったりきたりしません。結果として作業性が向上し人的ミスが減ります。 これは、とても良い仕組みに感じました。 例えば元の物理値データ(Model側が保有するデータ)としては、 データ/DB仕様などに基づき、  0.1L(リットル) として管理しているが、場所によっては、  100ml(ミリリットル)  100cc(シーシー) で表示したい、とかですかね? 有識者との議論/討論はタメになります。 ※回答Closeはもう少し先を予定しています。  回答やコメントが落ち着きを見せましたら、他回答者様ふくめ回答群よりベストアンサー選んで、  Close予定とさせていただきます。
Zuishin

2022/03/09 03:01

> MVVMで実装するViewを対象にすると、 > ViewModelの数>=Viewの数 > になりそうな印象でした。 そんなことはないと思いますけどねえ。 > 通常、最低 1 つの画面に 1 つの ViewModel が必要で、コレクション・ビュー(= ListBox や TreeView など)の項目ごとに操作があるなら、それの 1 項目ごと用の ViewModel も必要です この場合のコレクション・ビューは View です。(ビュー = View) View ごとに ViewModel を作るよう勧めています。 ViewModel の数が View を超えるイメージがわきません。
退会済みユーザー

退会済みユーザー

2022/03/09 12:01

みなさま、コメントありがとうございます。 (メールが届かなくなってしまって、たくさんコメントがあったことに気づけませんでした・・) --- ttactさん > コレクションは微妙で、ログをDataGridで表示する箇所などではUIを意識してModelを作ってしまうので、ViewModelは作ってないです。 私も同じでした。 厳格なMVVMではなくなってしまうかもしませんが、ModelをViewにバインドする形で実装してしまうこともよくあります。 > ドメインの知識が含まれるオブジェクトに対するIValueConverterは、ごく少数の例外を除いてはほぼ作ってないですね。 > 表示単位への変換をConverter指定できるようにしています。 そうですよね。 これは単位の変換という汎用的なIValueConverterクラスを実装するということですよね。 ですが、私の所属する現場では、sampleInstance.SampleProperty(表示項目Aのバインド元)が"この値"の場合、表示項目BのIsEnabledをfalseにするためのIValueConverter、といったような汎用的ではないIValueConverterクラスが大量に実装されてしまっている状況があります・・ 30項目の表示項目あったら、30項目以上のIValueConverterクラスが実装されてしまっているような感じです・・ (単純に無駄っぽいクラスを実装するのが面倒臭いです・・) (バインドは便利ですが、ビルド時の静的なエラーが検出できないところを懸念しております、、単純なバインドでしたらViewとViewModelの1段階の関係を気にすれば良いですが、IValueConverterを入れるとViewとIValueConverterとViewModelの2段階の関係を気にしなければいけないので、不具合を埋め込む要因を1段階分増やすように感じております) --- WhiteTempestさん > ※例えば、任意条件でのフィルタリングや並び変え等、当該データ/当該View固有の処理であれば、   ViewModelに実装した方がいい  といった感じ? なるほど、このような内容はViewでもなく、Modelでもなく、ViewModelで良いのかもしれませんね。 --- Zuishinさん > ViewModel の数が View を超えるイメージがわきません。 コメントありがとうございます。 私の認識の前提の記載が不十分だったり、私の認識が誤っていたりしていたようでしたので、改めてご確認させていただきたいと思います。 私はViewの数、ViewModelの数と記載した時の「数」はクラスの数のことを指していたつもりでした。 https://elf-mission.net/programming/wpf/getting-started-2020/step09/ リンク先の記事では、Viewクラスに対して、ViewModelクラスの方が多く作成されているように思っております(記事の内容が唯一の正解だとは思っておりません)。 「ViewModel の数が View を超えるイメージがわきません。」のご記載からですが、どのような実装方針にしたとしても、ViewModelのクラスの数がViewクラスの数を超えることはない、というように感じました。 このあたりの認識の食い違いなど、コメントいただけますと幸いでございます。 (私の理解不足のためにお手数をおかけしてしまいまして申し訳ございません・・)
WhiteTempest

2022/03/10 05:27

Zuishinさん コメントありがとうございます。 >>この場合のコレクション・ビューは View です。(ビュー = View) >>View ごとに ViewModel を作るよう勧めています。 >ViewModel の数が View を超えるイメージがわきません。 主観ですが、「なに」を「View」とみなすかの前提条件の違いでは無いでしょうか? Zuishinさんは、「ListBox」も「View」と扱われていますが、 xg63ex2bさんは、「ListBox」を「View」としてみなしていないのだと思います。 xg63ex2bさんもおっしゃっていますが、あくまで数は「作成するクラス」とするならば、  画面A(View)   |-コンポーネントA-1   |-タブA-2    |-コンポーネントA-2-1    |-コンポーネントA-2-2   |-リストA-3 といった構成が存在した場合、 タブA-2やリストA-3を「View」とみなすか、構成要素の一つとみなすか、 というように表現?認識?の違いでは無いかと感じました。 タブA-2の構成要素を画面AのXML中に実装してしまうなら構成要素に見えますが、 別XMLで用意するならば、それはそれで「View」に見える気がします。
ttact

2022/03/11 23:19

今週ちょうど、コレクションに格納することが前提の共通部品の開発があり、その設計の議論がチーム内でありました。その際に「チーム内の各人でViewと見なすモノの認識が違う」ということがわかりました。 「ボタン1つに対してViewModelは作ってないでしょ?」という話があって一瞬納得しかけたのですが、じゃあどういう条件ならViewModelを作るのか?みたいな。 標準のボタンでテンプレートを変更しなくても、バインドできるプロパティはたくさんあります。ViewModel側に表現したい複合的な内容があって、それがドメイン上の概念を持っていて定型的にバインディングするのであれば、それはViewModelとなるのではないか、みたいな話になりました。 結局はそのViewModelの概念を示すinterfaceを定義して、それを簡単にバインディングできるようViewに依存関係プロパティを定義しました。 振り返ってみると、対象が「コレクションアイテム」かどうかは、ViewModelにすべきかどうかの判断材料にはなっていない、と思いました。同じような「複合的な」表現を「複数の箇所(⊃コレクションアイテム)」で行うなら、その概念を実装上で表現したくなりますし、そのほうが後でコードを読んだときに意図が伝わりやすくなると思います。 この結論が適切かどうかは正直わかりませんが、皆様の議論の参考になればと思います。 xg63ex2b様 > 私の所属する現場では、sampleInstance.SampleProperty(表示項目Aのバインド元)が"この値"の場合、表示項目BのIsEnabledをfalseにするためのIValueConverter、といったような汎用的ではないIValueConverterクラスが大量に実装されてしまっている状況があります・・ うーん、これはちょっと確かに違和感ありますね。以前のコメントにあったユニットテスト可能な部分を狭めてしまっていることもありますし(それは私の単位の話もある意味そうなのですが)、直感的には品質に良い影響は与えてないように思います。というかそういう品質の話を除いても、単純にXAML書くの大変じゃないですかね。。。
退会済みユーザー

退会済みユーザー

2022/03/12 10:09

みなさま コメントありがとうございます。 やっぱりメールは届かないようで・・・ --- WhiteTempestさん > 主観ですが、「なに」を「View」とみなすかの前提条件の違いでは無いでしょうか? 確かに、そんな感じですね。 (メールが届かないっぽいですので、Zuishinさんからはコメントいただけないかもしれませんね・・) --- ttactさん > 今週ちょうど、コレクションに格納することが前提の共通部品の開発があり、その設計の議論がチーム内でありました。 議論ができる時点で良いチームと感じました。 業務システムの技術者だとなかなかその土台に至ることも難しいと感じています・・ > MVVMパターンの各要素の実装をこねくり回す過程でパターンを把握した気になって、パターンの本来の目的を破壊してしまうような実装を推奨してしまっている人も見ます。そんな滑稽(こっけい)なことをしない知識を持ってほしいのです。 > (略) > それらを理解することで、正しくMVVMパターンを実装できるようになるのはもちろんのこと、MVVMパターンにのっとって要件に合わせた実装の簡略化やカスタマイズが行えるようになるはずだと思っています。 > https://atmarkit.itmedia.co.jp/fdotnet/chushin/greatblogentry_02/greatblogentry_02_01.html 上に引用したような記述を見ると、View、ViewModel、Modelの切り分けは明確であって、その切り分けを悩まずできないのであれば、それはMVVMの理解ができていないかのように感じてしまっております・・ でも、みなさま悩んでいますよね・・ > MVVMにおいてはViewModel同士がお互いを操作する必要なんて基本的にはありません。所有関係はあることはありますがそもそもViewModelはModelの影なのです。そしてまたViewはViewModelの影でもあります。 > https://ugaya40.hateblo.jp/entry/model-mistake 上記、引用の「ViewModelはModelの影」という表現ですが、私はあまり正しく認識できていないのかもしれません。 > 「じゃあどういう条件ならViewModelを作るのか?」 このような疑問を持つこと自体も「ViewModelはModelの影」という表現を理解できていないところがあるのではないかという気もします。 ・・難しいですね・・ > というかそういう品質の話を除いても、単純にXAML書くの大変じゃないですかね。。。 IValueConverterのお話についてもコメントありがとうございます。 大変なのです・・ なぜこのように実装してしまったのか・・ 一度実装されてしまうと、一から作るよりも難しかったりしています・・ いただいたコメントをもとに少しずつ改善していこうと思います。
WhiteTempest

2022/03/23 05:00

ttactさん、xg63ex2bさん 的を射ない質問の中、何度もコメントいただき、ありがとうございます! 今回の討論を通して、  「チーム内の各人でViewと見なすモノの認識が違う」 というところがキモであると、再認識できました。 正直、正解は各人で異なるというのが真理であって、 あとはチーム内で統一した設計とすることがMVVMとしての要点と 認識できました。 >今週ちょうど、コレクションに格納することが前提の共通部品の開発があり、その設計の議論がチーム内でありました。 うらやましい。 そういった議論って、最近やってない気がします。 根っからの技術者なので、楽しそう(やりがい)に感じてしまいます! 一旦、質問としては解決済みとさせていただきたいと思いますが、 続きの議論、ご意見あればコメント継続いただければと思います(笑) 改めまして、お付き合いいただき、ありがとうございました!
guest

0

①ViewModelはViewの数だけ存在すべきという認識で合っていますか?

「存在してもいい」ぐらいだと思います。マルチページアプリケーションで各ページがシンプルな作りならページ単位でだけViewModelを作るようにしても十分ですし、各ページが複雑だったり、あるいはシングルページアプリケーションとして一つのページで作り込む場合は、ページ内のUIパーツそれぞれにVMがあってもいいと思います。

②ViewとViewModelのデータ的関係については、Bindingでリンクしているだけなので、ViewModelの構成要素(クラスメンバ)が変化しない限り、Viewへの影響は無い(ようにするすべき)認識で合っていますか?

依存方向は基本的に V→VM→M と単方向です。例えばViewのダイアログの機能をViewModelで使いたい場合は依存性の逆転(ググってください)のパターンを使って依存方向がVM→Vにならないようにします。

VはVMに依存しているという意味でVMが変わるならVも相応に変わりますが、逆にVが変わる時にVMに修正が必要とは限らないと言えると思います。

③たとえば、DBから取得したデータを画面等で利用する場合、データ本体を格納しておくデータクラスをModel部で保有しておき、Model部でViewModelにデータセットすることで、Viewに自動反映させるイメージで大きく認識に相違無いですか?※ViewModelとViewのBindingはおこなっていると仮定

ModelはViewModelのことを関知しません。ViewModelがModelを参照してデータ変化をViewに伝えるという流れが基本です。具体的にはModelにINotifyPropertyChangedやイベントを実装し、それらによるデータ変更通知をViewModelがフックしておく。Modelのデータ変更通知を受けてViewModelがViewに表示を反映する、という流れです。

④たとえば、複数の画面から1つのデータを利用したい場合などは、Model、「共通データ」、View1/ViewModel1、View2/ViewModel2を準備しておき、Model部で「共通データ」をViewModel1/2へセットすることで、View1/2に反映させる形がオーソドックスでしょうか?

繰り返しになりますが依存は V→VM→M と単方向であるべきです。ですので、ViewModelがコンストラクタ等でModelと共通データを受け取って、それらを使ってViewModelが表示データをViewに与えます。ModelがViewModelを参照することはありません。

その上で、Modelと共通データは別々にしたままViewModelに渡してもいいですし、なんらかのModelが共通データのハブ、集約を行って変更通知可能なプロパティ等として公開するなどしてもいいと思います。

⑤ViewModelは橋渡しが主な役割の認識ですが、簡単なデータ変換であれば実装しても良いものでしょうか?それとも"変換"はロジカルな部分となるため、Modelに実装すべき内容でしょうか?

例示されている 1 -> True のようなドメイン知識としての変換は常にModelで解消された状態でViewに渡すべきです。View側は「0がTrueか1がTrueか、どっちかわからない」という前提であるべきです。

一方でViewで変換するのは、例えば、trueの時に表示すべきテキスト「はい」なのか「有効」なのか、といった「データからユーザーが見るものの境界としての変換」であるべきと考えます。

投稿2022/03/08 12:52

tor4kichi

総合スコア771

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

WhiteTempest

2022/03/10 05:04 編集

tor4kichiさん ご回答ありがとうございます。 >各ページが複雑だったり、あるいはシングルページアプリケーションとして一つのページで作り込む場合は、ページ内のUIパーツそれぞれにVMがあってもいいと思います そうなりますと、数の関係で言うと、  View<=ViewModel というのが基本原則ですかね。 大体下記の2点が大原則そうでしょうか? ・最低限ページ数分のViewModelは用意すべき。 ・でも、グルーピング出来たり、シングルページアプリだと画面遷移毎にレイアウト/役割も変わるだろうから、 画面毎、UIコンポーネント毎にViewModelを用意すべき。 >ViewModelがModelを参照してデータ変化をViewに伝えるという流れが基本です。 申し訳ありません。 質問/表現が大きく間違っておりました。 V⇒VM⇒Modelの単方向参照の認識は持っております。 1点、ご回答を踏まえての素朴な疑問なのですが、  >ViewModelがViewに表示を反映する という部分ですが、こちらは厳密には、  ViewがViewModeの変更をフックしている というのが正しいのでしょうか? ViewとViewModelの関係上、  View⇒ViewModel となっておりますが、ViewModelがViewに変更を反映するとなる場合、  ViewModel⇔View と、双方向になるように感じてしまったため、 確認させていただきました。 >>⑤ViewModelは橋渡しが主な役割の認識ですが、簡単なデータ変換であれば実装しても良いものでしょうか?それとも"変換"はロジカルな部分となるため、Modelに実装すべき内容でしょうか? >例示されている 1 -> True のようなドメイン知識としての変換は常にModelで解消された状態でViewに渡すべきです。View側は「0がTrueか1がTrueか、どっちかわからない」という前提であるべきです。 イメージの説明不足により、誤解を招いておりましたら申し訳ありません。 もちろんViewにてデータ変換することはNGと思っております。 Modelは元データ(原本)を持っていますので、 0/1などのデータは仕様上の値から変換しない方がいいのでは?と思っております。 例えばView側で0/1をもとに、タブの表示/非表示などに直接利用することが出来ないと思います。 それを緩衝するためにViewModelで、Viewが理解できる値に一部整形/変換するのはアリなのか? という主旨での質問でした。  ※ttactさん の回答を見ましても、現場や技術者によって賛否は分かれそうな内容ですが。。。 tor4kichiさん の回答を参考にしますと、 個人的には以下の変換イメージが妥当ではないかと思っておりますが、 相違なさそうでしょうか? Model : 1(仕様/DB仕様に準拠した元データ) ViewModel : 1 -> true (Viewが理解できる値) View : true -> タブA表示(ViewModelにてセットされた理解できる値から導き出される表示値)
tor4kichi

2022/03/09 03:57

データの流れは双方向ですよね。依存の流れは単方向にという原則をご存知のようならMVVMの理解は大丈夫だと思います。 Modelが管理するデータの型のあり方としてベストなのは、データベース上の型とModel上の型が同じであることだと思います。「本当はEnum型として表現すべきだけどデータベース上は数値でしか持てない」時に、データの永続化を管理するModel以降においてヒューマンリーダブルな意味付けを持たせたEnumなりboolなり適切な型への変換(=ドメイン知識を明確な型として表現する)をしたいところです。 View→ViewModelにおけるデータ変換は画面としての仕様を満たすために必要十分に行うべきと思います。理想としてはModelにおいて十分にドメイン知識を表現した状態にし、ViewModelで行うのはフィルタリング(表示すべきコンテンツの判断)や並び替えなどデータの変形がメインになるようにすることだと思います。
WhiteTempest

2022/03/10 05:12

>データの流れは双方向ですよね。依存の流れは単方向にという原則 !!! 私自身の勘違いに気づかせていただき、ありがとうございます! 依存が単方向なだけで、データは確かに双方向ですね! ちょっと視野が狭くなってしまっていました。。。 納得です。 >データベース上の型とModel上の型が同じであること 同意です。 >View→ViewModelにおけるデータ変換は画面としての仕様を満たすために必要十分に行うべきと思います。理想としてはModelにおいて十分にドメイン知識を表現した状態にし、ViewModelで行うのはフィルタリング(表示すべきコンテンツの判断)や並び替えなどデータの変形がメインになるようにすることだと思います。 なるほど。 確かに、"理想"としてはModel<->ViewModel間で変換が入らない粒度(ドメイン知識を完全に認識共有)で、 データベース/仕様定義されていれば、View<->ViewModel間のデータ参照関係もシンプルになりますし、 そうすれば、ViewModelにて無駄に変換の責務を負わせる必要性が無くなりますからね。 →経験則から勝手に、"理想"ではなく"現実的"(データの"値"は使う側で考慮する)な考え方になってしまっていました。。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問