[解決済み] なぜMVVMを使うのか?
質問
さて、私はMVVMパターンについて調べているのですが、以前調べようとするたびに、いろいろな理由で断念していました。
- 不要な余分な長ったらしいコーディング
- コーダーにとって明白な利点がない (私のオフィスにはデザイナーがいない。現在、自分だけがすぐに別のコーダーになる)
- 良いプラクティスのリソース/ドキュメントがあまりない! (少なくとも見つけるのは難しい)
- これが有利になるようなシナリオは一つも思いつかない。
私はまだそれをあきらめようとしていて、誰かが上記の理由に答えるかどうか尋ねてみようと思いました。
正直なところ、シングル/パートナーでのコーディングにこれを使用する利点が見当たりません。たとえ 10 のウィンドウを持つ複雑なプロジェクトであってもです。私にとっては、DataSet は十分なビューであり、次のようなバインディングです。 ブレント 次の 質問
MVVMパターンを使用することで、XAMLのデータバインディングと比較して、時間を節約できる例を示してください。
私のバインディングの100%は、現在XAMLで行われます。したがって、私は、私が書き、依存する必要がある背後にある余分なコードであるため、VMのポイントがわからない。
EDITです。
午後からMVVMについて調べていたら、ようやくその本当の良さを実感できるものを見つけました。
答え
.
どのように解決するのですか?
概要
- すべてのパターンの使用は状況に応じて行われ、利点は (もしあれば) 常に複雑さを軽減することにあります。
- MVVMは、GUIアプリケーションのクラス間で責任を分散させる方法を教えてくれます。
- ViewModel は Model からのデータを View に適合する形式に投影します。
- 些細なプロジェクトでは、MVVMは不要です。Viewだけを使用すれば十分です。
- 単純なプロジェクトでは、ViewModel/Modelの分割は不要で、ModelとViewを使うだけで十分な場合があります。
- ModelとViewModelは最初から存在する必要はなく、必要な時に導入すればよい。
パターンを使うべきとき、避けるべきとき
十分にシンプルなアプリケーションでは、すべてのデザインパターンは過剰なまでに使われます。押されると "Hello world" と表示される単一のボタンを表示する GUI アプリケーションを書くとします。この場合、MVC、MVP、MVVM などのデザイン パターンはすべて、多くの複雑さを追加しますが、何の価値も追加しません。
一般的に、なんとなく合っているからという理由でデザインパターンを導入するのは、常に悪い判断です。デザインパターンは、全体の複雑さを直接減らすか、見慣れない複雑さを見慣れた複雑さに置き換えることによって、複雑さを減らすために使用されるべきです。 もしデザインパターンがこれらの2つの方法のどちらかで複雑さを減らすことができないのであれば、それを使ってはいけません。
見慣れた複雑さと見慣れない複雑さを説明するために、次の2つの文字列を例に挙げてみましょう。
- D.€|Ré%dfà?c"
- "CorrectHorseBatteryStaple"。
2 番目の文字列は最初の文字列の 2 倍の長さですが、最初の文字列よりも読みやすく、速く書け、覚えやすいのは、すべてそれがより親しみやすいからです。同じことが、コード内の見慣れたパターンにも当てはまります。
この問題は、親しみやすさが読者に依存することを考慮すると、別の次元になります。ある読者は、3.14159265358979323846264338327950" が上記のパスワードのいずれかよりも覚えやすいと感じるでしょう。そうでない方もいらっしゃるでしょう。ですから、MVVMのフレーバーを使用したい場合は、使用している特定の言語とフレームワークで最も一般的なフォームを反映したものを使用するようにしてください。
MVVM
とはいえ、例によってMVVMのトピックに飛び込んでみましょう。MVVM は、GUI アプリケーションのクラス間 (またはレイヤー間 - これについては後で説明します) で、クラスの数を少なくし、クラスごとの責務の数を少なくし、よく定義することを目標に、責務を分散する方法を教えてくれます。
適切な」MVVMは、少なくとも中程度の複雑なアプリケーションを想定しており、どこかから取得したデータを扱います。データベース、ファイル、Webサービス、または無数の他のソースからデータを取得することができます。
例
この例では、2つのクラス
View
と
Model
は存在しないが
ViewModel
. また
Model
は csv ファイルをラップし、 起動時に読み込み、アプリケーションが終了したときにユーザがデータに加えた すべての変更とともに保存します。また
View
からのデータを表示する Window クラスです。
Model
のデータをテーブルに表示し、ユーザがそのデータを編集できるようにする Window クラスです。csvのコンテンツは、なんとなくこんな感じでしょうか。
ID, Name, Price
1, Stick, 5$
2, Big Box, 10$
3, Wheel, 20$
4, Bottle, 3$
新しい要件です。価格をユーロで表示する
今、私たちはアプリケーションに変更を加えるよう求められています。データは 2 次元グリッドで構成され、すでに USD の価格を含む "price" 列があります。事前に定義された為替レートに基づいて、米ドル建てに加えてユーロ建ての価格を表示する新しい列を追加する必要があります。他のアプリケーションが同じファイルで動作し、これらの他のアプリケーションは私たちのコントロール下にないため、csv ファイルの形式は変更してはいけません。
可能な解決策は、新しいカラムを単に
Model
クラスに追加することです。これは最良の解決策ではありません。
Model
は csv に公開するすべてのデータを保存し、csv に新しいユーロ価格のカラムを作りたくないからです。そのため
Model
への変更は非自明なことであり、また、Model クラスが行うことを記述するのは難しく、それは
コードの匂い
.
また、この変更は
View
で変更することもできますが、現在のアプリケーションでは、データバインディングを使って
Model
クラスによって提供されるデータを直接表示するためにデータバインディングを使用しています。GUI フレームワークでは、テーブルがデータ ソースにデータ バインドされている場合、テーブルに追加の計算カラムを導入することができないため、テーブルの View
を大幅に変更する必要があり、これを実現するために
View
はもっと複雑になります。
ViewModel の紹介
は存在しません。
ViewModel
が存在しないため、アプリケーションでは
Model
は Csv が必要とする方法でデータを表示し、それはまた
View
が必要とする方法です。このように
ViewModel
を挟むことは、目的もなく複雑さを増していたことでしょう。しかし、今では
Model
がデータを提示しなくなったので
View
が必要とする方法でデータを表示することができなくなったので、私たちは
ViewModel
.
は
ViewModel
のデータを投影します。
Model
を投影するようにします。
View
はシンプルにすることができます。
以前は
View
クラスをサブスクライブしていました。
Model
クラスをサブスクライブしています。ここで、新しい
ViewModel
クラスのサブスクライブ先が
Model
クラスを購読し
Model
のデータを
View
- に、価格をユーロで表示するカラムを追加しています。そのため
View
はもはや
Model
を知らないので、今は
ViewModel
という点から
View
と同じに見えますが
Model
は以前と同じように見えますが、公開されたデータには新しい読み取り専用のカラムが含まれています。
新しい要件: データをフォーマットする異なる方法
次のお客様のご要望は、データをテーブルの行として表示するのではなく、各項目(通称:行)の情報をカード/ボックスとして表示し、4x5のグリッドで画面に20個のボックスを一度に表示してほしいというものでした。のロジックをそのままにしているので
View
のロジックをシンプルにしているので、単純に
View
を顧客が望むように新しいクラスで完全に置き換えるだけです。もちろん、古い
View
を好む顧客もいるので、両方をサポートする必要があります。なぜなら、共通のビジネスロジックはすべてすでに
ViewModel
にあるため、あまり問題にはなりません。そこで、View クラスを
TableView
に変更し、新たに
CardView
を書くことで、データをカード形式で表示します。また、いくつかのグルーコードを書かなければなりませんが、これはスタートアップ関数内のオネリになるかもしれません。
新しい要件:動的な為替レート
次のお客様の要望は、あらかじめ設定された為替レートを使用するのではなく、インターネットから為替レートを取得してほしいというものです。ここで、先ほどの「レイヤー」の話をもう一度。私たちは
Model
クラスを変更して、為替レートを提供することはありません。その代わりに、為替レートを提供する完全に独立した追加のクラスを書く(または見つける)のです。その新しいクラスはモデル層の一部となり、私たちの
ViewModel
は csv-Model と exchange-rate-Model の情報を統合し、それを
View
. この変更のために、古いモデルクラスとビュークラスは触る必要さえありません。ただし、Model クラスの名前を
CsvModel
という名前に変更し、新しいクラスは
ExchangeRateModel
.
もし、ViewModel を導入したときに導入せず、今になって導入していたとしたら、今 ViewModel を導入するための作業量が多くなってしまいます。
View
と
Model
に機能を移し、その機能を
ViewModel
.
ユニットテストに関するあとがき
MVVM の主な目的は、Model と ViewModel のコードをユニットテストの下に置くことができることではありません。MVVM の主な目的は、コードが少数の明確に定義された責任を持つクラスに分割されることです。少数の明確に定義された責任を持つクラスで構成されるコードを持つことのいくつかの利点の一つは、Unit Testの下でコードを置くことが容易であることです。より大きな利点は、コードが理解、維持、および変更しやすくなることです。
関連
-
[解決済み】C#におけるtypedefの等価性
-
解決済み] Critical error detected c0000374 - C++ dll returns pointer off allocated memory to C# [解決済み] Critical error detected c0000374 - C++ dll returns pointer off allocated memory to C#.
-
[解決済み】Unity3DでOnTriggerEnterが動作しない件
-
[解決済み】Entity FrameworkからのSqlException - セッション内で他のスレッドが動作しているため、新しいトランザクションは許可されません。
-
VSでscanfエラーを恒久的に解決するには、ソースファイルを作成し、自動的に#define _CRT_SECURE_NO_WARNINGS 1を追加してください。
-
[解決済み] IDisposable インターフェースの正しい使用法
-
[解決済み] なぜList<T>を継承しないのですか?
-
[解決済み] EqualsメソッドがオーバーライドされたときにGetHashCodeをオーバーライドすることが重要な理由は何ですか?
-
[解決済み] C#でHashtableよりDictionaryが好まれる理由とは?
-
[解決済み】なぜFunc<T>ではなくExpression<Func<T>を使うのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] [Entity Framework 4.1でエンティティに関連オブジェクトを追加する際に、エンティティオブジェクトをIEntityChangeTracker.の複数のインスタンスから参照できない。
-
[解決済み] 'SubSonic.Schema .DatabaseColumn' 型のオブジェクトをシリアライズする際に、循環参照が検出されました。
-
[解決済み】Unity 「関連するスクリプトを読み込むことができません」「Win32Exception: システムは指定されたファイルを見つけることができません"
-
[解決済み】HRESULTからの例外:0x800A03ECエラー
-
[解決済み】ファイルへの読み書きの際に共有違反のIOExceptionが発生する C#
-
[解決済み] ...基礎となる接続は閉じられました。予期しないエラーが受信で発生しました
-
[解決済み】URLから画像をダウンロードする方法
-
[解決済み】インデックスが範囲外でした。コレクションパラメータname:indexのサイズより小さく、非負でなければなりません。
-
[解決済み】ファイルやアセンブリ、またはその依存関係の1つをロードできませんでした。
-
[解決済み】名前 'ViewBag' が現在のコンテキストに存在しない - Visual Studio 2015