Closed8
LaravelにおけるServiceとUseCaseの違い

Laravelの開発ではよくMVCが採用される。自分なりの理解としては以下の感じ。
純粋なMVC
- Model: 業務ロジックを持つ、DBとのやり取り、データ構造を持つ
- View: Bladeテンプレートを使用してUIを構成しユーザーとのやり取りを行う
- Controller: HTTPリクエストを受取り、ModelとViewと連携する

しかしMVCのみでは各層の責務が肥大化しやすいため、ServiceやRepositoryが追加で実装される。
Service
Modelから業務ロジックを分離する。Modelの役割をDB操作やアプリケーションで使用するデータ構造の管理に専念させる。Serviceには業務ロジックを実装しControllerから呼び出す形にする。
Repository
ModelからDB操作を分離する。DB操作(データアクセス処理)を抽象化し、業務ロジックと永続化を分離させる。
- 業務ロジックがDB操作の具体的な実装に依存しなくなる
- 特定の仕組み(Eloquent, QueryBuilder等)に依存する必要がなくなるので、保守性向上

Serviceに似たものでUseCaseがあるが、これらの役割の違いが分からなかった。と言うより、言葉が違うだけで同じものだと思ってた。厳密な違いを確認しておきたい。

そもそもService, UseCase, RepositoryはDDD、クリーンアーキテクチャ、デザインパターンの思想であり、Laravelに限ったことではないと思う。DDDやクリーンアーキテクチャの話に広げると長いので、とりあえずServiceとUseCaseの違いについてまとめることにする。

AIに聞いたり、調べた感じの自分なりの解釈としては、
UseCase
- 単一のユースケース(登録処理、支払い処理...)をカプセル化する
- 誰が何のためにどういったことをするのか意識した粒度
- 低い抽象度、再利用性が低い
- 他のUseCaseと独立した実装になりやすい
- Controllerと一対一対応
- 1つのUseCaseクラスが1つの関数をもつ
Service
- 複数のユースケースでの使用を想定した共通処理でカプセル化する
- 高い抽象度、再利用性が高い
- Controllerは複数のServiceを呼び出す
- 1つのServiceクラスは複数の関数を持つ

ControllerとServiceの間にUseCaseを入れると、Controllerは責務が明確になりそう。一方でレイヤーを増やすことで実装/保守のコストが上昇することにつながる。

UseCaseを間に挟むとControllerで手続き的な処理を記述する必要がなくなるのでControllerの肥大化を防げる。
// Service
class UserController {
function login() {
$isExist = $userService->isExistAccount();
if($isExist) {
$userService->login();
}
}
}
// UseCase
class UserController {
function login() {
$userLoginUseCase->execute();
}
}

ただ大規模なアプリケーションでない限り、UseCaseは必要以上なレイヤーだと思う。
このスクラップは16日前にクローズされました