偶然にも、MVCを模したWinFormsプロジェクトに取り組んでいます。これを完璧な答えとは言いませんが、全体的な設計について説明します。
このプロジェクトを開始する前に読んだことから、これを実装する「正しい」方法はないようです。単純なOOPとMVCの設計原則に従いましたが、残りは試行錯誤でワークフローを開発しました。
MVCはこのユースケースにとって単に不適切なアーキテクチャですか?
いいえ ..?あなたの質問には、それに対する直接的な答えを提供するのに十分な文脈がありません。そもそもMVCを使用しているのはなぜですか?プロジェクトの非機能要件は何ですか?あなたのプロジェクトは非常にUIが重いですか?セキュリティにもっと関心があり、むしろ階層化アーキテクチャが必要ですか?プロジェクトの主なコンポーネントは何ですか?おそらく、各コンポーネントには異なる設計パターンが必要です。そもそもこのデザインパターンを使用する理由を見つけてください。そうすれば、自分の質問に答えられるかもしれません;)
MVCを使用する理由:私の意見で理解するのはかなり単純なデザインパターンであり、私のデザインはユーザーの操作に大きく基づいています。MVCで開発者が懸念を分離できるようにする方法は、私のアプリケーションでも十分です。これにより、コードの保守性とテスト性が向上します。
また、私はより多くのハイブリッド設計を使用していると思います。通常、ソフトウェアエンジニアリングで提示される理想的な概念は、実際には実際には機能しません。プロジェクトのニーズに合わせて設計を変更できます。善悪に巻き込まれる必要はありません。一般的な慣行はありますが、自分で足を撃たない限り、ルールは常に曲がったり壊れたりすることがあります。
私の実装は、必要なコンポーネントについてのアイデアを与えてくれた高レベルの設計から始まりました。この方法で開始し、アーキテクチャ内で作業を進めることが最善です。プロジェクトのパッケージ図は次のとおりです(StarUMLで作成):
プレゼンテーションレイヤーを除くすべてのレイヤーがメッセージングシステムに依存していることに注意してください。これは、下位層とそれらの層のサブシステムが互いに通信するために使用する一般的な「言語」です。私の場合、実行可能な操作に基づいた単純な列挙でした。それは次のポイントに私をもたらします...
操作またはコマンドを実装の基礎と考えてください。アプリケーションで何をしたいですか?最も基本的な操作に分けてください。例:CreateProject、WriteNotes、SaveProject、LoadProjectなど。GUI(またはフォームクラス)で何らかのイベント(ボタンを押すなど)が発生します。すべての操作には、コントローラメソッドが関連付けられています。この場合、Exitのようなものは単純すぎます。アプリケーションは、Formクラスから単純に閉じることができます。しかし、最初にいくつかのアプリケーションデータをファイルに保存したいとしますか?ボタンを押すメソッド内で、それぞれのコントローラークラスから「保存」メソッドを呼び出します。
そこから、コントローラーはサービスクラスから正しい操作セットを呼び出します。アプリケーションのサービスクラスは、ドメインレイヤーへのインターフェイスとして機能します。コントローラのメソッド呼び出し(およびGUI)から受け取った入力を検証し、データモデルを操作します。
検証と対応するオブジェクトの操作が完了すると、サービスメソッドはメッセージコードをコントローラーに返します。たとえば、MessageCodes.SaveSuccess
。コントローラクラスとサービスクラスの両方は、ドメインオブジェクトおよび/またはグループ化できる一般的な操作のセットに基づいていました。
例:(FileMenuController
操作:NewProject、SaveProject、LoadProject)-> ProjectServices
(CreateProject、PersistProjectToFile、LoadProjectFromFile)。Project
データモデル内のドメインクラスはどこにありますか。私の場合、コントローラークラスとサービスクラスは、静的メソッドを持つインスタンス化不可能なクラスでした。
次に、コントローラーは、操作が完了しない/成功したと認識します。現在、コントローラーには、プレゼンテーション層と対話するために使用する独自のメッセージングシステムがあるため、サービス層とプレゼンテーション層の間の二重の依存関係があります。この場合ViewState
、ViewModels
パッケージで呼び出されたクラスは常にコントローラーによってGUIに返されます。この状態には、「アプリケーションを有効にしようとした状態は?」、「実行しようとした操作に関する人間が読めるメッセージと、成功または失敗した理由(エラーメッセージ)」およびViewModel
クラスなどの情報が含まれます。
このViewModel
クラスには、GUIがビューの更新に使用するドメインレイヤーからの関連データが含まれています。これらのビューモデルはドメインクラスのように見えますが、私の場合は非常に細いオブジェクトを使用しました。基本的に、それらにはほとんど動作がなく、アプリケーションの下位レベルの状態に関する情報を中継するだけです。つまり、ドメインクラスをプレゼンテーション層に渡すことは決してありません。これはまた、Controllers
とServices
パッケージがサービスレイヤーを2つの部分に分割する理由でもあります。コントローラは、ドメインクラスを処理したり、状態を検証したりすることはありません。それらは、GUI関連データをサービスが使用できるドメイン関連データに変換する境界として機能し、逆もまた同様です。コントローラにサービスロジックを含めると、非常に太くなる 保守が難しいコントローラー。
これが出発点になることを願っています。