質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
MVC

MVC(Model View Controller)は、オブジェクト指向プログラミングにおけるモデル・ビュー・コントローラーの総称であり、ソフトフェア開発で使われている構築パターンとしても呼ばれます。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

Q&A

解決済

3回答

29097閲覧

【MVC】コントローラとサービスの切り分け

HelloWorld2

総合スコア32

MVC

MVC(Model View Controller)は、オブジェクト指向プログラミングにおけるモデル・ビュー・コントローラーの総称であり、ソフトフェア開発で使われている構築パターンとしても呼ばれます。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

0グッド

0クリップ

投稿2019/08/23 02:12

編集2019/08/23 02:14

わからないこと

  • ControllerとServiceの切り分けが分かりません。
  • 下記に簡単な例を示しましたので、どの方法がベストか、他の方法が良いか、ご教示いただきたいです。
  • (そもそもRepositoryを直接コントローラから実行するのって普通ですか?Serviceを経由する必要はないですか?)

処理概要(細かいところは省きます)

  1. テーブルaのデータを取得
  2. 取得できなかったら処理終了
  3. テーブルbのデータ取得
  4. DTOにaとbのデータをセット

コード

※現在springを使用しているため、javaおよびspringで記載します。

パターン1:全部Serviceで処理(同一のDTOを構成する処理はまとめるという思想、ただ関連テーブルが増えるとserviceのメソッド内の処理が膨大になります・・・)

Java

1@Controller 2public Class hogeController{ 3 public hogeDto search(){ 4 return hogeService.getDto(); 5 } 6} 7 8@Service 9public Class hogeService{ 10 public hogeDto getDto(){ 11 aEntity = aRepogitory.findOne(1); 12 if( aEntity == null ){ 13 return null; 14 } 15 bEntity = bRepogitory.findOne(1); 16 17 hogeDto.setHoge(aEntity.hoge); 18 hogeDto.setFuge(bEntity.fuga); 19 20 return hogeDto; 21 } 22}

パターン2:全部Controllerで処理(多分この程度の処理なら許容されそうですけど、もっと膨大になったらだめですよね・・・?)

Java

1@Controller 2public Class hogeController{ 3 public hogeDto search(){ 4 aEntity = aRepogitory.findOne(1); 5 if( aEntity == null ){ 6 return null; 7 } 8 bEntity = bRepogitory.findOne(1); 9 10 hogeDto.setHoge(aEntity.hoge); 11 hogeDto.setFuge(bEntity.fuga); 12 13 return hogeDto; 14 } 15}

パターン3:値のセットはControllerで処理、後はServiceで実装(データ操作はすべてServiceを経由、データ操作に不随してロジックもついてたらこれですかね・・・・?)

Java

1@Controller 2public Class hogeController{ 3 public hogeDto search(){ 4 aEntity = hogeService.getA(); 5 if( aEntity == null ){ 6 return null; 7 } 8 bEntity = hogeService.getB() 9 hogeDto.setHoge(aEntity.hoge); 10 hogeDto.setFuge(bEntity.fuga); 11 return hogeDto; 12 } 13} 14 15@Service 16public Class hogeService{ 17 public hogeDto getA(){ 18 aEntity = aRepogitory.findOne(1); 19 if( aEntity == null ){ 20 return null; 21 } 22 23 return aEntity; 24 } 25 26 public hogeDto getB(){ 27 return bRepogitory.findOne(1); 28 } 29}

どうあるべきか、ご意見お聞かせいただけたら幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

MVCというよりSpringMVCについての回答となりますが、
コントローラからServiceクラス(@Serviceアノテーション付加)のメソッドを呼び出した際にトランザクションが開始されますので、
トランザクション管理したいものをServiceクラスに実装し、不要なものはコントローラ層で実装すればよいです。

1.テーブルaのデータを取得
3.テーブルbのデータ取得

とありますが、これは同一トランザクションで取得すべき内容でしたら
両方とも同一Serviceクラス(の同一メソッド)内に記載すべきです。
※SharedServiceを利用して分割する方法もありますが割愛します

以下が参考になるかと。
http://terasolunaorg.github.io/guideline/5.5.1.RELEASE/ja/ImplementationAtEachLayer/DomainLayer.html

投稿2019/08/24 04:50

編集2019/08/24 04:52
horz

総合スコア21

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

とのことですが、基本形・理想形はどういった形式で、どういう状況で変化するのでしょうか?

理想形かどうかはわかりませんが、一つの指針ならあげられますので参考にしてみてください。

各クラスの役割

  • コントローラークラス

画面からのイベントを受け取ってサービスを呼び出す

  • サービスクラス

リポジトリを呼び出してデータの取得、ドメインクラスを呼び出す

  • ドメインクラス

業務のデータの保持と、ルールを記載するクラス
リポジトリは呼び出さずに業務ルールだけに専念する

流れ

サービスは言い換えるとユースケースと言えます。
例えば自動販売機でジュースを買う場合、以下のように考えられます。

  • コントローラ

「自販機のボタンを押す」というイベントをうけて
自販機サービスの「ジュースを買う」を呼びだす

  • サービス

ジュースの情報(ドメイン)を取得

  • ドメイン

金額やジュースの残量、冷え具合などの状態を持っているので、
「まだジュースは残ってるか?」
「冷えて出せる状態か?」
「投入されたお金は本物か?」
「金額は足りてるか?」
などのルールを判定する
また、ルールには判定だけじゃなくて、このジュースの場合は
シールをつけるみたいな業務ルールのロジックも組み込みます
※自販機ではそういうことはないですが

  • サービス

ドメインのルール判定の結果、問題なければコントローラーに結果を返す

  • コントローラー

サービスの結果をもとにジュースを出す

設計方法

作る前に上記のルールを考えておけば、設計段階で

  • 画面からのイベント
  • ユースケース
  • 業務ルール

以上を押さえた資料を作成すればバックエンドのプログラムは作れると思います。

その他

サービスクラスがオブジェクト指向っぽくなりませんが、
そこは仕方ないと割り切って作ります。
例えば、「自動販売機サービス」なのに持っているメソッドは「ジュースを買う」っておかしな感じになっちゃってます。

投稿2019/08/24 04:36

編集2019/08/24 04:39
msss

総合スコア33

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

プログラミングの世界には「ファットコントローラ」という概念があります。
ファットコントローラ撲滅運動というスライドが作られるくらい、忌み嫌われるものです。

そもそもオブジェクト指向では「役割分担」をきちんとすることが理想とされています。はじめのうちは何でもかんでもコントローラに全て書いてしまいがちです。
ただ、それでは可読性もメンテナンス性も悪くなります。

そのために細かい役割分担をすることで「道具を用意して適宜使う」ような形にするわけですね。
1個軽い道具を作れば他でも使いまわしがききます。

サービスとは・・でいうと使っているフレームワークや言語、もしかしたら現場で概念がちょっとずつ違うかもしれませんが、一般的には下記に現れるようなものと思っていいと思います。

基本はビジネスロジック部分を切り出したもの・・・という理解ですね。
コントローラはあくまでリクエストを受けて、レスポンスを返すだけに終始し、その間の処理部分はサービスに任せる。

どこまでどう切り出すかは状況次第とは思います。
サービスもあまりコントローラに特化したものでないほうが良いとは思います。

投稿2019/08/23 02:26

m.ts10806

総合スコア80850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

HelloWorld2

2019/08/23 08:26

ご回答ありがとうございます。 > どこまでどう切り出すかは状況次第 とのことですが、基本形・理想形はどういった形式で、どういう状況で変化するのでしょうか? > ファットコントローラ パターン2は基本形でないことはわかりました。 また、コントローラから(サービスを経由せず)リポジトリを呼び出すことは問題ないのでしょうか?
m.ts10806

2019/08/23 09:18

デザインパターン で調べてください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問