コントローラが太りすぎてモデルのインスタンス化が増加し始めた場合、サービス層を使用できます。
ロジックをサービスクラス内にラップするだけで、1つまたは2つのメソッドを備えた一連のサービスを取得できます。これはコードのにおいのように感じます。これに関するベストプラクティスはありますか?
サービスはモデルをインスタンス化できますか?
サービスがモデルをインスタンス化する場合、サービスを単体テストすることはできません。それらは統合テストでのみカバーできますか?
「SOLID」では、「I」はインターフェース分離を表します。この原則の全体的な考え方は、大きなインターフェースをより小さなモジュールに分割し、よりモジュール化することです。 MVCサービスでは通常、コントローラーが依存するインターフェイスがあります。コントローラにそのサービスの具体的な実装について知らせたくありません。したがって、1つまたは2つの方法を備えた一連のサービスを用意することをお勧めします。
サービスは通常、大規模なアプリケーションではDTOを返し、小規模なアプリケーションではドメインモデルを直接返します。 DTOは通常、より多くの作業を必要としますが、関心事の分離が向上します。一般的なフローは次のとおりです。
マッピングは手動で行うことができますが、ほとんどの開発者は、自動コード作成フレームワークを使用することを好みます。
http://en.wikipedia.org/wiki/Interface_segregation_principle
https://github.com/AutoMapper/AutoMapper
DTOとドメインモデルの使用に関するスタックオーバーフローに関する多くの議論の1つ: https://stackoverflow.com/questions/2680071/dto-or-domain-model-object-in-the-view-layer
MVCでは、モデルは単なるDTOや一連のマネージャー/サービスではなく、アプリケーションがモデル化している概念を表すことを目的としています。これは、ドメイン全体または状態と動作を含むビジネスロジックと考えることができます。ここで、コントローラーの目的が少し明確になることがわかったとします。それは単にコマンドをモデルに変換し、結果をビューに戻すことです。これは通常、ViewModelの形式で行われますが、ViewModelは異なりますが、MVCのモデルと混同されることがよくあります。
明確に定義されたモデルがない場合は、そのロジックのほとんどがコントローラー自体に存在するようになっている可能性があります。この時点で、コントローラーのサイズの縮小を開始するために、このロジックをマネージャーまたはサービスオブジェクトに戻し始めることができます。これらのサービスは通常、オブジェクトのようなDTO/Entityを返し、操作します。次に、コントローラーはこれらのサービスとビューモデル間のマッピングレイヤーになります。マッピングに関するいくつかの良いヒントについては、この記事をご覧ください 友達はAutoMapperを使用させません 。
あなたの質問に関しては、最初の質問はあなたのアプリケーションに大きく依存します。コントローラーからロジックを削除すると、より明確になるはずの方法でリファクタリングを行う必要があります。テストに関しては、サービス内のモデルのインスタンス化に問題はありませんが、テストが難しい場合は、おそらく単一の責任でサービスを小さな部分に分割する必要があるという単なる兆候です。
コントローラーには、モデル(ビジネスロジックが発生する場所)への呼び出しのみを含める必要があり、それらの呼び出しに基づいてビュー(情報のオブジェクトまたはエラーメッセージ)にデータを割り当てます。そのため、コントローラーが非常に複雑なページの場合でも、コントローラーは非常に小さくなります。非常に大きくなると、おそらくそのページをさらに多くのページに展開する必要があると考える必要があります。
それでもモデルはかなり大きくなる可能性があります...私が見つけた解決策は、どのモデルをロードするかを指示するコントローラー内の変数を持ち、特定のタスクでは特定のモデルをロードすることでした。
次のように、model-view-controllerモデルのクリーンに従ってください。