

サービスの役割について教えて下さい。

CakePHPでMVCを学んだのですが、CakePHPにはサービスというものがないのでどういう役割なのかがわかりません。

コントローラはユーザからの要求に対して必要な処理を抽出し、  
ビューは結果などを伝えるために表示するもの、  
モデルはコントローラから要求される処理をまとめておくものだと認識しています。  
(間違っていますでしょうか)

最近サービスという概念があることを知ったのですが、これはモデルの中に更に分けられるものなのでしょうか。それともモデルのことを言ってるのでしょうか?

わかりやすくサービスというものについて教えていただけると嬉しいです。


CC BY-SA 3.0
2015-01-10T05:10:55.957
4360
2015-01-13T08:39:09.320
2015-01-10T15:40:31.387
33
5855
question
cakephp mvc
MVCモデルにおけるサービスの役割について教えて下さい


WebアプリでのMVCでは通常コントローラー/アクションが特定のURLパターン、モデルがDBのテーブルという物理的な意味を持っています。

要件によってはアクションから一括更新や分割検索など複雑なモデル操作が必要になる場合がありますが、これをコントローラーやモデルに記述するのは行儀が良くないということでコントローラーとモデルの間にサービス層を挟み、データ上有効なモデル操作の単位で分割してサービスのメソッドを実装します。

> モデルはコントローラから要求される処理をまとめておくものだと認識しています。

という認識なら、モデルを単純なSQLに対応する部分とSQLを組み合わせたロジック部分に分割したロジック側がサービスということになるかと思います。

MVC以外のアーキテクチャでは[ビジネスロジック](https://ja.wikipedia.org/wiki/%E3%83%93%E3%82%B8%E3%83%8D%E3%82%B9%E3%83%AD%E3%82%B8%E3%83%83%E3%82%AF)と呼ばれることが多いです。


CC BY-SA 3.0
2015-01-11T03:52:25.257
4392
2015-01-11T12:33:46.250
2015-01-11T12:33:46.250
5750
5750
4360
answer


質問に単純に回答するならばCakePHPではComponentがService層に該当します。

自分も同じ疑問に当たった際にCakePHPコア開発者のJoseが書いた下記のエントリに行き当たりました。

  * <http://josediazgonzalez.com/2013/12/06/building-service-classes/>

MVCモデルとサービス層を明確に分ける定義は無いですが、CakePHPにおいてはComponentとして実装するのがすっきりします。  
おおまかにいうと下記のような形になります。

  * Modelは個別のテーブルに対するORマッパとしてシンプルに使う。
  * Modelに実装するメソッドは個別のモデルに対するカスタムファインダなど。(Whereをいちいち指定しないでいいようにするショートカット的に使う。 FindLatest() のような
  * Componetには複数のモデルを順番に呼ぶなどのハイレベルな処理を実装し、コントローラーへのAPIを提供する。 (RegisterUser のようなメソッドの中から操作が必要なテーブルモデルの呼出やWEBAPIなどの操作、メールなどDBの限定されない処理をまとめる。)

ただし、これについては反証もありえます。

  * Modelはデータベースのテーブルに対応しない形でも作成可能。 (useTable = false)
  * Modelでその他のモデルを扱う処理をまとめてService的にもできる。
  * ModelをORマッパしかできないと捉えるのは間違いであるとよく言われている。

結局のところ裁量でしかありませんが、Componentとして実装する事でWebAPIやセッションなどのコントローラー関係の処理も行いやすいですし、ModelをテーブルへのDAOに限定して使うというのはそれなりに理解しやすいと思います。

またCakePHP3ではModelはTableクラスとEntityクラスに分離されました。  
これによりDAO部分と論理的な処理をModel配下でも分離はしやすくなるでしょう。


CC BY-SA 3.0
2015-01-12T10:16:41.637
4432
2015-01-13T06:49:01.923
2015-01-13T06:49:01.923
452
452
4360
answer


CakePHPという、1つのフレームワークの中での、1つのとらえ方については
他の方の回答が参考になると思いますが、一歩引いて一般的に`MVC`と`サービス`というのがどういう関係にあるのか、それぞれの言葉の意味という点で回答します。

質問ではMVCについて、次のように書かれています。

> コントローラはユーザからの要求に対して必要な処理を抽出し、  
>  ビューは結果などを伝えるために表示するもの、  
>  モデルはコントローラから要求される処理をまとめておくものだと認識しています。

この分類はそんなに間違っているということはありません。しかし、実際「コントローラから要求される処理」にはいろいろな種類のものがあります。たとえば、

  * DBに情報を保存する／DBから情報を取得する
  * メールを送信する
  * アップロードされた画像ファイルのサムネイルを作成する

があります。これらの何がモデルで、何がビジネスロジックで、何がサービスなのか、パッと分からないですよね。言葉を整理しましょう。

## モデルとは？

一般的に「モデル」というのは、`仕組みや構造を分かりやすく表したもの`を指します。業務のためのシステムであれば、その業務で扱っている「情報の構造」だったり、「情報の作り方のルール」「手順」だったりします。

### CakePHPのModelは？

CakePHPのModelの場合、データベースのスキーマを自動的に読み取って、そのテーブルのレコードを簡単に扱えるようになっているため、一見Modelの役割が「DB入出力のためのコード置き場」のように見えてしまいます。しかし、このようなActiveRecordの本来の目的は、アプリケーションコードから、`情報の形`
を統一した形式で扱えるようにする点にあります。

他のMVC系のフレームワークでも、Modelと名付けられている部分には、このように「情報の形」を表現するという目的が与えられています。この情報の形に付随する処理（情報の入出力や、形の整合性のチェック、形の多少の変形・合成）は、Modelに記述するということになるでしょう。

### ルールや手順は？

最初に挙げた例のうち、ルールや手順といったものもありました。これらはModel、つまり情報の形に付随するものなのでしょうか？

良くある例としては、例えば会員が商品を購入する時の手続き（手順）があります。会員ごとの購入限度額をチェックし、その後在庫をチェックする、といった具合です。何らかの手順の中で、複数の情報のカタマリを横断して扱わなくてはなりません。

「複数のものを扱う」という基準でModelに記述していたものを何らかの別の形に切り出す、という方策もありますが、より正しくは、「手順＝ユースケースを表わす部分を独立させる」ということになります。これが、次に説明するサービスの使い方の1つの形です。

## サービスとは？

サービスというのは、`処理をするモノ`のことです。

たとえば、アプリケーションでユーザーのパスワードをハッシュ化して記録する場合、そのハッシュ化処理を1つのクラスに独立させたとしましょう。このクラスは「PasswordEncoderサービス」です。要するに、ライブラリでも何でも、処理を提供するクラスはサービスだと言ってしまえます。また、このPasswordEncoderサービスは、ユーザーの情報を保存する時に、Modelの内部で利用されることもあれば、他の理由でControllerから使われることもあり得ます。

### サービスを利用する場面

サービスをどう使うのかという点では、先ほどのPasswordEncoderでもそうでしたが、いくつか考えられます

  * Controllerに記述していた共通処理を何かの観点でまとめるのに使う
  * Modelに記述していた共通処理を何らかの観点でまとめるのに使う
  * テンプレートのために必要な共通処理を何らかの観点でまとめるのに使う

Controllerの共通処理のためには、Controllerの基底クラスを作り、そこに共通メソッドを作るという方法もありますが、これはあまり良い方法ではありません。個々のControllerからコードが減る代わりに、基底クラス側に複雑性が集中してしまったりします。

「サービス」というものを直接扱えるフレームワークであれば、単に個々の処理に対応するクラスを作り、必要な箇所で利用できうようにフレームワークに指示する、という共通した手順で使えます（例えばSymfonyのサービスコンテナ）。CakePHPの場合は、使う箇所によってヘルパーだったり、と個別の仕組みが用意されていたりしますが、そういったものを超えて、自分で作ったクラスを使えるようにすれば、いろいろと対応の幅が広がります。

  * [CakePHPにDIコンテナを統合してサービスを扱いやすくした例](http://blog.yagni.jp/archives/419)

### サービスはModelなのか？

前節のように、MVCのパーツのどの部分の処理でも、それをサービスにまとめることは可能です。サービスというのは、単なる「処理を提供するもの」だからです。この意味で、サービスというのは、ModelだとかControllerだとか、そういった構造とは基本的に関係のないものということになります。

### サービスレイヤー（ユースケースレイヤー）

  * ControllerとModelの間に挟んで、Modelの操作をまとめる層のように使う

という使い方もあります。これは部品として使うというよりも、MVCというアーキテクチャ（作り方）に構造を追加するという目的になります。専門的な言葉では、サービスレイヤー、またはユースケースレイヤーと呼ばれます。こういった作り方で、プロダクションコードの見通しを良くすることができます。

## マイクロサービス？

昨今話題になる「マイクロサービス」という言葉で表されるサービスは、ここで説明した「1つのクラス」というのよりももっと大きな単位を指しています。例えば1つの企業の中の「会員管理サービス」などを1つのサービスというカタマリで捉えます。

「サービス」という言葉はとても汎用的で、この言葉を基準にして調べても膨大な事柄がでてきてしまいます。なので、`何のために使うのか`という目的から理解されていくのが、よいと思います。

# まとめ

  * サービスというのは単なる処理／クラス
  * MVCの「モデル」とサービスとは、直接的には関係がない
  * 「サービス」は用語として混乱しているので、目的から理解しよう

# 参考情報

  * [PofEAA's Wiki - ServiceLayer](http://capsctrl.que.jp/kdmsnr/wiki/PofEAA/?ServiceLayer)
  * [サービスコンテナ | Symfony2日本語ドキュメント](http://docs.symfony.gr.jp/symfony2/book/service_container.html)
  * [モデルもしくはサービスレイヤーに関する補足 - noopな日々](http://d.hatena.ne.jp/noopable/20100309/1268103347)


CC BY-SA 3.0
2015-01-13T08:39:09.320
4495
2015-01-13T08:39:09.320
5444
4360
answer