さて、私はMVVMパターンを調査してきましたが、以前にそれを調査しようとするたびに、いくつかの理由でgaveめました。
私は再びそれをあきらめようとしています、そして誰かが上記の理由に答えるかどうかを尋ねると思いました。
正直に言って、これをシングル/パートナーコーディングに使用する利点はわかりません。数十のウィンドウがある複雑なプロジェクトでも。私にとっては、DataSetは Brent による question
XAML DataBindingと比較した場合、MVVMパターンを使用すると時間を節約できる例がありますか。
現時点では、バインドの100%がXAMLで行われています。したがって、VMのポイントは、私が記述し、依存する必要のある、その余分なコードの背後にあるとは思えません。
編集:
午後のMVVMの調査に費やした後、最終的に、この 回答 から本当のメリットを実感できる何かを見つけました。
十分に単純なアプリケーションの場合、すべての設計パターンは過剰です。押すと「Hello world」と表示される単一のボタンを表示するGUIアプリケーションを作成するとします。この場合、MVC、MVP、MVVMなどの設計パターンはすべて、多くの複雑さを追加しますが、価値はまったく追加しません。
一般に、デザインパターンを導入することは、ある程度適合しているという理由だけで、常に悪い決定です。全体的な複雑さを直接減らすか、なじみのない複雑さを馴染みのある複雑さで置き換えることにより、設計パターンを使用して複雑さを減らす必要があります。 これら2つの方法のいずれかで設計パターンが複雑さを軽減できない場合は、使用しないでください
なじみのある、なじみのない複雑さを説明するには、次の2つの文字シーケンスを使用します。
2番目の文字シーケンスは最初のシーケンスの2倍の長さですが、最初のシーケンスよりも読みやすく、書きやすく、覚えやすいのは、すべて馴染みがあるからです。同じことがコードのなじみのあるパターンにも当てはまります。
一部のパターンは、将来コードを使用するすべての開発者に馴染みがないかもしれないという事実を意識してください。前の例に関して、次のシーケンスは、それを覚えている人の経験とトレーニングに応じて、上記のシーケンスのいずれよりも覚えやすいか、またはそうでない場合があります:「3.14159265358979323846264338327950」。より高度な設計パターンが関係する場合には、メンテナンス開発者が既にそれに精通している場合にのみ、設計パターンを使用するのが理にかなっています。
つまり、例によってMVVMのトピックに飛び込みましょう。 MVVMは、クラスごとの責任の数を小さく、適切に定義したまま、クラスの数を少なくすることを目的として、GUIアプリケーションのクラス間(またはレイヤー間-これについては後で説明します)で責任を分散する方法をガイドします。
「適切な」MVVMは、「どこか」から取得したデータを処理する、少なくとも中程度に複雑なアプリケーションを想定しています。データベース、ファイル、Webサービス、または他の無数のソースからデータを取得する場合があります。
この例では、2つのクラスView
とModel
がありますが、ViewModel
はありません。 Model
は、起動時に読み込むcsvファイルをラップし、アプリケーションのシャットダウン時に保存し、ユーザーがデータに加えたすべての変更を保存します。 View
は、Model
のデータをテーブルに表示し、ユーザーがデータを編集できるようにするWindowクラスです。 csvコンテンツは次のようになります。
ID, Name, Price
1, Stick, 5$
2, Big Box, 10$
3, Wheel, 20$
4, Bottle, 3$
新しい要件:ユーロで価格を表示
ここで、アプリケーションに変更を加えるように求められます。データは2次元のグリッドで構成されており、そのグリッドには既に「価格」列があり、USDの価格が含まれています。事前に定義された為替レートに基づいて、米ドルの価格に加えてユーロの価格を示す新しい列を追加する必要があります。 csvファイルの形式は、他のアプリケーションが同じファイルで動作し、これらの他のアプリケーションは当社の管理下にないため、変更してはなりません。
考えられる解決策は、新しい列をModel
クラスに単純に追加することです。 Model
はcsvに公開するすべてのデータを保存するため、これは最適なソリューションではありません。csvに新しいユーロ価格の列は必要ありません。したがって、Model
への変更は簡単ではなく、Modelクラスが何を行うのかを記述するのも難しくなります。これは code smell です。
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
が以前と同じように見えますが、公開データには新しい読み取り専用列が含まれます。
新しい要件:データをフォーマットする別の方法
次の顧客の要求は、データを表の行として表示するのではなく、各アイテム(別名行)の情報をカード/ボックスとして表示し、20個のボックスを4x5グリッドで画面に20個表示することです。一度にボックス。 View
のロジックをシンプルに保ったので、単にView
を完全に、顧客が望むように機能する新しいクラスに置き換えるだけです。もちろん、古いView
を好む別の顧客がいるので、今は両方をサポートする必要があります。共通のビジネスロジックはすべて、たまたまViewModel
にあるため、それほど問題ではありません。したがって、Viewクラスの名前をTableView
に変更し、データをカード形式で表示する新しいCardView
クラスを作成することで、これを解決できます。また、いくつかのグルーコードを記述する必要があります。これは、スタートアップ関数の1つのライナーになる可能性があります。
新しい要件:動的為替レート
次の顧客の要求は、事前に定義された為替レートを使用するのではなく、インターネットから為替レートを引き出すことです。これが、「レイヤー」に関する以前のステートメントを再検討するポイントです。 Model
クラスを変更して為替レートを提供しません。代わりに、為替レートを提供する完全に独立した追加クラスを作成(または検索)します。その新しいクラスはモデルレイヤーの一部になり、ViewModel
はcsv-Modelとexchange-rate-Modelの情報を統合し、View
に提示します。この変更では、古いModelクラスとViewクラスを変更する必要さえありません。さて、Modelクラスの名前をCsvModel
に変更し、新しいクラスExchangeRateModel
を呼び出す必要があります。
導入時にViewModelを導入していなかったが、今までそうするのを待っていた場合、View
とModel
の両方からかなりの量の機能を削除する必要があるため、ViewModelを導入するための作業量が多くなります機能をViewModel
に移動します。
MVVMの主な目的は、ModelとViewModelのコードを単体テストの下に置くことではありません。 MVVMの主な目的は、コードが少数の明確に定義された責任を持つクラスに分割されることです。明確に定義された少数の責任を持つクラスで構成されるコードを持つことのいくつかの利点の1つは、コードをユニットテスト下に置くことが簡単になることです。はるかに大きな利点は、コードの理解、保守、および変更が簡単になることです。
パターンを実装し、ベストプラクティスに従うことは無意味な追求のように感じることがよくありますが、上司が機能を追加または微調整するように求めてきたときに、あなたは改宗者になります。 MVVM(および一般的なパターン)を使用すると、実際には独自のコードに従い、数週間または数か月ではなく、最悪でも数時間または数日で要件を満たすことができます。 (この変更は、新しい機能を追加しようとする前に最初に何をしたかを理解しようとして数週間を費やすのではなく、ほんの数行のコードである可能性があります。)
フォローアップ:パターンとベストプラクティスは、実際には初期開発を遅くします。これは多くの場合、管理とエンジニアリングの両方にとって難しい売りです。投資回収(ビジネス用語でのROI)は、実際に保守可能で、スケーラブルで拡張可能な、適切に構造化されたコードを持つことからもたらされます。
例として、MVVMを適切に使用すれば、データ全体やビジネスロジックに影響を与えることなく、ビュー全体をスワップアウトするなど、表示ロジックに大幅な変更を加えることができます。
考えモデルにデータセットを使用することについて:(私も実際にこれにfallしています)。問題は、データ項目を識別する方法にあります。データは行と列に格納されるため、列名またはインデックスで検索を実行する必要があり、特定の行をフィルタリングする必要があります。これらのロジックは、アプリケーションのワイヤリングロジックでマジックストリングとマジックナンバーを使用する必要があることを意味します。型指定されたデータセットを使用すると、この問題の一部が軽減されますが、完全ではありません。型指定されたデータセットを使用すると、MVVMから離れ、UIとデータソース間のより緊密な結合に移行することになります。
GUIとプログラムロジックを分離するのに役立ちます。それらを混合すると、特にプロジェクトが時間とともに成長する場合に、アプリケーションの保守が非常に難しくなる可能性があります。
ここ から:
開発者として、Model-View-ViewModelパターンを気にする必要があるのはなぜですか?このパターンがWPFとSilverlight開発の両方にもたらす多くの利点があります。先に進む前に、次のことを自問してください。
- プロジェクトをデザイナーと共有する必要がありますか?また、設計作業と開発作業をほぼ同時に行う柔軟性が必要ですか?
- ソリューションの徹底した単体テストが必要ですか?
- 組織内のプロジェクト内およびプロジェクト間で再利用可能なコンポーネントを使用することは重要ですか?
- コードベースの他のロジックをリファクタリングすることなく、ユーザーインターフェイスを変更できる柔軟性が必要ですか?
これらの質問のいずれかに「はい」と答えた場合、これらはMVVMモデルを使用してプロジェクトにもたらすメリットのほんの一部です。
MVVMをアプリケーションの構造化に自然な方法にするWPF(およびSilverlight 2)機能に加えて、ViewModelクラスはユニットテストが簡単であるため、このパターンも人気があります。アプリケーションの対話ロジックがViewModelクラスのセットに存在する場合、テストするコードを簡単に作成できます。ある意味では、ビューとユニットテストは、2つの異なるタイプのViewModelコンシューマにすぎません。アプリケーションのViewModelsのテストスイートを使用すると、無料で高速な回帰テストが提供され、長期にわたるアプリケーションの維持コストを削減できます。
私にとって、これがMVVMを使用する最も重要な理由です。
以前は、ビューとビューモデルを一緒にマッシュアップするコントロールがありました。ただし、ビューには基本的に入力としてマウスイベントとキーボードイベントがあり、出力としてピクセルが描画されます。そのようなものをどのようにユニットテストしますか? MVVMは、テスト不可能なビューをテスト可能なビューモデルから分離し、ビューレイヤーを可能な限り薄くするため、この問題を解消します。
私はまだ自分自身でこのパターンを理解していますが、価値があると思います。現時点での最大の課題は、アプローチがまだ非常に新しく、したがって多くの混乱があり、パターンの特定の主要なコンポーネントがまだ実装するのが難しいことです。パターンのよりクリーンな実装を作成するのに非常に役立ついくつかのことを発見しました:
Josh Smithの MVVM Foundation のRelayCommandを多用しています。これにより、コマンドを介したViewからViewModelへのバインディングがよりクリーンになります。
AOPを使用して、INotifyPropertyChangedの実装の苦痛を緩和します。現在、Postsharpを使用していますが、これを実行できるツールは他にもあると思います。もしこれを発見していなかったら、手作業で実装する定型コードが本当に私を悩ませていたので、たぶんあきらめていたでしょう。
ソフトウェアの実装方法に対するアプローチを逆にする必要がありました。すべてのミニオンに何をすべきかを指示する独裁者クラスを持つ代わりに、ミニオンを使用すると、私のソフトウェアは次のような疎結合サービスの問題になります。
これは私が行う方法を知っていることです
これらは私がしなければならないことです
このようにコードを構造化し、依存関係を簡単に結び付けるツールを使用し始めると(選択できる幅広いIoCフレームワークがあります)、MVVMの扱いにくい部分が緩和されることがわかりました。モデルをViewModelsに挿入し、ViewModelsが使用するさまざまなView Services(ファイルダイアログの表示など)を見つけることに関連する定型コードを減らすことができます。
この異なるアプローチを習得することは大きな投資であり、実装の主要な変化と同様に、最初に使用を開始したときの生産性ははるかに低くなります。しかし、トンネルの終わりに光が見え始めており、厄介な詳細を習得すると、アプリケーションはよりクリーンで保守性が向上すると考えています。
Postsharpを介してINotifyPropertyChangedに関する質問に対処するには、例 here に基づくアスペクトを使用します。私は自分の使用のために少しカスタマイズしましたが、それはあなたにそれの要点を与えます。これにより、クラス[NotifyPropertyChanged]にタグを付けるだけで、すべてのパブリックプロパティのセッターにパターンが実装されます(自動プロパティセッターであっても)。クラスにINotifyPropertyChangedを実装させるのに時間をかけるかどうかを心配する必要がなくなったので、私はずっときれいに感じました。属性を追加するだけで完了です。
このMVVMの概要をお読みください 記事
2005年、現在マイクロソフトのWPFおよびSilverlightアーキテクトの1人であるジョンゴスマンは、ブログでModel-View-ViewModel(MVVM)パターンを発表しました。 MVVMは、両方のパターンがビューの状態と動作を含むビューの抽象化を特徴とするという点で、ファウラーのプレゼンテーションモデルと同一です。ファウラーは、UIプラットフォームに依存しないビューの抽象化を作成する手段としてプレゼンテーションモデルを導入しました。一方、ゴスマンは、ユーザーインターフェイスの作成を簡素化するWPFのコア機能を活用する標準化された方法としてMVVMを導入しました。その意味で、MVVMはより一般的なPMパターンの特殊化であり、WPFおよびSilverlightプラットフォーム用にカスタマイズされていると考えています。
..
MVPのプレゼンターとは異なり、ViewModelはビューへの参照を必要としません。ビューは、ViewModelのプロパティにバインドし、ViewModelは、モデルオブジェクトに含まれるデータおよびビューに固有の他の状態を公開します。 ViewModelオブジェクトはビューのDataContextとして設定されるため、viewとViewModelの間のバインディングは簡単に構築できます。 ViewModelのプロパティ値が変更されると、それらの新しい値はデータバインディングを介してビューに自動的に伝播します。ユーザーがビュー内のボタンをクリックすると、ViewModelのコマンドが実行され、要求されたアクションが実行されます。 ViewModelは、Viewではなく、モデルデータに加えられたすべての変更を実行します。ビュークラスは、モデルクラスが存在することを認識しませんが、ViewModelとモデルはビューを認識しません。実際、モデルはViewModelとビューが存在するという事実を完全に無視しています。これは非常に疎結合の設計であり、すぐにわかるように、多くの点で利益をもたらします。
また、記事ではこれらのGUIパターンを使用する理由について説明しています。
単純な「Hello、World!」でデザインパターンを使用する必要はなく、逆効果です。プログラム。有能な開発者であれば、数行のコードを一目で理解できます。ただし、プログラムの機能の数が増えると、それに応じてコードの行数と可動部分が増えます。最終的に、システムの複雑さ、およびシステムに含まれる繰り返し発生する問題により、開発者は、理解、議論、拡張、トラブルシューティングが容易になるようにコードを整理するようになります。ソースコード内の特定のエンティティに既知の名前を適用することにより、複雑なシステムの認知的混乱を軽減します。システムでの機能的な役割を考慮して、コードに適用する名前を決定します。
開発者は、パターンを有機的に出現させるのではなく、設計パターンに従ってコードを意図的に構造化することがよくあります。どちらのアプローチにも問題はありませんが、この記事では、MVVMをWPFアプリケーションのアーキテクチャとして明示的に使用することの利点を調べます。特定のクラスの名前には、クラスがビューの抽象化である場合に「ViewModel」で終わるなど、MVVMパターンの既知の用語が含まれます。このアプローチは、前述の認知的混乱を回避するのに役立ちます。代わりに、制御されたカオスの状態に喜んで存在することができます。これは、ほとんどのプロフェッショナルなソフトウェア開発プロジェクトの自然な状態です!
MVVMには多くの優れた点がありますが、おそらく最も重要なことは、コードをテストできることです(ViewModelをテストするユニット)。
ビューとビューモデルの間の接続の欠如は、疎結合を実際に助けます。コーディングしたコンポーネントの再利用が非常に簡単になります。
MVVMを使用すると、鉱石コードを書くことで肩に負担がかかることに同意しますが、あなたがプログラムを設計できるように、そして他の人があなたのためにコーディングできるように、すべてが孤立している明るい面を見てくださいMVVMを使用しない場合、特に大規模なエンタープライズアプリケーションでメンテナンス可能な環境がどのように維持されるかを確認してください。そうすれば、メンテナンスがほとんど不要になります。..私自身はERPソリューションを開発するときに使用しましたその分離レベルのため、メンテナンスは非常に簡単です
他の人が投稿したすべての理由でMVVMのようなパターンを使用すれば、長期的には満足するでしょう。単語ごとのパターン要件に従う必要はありません。ウィンドウ(ビュー)とロジック(コードビハインド)が十分に分離されていることを確認してください。
MVVMは本当に過剰なコードです。
MVVMにはどのような利点がありますか?
それはただ懸念の分離それ以上ではない。 ViewModelロジックをコントローラーに書き込むこともできます。 ViewModelは、変換(たとえば、オブジェクトの文字列への変換)を行うために適切です。 MVVMを使用すると、よりオブジェクト指向のプログラミングスタイルを使用できます。変換ロジックをコントローラーに書き込むことにより、より機能的なプログラミングスタイルを使用できます。
そのため、読みやすいコードを多く持つか、大きなコントローラーファイルでコードを少なくすることになります。結論として、MVVMを使用する必要があると言うことはできません。MVVMよりも優れているため、個人的な好みにすぎません。
コントローラーについて言及する理由を明確にするために、MVVMにはコントローラーコードもどこかにあります。 Cを離れるのに幅広いコンセンサスがある理由はわかりません。
MVVMの利点
それが役に立てば幸い。