MVCでサービスレイヤーを使用する


12

コントローラーが太りすぎて、モデルのインスタンス化が増え始めると、サービスレイヤーを使用できます。

  • サービスクラス内にロジックをラップするだけの場合、1つまたは2つのメソッドで多数のサービスを取得します。これはコード臭のように感じます。これに関するベストプラクティスはありますか?

  • サービスはモデルをインスタンス化できますか?

  • サービスがモデルをインスタンス化する場合、サービスを単体テストすることはできません。それらは統合テストでのみカバーできますか?

回答:


23

「SOLID」では、「I」はInterface Segregationの略です。この原則の全体的な考え方は、大きなインターフェイスを小さなインターフェイスに分割し、よりモジュール化することです。MVCでは、通常、サービスにはコントローラーが依存するインターフェイスがあります。コントローラーにそのサービスの具体的な実装について知らせて欲しくありません。したがって、1つまたは2つの方法を備えた多数のサービスを用意することをお勧めします。

通常、サービスは大規模なアプリケーションのDTOまたは小規模なアプリケーションのドメインモデルを直接返します。DTOは通常、より多くの作業を意味しますが、懸念事項の分離は改善されます。典型的なフローは次のとおりです。

  • コントローラー呼び出しサービス
  • サービスはオブジェクト(DTO、ドメインモデルなど)を返します
  • コントローラーはDTO /ドメインモデルをビューモデルにマップします

マッピングは手動で行うことができますが、ほとんどの開発者は配管コードを書くのが好きではなく、とても怠け者になる可能性があるため、Automapperなどの自動マッピングフレームワークを使用することを好みます。

http://en.wikipedia.org/wiki/Interface_segregation_principle

https://github.com/AutoMapper/AutoMapper

DTOおよびドメインモデルの使用に関するstackoverflowに関する多くの議論の1つ:https ://stackoverflow.com/questions/2680071/dto-or-domain-model-object-in-the-view-layer


1
ここで自動マッパーの使用には注意が必要ですuglybugger.org/software/post/…–
ダニエルリトル

AutoMapperには、すべてのマッピングルーチンを1行で検証できる組み込みのユニットテスト機能が付属しています。この投稿の著者はそれについて言及しませんでした。
CodeART

しかし、彼はそれについて知っていて、それを使いました。コメントはこれに少し入ります。
ダニエルリトル14年

2
通常、1つまたは2つのメソッドしか持たない多くのクラスは、凝集性がないことを意味します。サービス層は、存在する場合、モデル内にあるロジックの大部分とともに薄くする必要があります。ビューをプロパティバッグに過ぎないダムオブジェクトにバインドするのは、かなり無意味に思えます。MVCのモデルは、貧弱なモデルではなく、リッチドメインモデルである必要がありますmartinfowler.com/bliki/AnemicDomainModel.html
Andy

3

コントローラーにはモデルへの呼び出し(ビジネスロジックが発生する場所)のみを含める必要があり、それらの呼び出しに基づいてビューのデータ(情報またはエラーメッセージのオブジェクト)を割り当てるため、コントローラーがまだ非常に複雑なページであってもコントローラーは非常に小さくなります非常に大きくなった場合、おそらくそのページをより多くのページに展開する必要があると考える必要があります。

それでもモデルはかなり大きくなる可能性があります...私が見つけた解決策は、どのモデルをロードするか、特定のモデルをロードする特定のタスクを伝える変数をコントローラー内に持っていました。

次のようにmodel-view-controllerモデルをきれいにしてください:

  • ビュー:データを表示します
  • コントローラー:ユーザー入力を収集し、要求されたデータをモデルに要求し、ビューに送り返します
  • モデル:データベースと対話し、論理アクションを実行して情報を準備します

2

MVCでは、モデルは単にDTOまたはマネージャー/サービスのセットではなく、アプリケーションがモデリングしている概念を表すことを目的としています。これは、ドメイン全体または状態や動作を含むビジネスロジックと考えることができます。これで、コントローラーの目的が少し明確になることがわかったと仮定します。仕事は、コマンドをモデルに変換し、結果をビューに戻すことです。これは通常、ViewModelの形式で行われますが、ViewModelは異なりますが、MVCのモデルと混同されることがよくあります。

適切に定義されたモデルがない場合は、そのロジックのほとんどがコントローラー自体に存在するようになっている可能性があります。この時点で、コントローラーのサイズの縮小を開始するために、このロジックをマネージャーまたはサービスオブジェクトに戻すことができます。これらのサービスは、通常、オブジェクトのようなDTO /エンティティで返されて動作します。次に、コントローラーがこれらのサービスとビューモデルの間のマッピングレイヤーになります。マッピングに関するいくつかの良いヒントについては、この記事を参照してください。友人はAutoMapperを友人に使用させません

質問に関しては、最初の質問はアプリケーションに大きく依存します。コントローラーからロジックを削除したら、より明確になるように、リファクタリングを行う必要があります。テストに関しては、サービス内でモデルをインスタンス化するのに問題はありませんが、テストが困難であることがわかった場合は、おそらく、1つの責任でサービスを小さな部分に分割する必要があるだけです。


-1

複数のコントローラーで実行する必要があるかもしれないロジックや、コントローラーが大きくなり読みにくくなるのを防ぐという事実に加えて、コントローラーの一部として十分に具体的ではないロジックを実行するのにサービスが本当に役立つと思います。 。

私は個人的には「aaa」に「モデル(ビジネスロジックが発生する場所)」と言っていることに同意しません。なぜなら、それがコントローラーを持っている理由であるからです。繰り返しますが、サービスはデータ抽象化タスクに関与すべきではありません...

ただ言って...


1
あなたのモデルはちょうどある場合は、貧血のドメインモデルアンチパターンに陥ってきたDTO martinfowler.com/bliki/AnemicDomainModel.html
アンディ・
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.